场景再现
在一个微服务架构的商城系统中有两个服务:下单服务和库存服务。当我们进行下单的时候,此时会调用库存服务,进行库存的扣减。这种服务间的调用/通信我们之前是用FeignClient以接口式的请求实现的。但是,OpenFeign是以HTTP协议为基础的,默认下是属于同步通信的,调用者会等待被调用者的响应,所以这个过程是阻塞式的。只有两种结果:要么响应,要么超时,必须等到了结果才会进行下一步的逻辑处理。
对于有的操作是必须使用同步调用的,只有得到了响应才能进行下一步的操作,而对于有的是不需要等待响应结果的,就比如上面的库存服务,又或者是一些不那么核心的边缘服务。如果就为了等响应,全部等着,性能就大大下降了。此时就需要使用异步通信了。
MQ(Message Queue)
一种用于在分布式系统(如微服务)中实现异步通信的消息中间件。如RabbitMQ。
核心概念
生产者:也就是发送消息的人(程序,服务)
消费者:接收到消息的人(程序,服务)
队列:存储消息的容器,任何发送过来的消息都会进入这个队列,等待消费者取出
交换机:可以理解为消息路由转发器,它位于生产者和队列之间,进入交换机的消息会根据规则转发到相应的队列。只转发不存储。常用交换机:
FanOut广播模式:将消息转发到所有绑定了这个交换机的队列,等于说对消息进行了N份复制,然后广播给所有人
Direct直连模式:根据路由键(条件)匹配相应的队列,然后消息转发。
绑定:指队列和交换机之间的绑定,多个队列绑定到了同一个交换机才能接收到交换机的消息。至于交换机会把消息转发给哪个队列,取决于绑定的路由键。
路由键:队列和交换机进行绑定的时候,设置一个路由键(标识),当生产者发消息的时候,传递一个路由键,然后交换机会找到具有此路由键标识的队列进行转发。
虚拟主机:可以理解为类似于容器的东西,每个虚拟主机拥有独立的交换机、队列、绑定和权限配置,可以用来隔离应用。
如:用户有两个队列q1,q2,以及交换机exchange1,两个队列都与交换机进行了绑定,并且指定了不同队列的路由键
如果现在发消息,并且指定路由键为test1,那么此时能接收到消息的就只有q1队列了。
异步优点
1,非阻塞
支付服务发送消息后,不会阻塞等待订单状态修改的结果,因此支付服务的调用不会因为消息处理失败而挂起。
2,解耦
支付服务和订单服务解耦了,支付服务只关心是否发送消息,而订单服务负责接收并处理消息。即使订单服务暂时不可用,支付服务也不会受到影响。
3,错误处理
即使消费者处理消息失败(例如订单服务不可用),也不会影响生产者(支付服务)。可以在消费者端设置重试机制或使用死信队列(Dead Letter Queue)来处理失败的消息。
基于注解的方式使用MQ
以支付和交易服务为例,如果支付成功,就调用交易服务,进行订单状态的更改。不使用OpenFeign。
1,引入依赖
此时生产者为支付,消费者为交易,两边都引入依赖
RMQ是基于AMQP协议的,使用Spring提供的依赖简化开发
2,配置RMQ服务的地址等
3,消息处理
生产者只是消息发送,所以我们将队列的创建以及交换机的绑定写在消费者端,方便处理接收到消息后的逻辑。
生产者:
原本是使用Feign客户端进行调用操作的,现在用发消息代替。
参数为:发送到哪个交换机的哪个队列,消息是什么?这里的消息是传过去的订单ID
// 5.修改订单状态
//orderClient.markOrderPaySuccess(po.getBizOrderNo());
rabbitTemplate.convertAndSend("trade.exchange","pay.success",po.getBizOrderNo());
消费者:
@RabbitListener 标记此方法为RMQ的消息监听器(消费者)
@QueueBinding 声明队列和交换机的绑定关系
并且指定了这个队列使用名为key的路由键。这个接收及处理消息的方法会接收到反序列化回来的消息ID,然后调用交易服务进行修改。
消息转换器
什么是消息转换?当生产者把消息发送出去的时候,是发送到了RMQ服务器,这个消息可以是普通的变量值,也可以是集合,对象等,当向网络发送这些消息的时候,这些消息会被JDK默认自带的序列化机制序列化为字节流进行发送,会导致原本只有如32字节的数据变成几百字节,占用空间。在服务端看到的还是一堆乱码。可以自定义一个新的消息转换器来解决:
引入依赖,配置即可,Spring 会自动将其应用于 AMQP 相关的组件中,替代原本的默认转换器。
解决后:
应用执行后,服务端可以看见创建的队列以及交换机等。
如果消息发送后,还有后续操作不依赖于消息结果,异步就非常有意义,它不会阻塞程序。
以上只针对消息发送成功的情况,如果消息发送失败呢?关注不迷路。
消息通知失败https://mp.csdn.net/mp_blog/creation/editor/143590954
往期
网关与微服务的通信https://mp.csdn.net/mp_blog/creation/editor/143430164
OpenFeign同步通信机制https://mp.csdn.net/mp_blog/creation/editor/143435763
标签:异步,RMQ,服务,通信处理机,绑定,队列,交换机,消息,路由 From: https://blog.csdn.net/2301_81243054/article/details/143577224