1.同步调用的优点
- 时效性较强,可以立即得到结果
2.同步调用的问题
- 耦合度高
- 性能和吞吐能力下降
- 有额外的资源消耗
- 有级联失败问题
3.异步通信的优点
- 耦合度低
- 吞吐量提升
- 故障隔离
- 流量削峰
4.异步通信的缺点
- 依赖于Broker的可靠性、安全性、吞吐能力
- 架构复杂了,业务没有明显的流程线,不好追踪管理
什么是MQ
MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列,也就是事件驱动架构中的Broker
RabbitMQ入门
RabbitMQ中的几个概念
- channel:操作MQ的工具
- exchange:路由消息到队列中
- queue:缓存消息
- virtual host:虚拟主机,是对queue、exchange等资源的逻辑分组
HelloWorld案例
官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:
- publisher:消息发布这,将消息发送到队列queue
- queue:消息队列,负责接收并缓存消息
- consumer:订阅队列,处理队列中的消息
基本消息队列的消息发送流程
- 建立connection
- 创建channel
- 利用channel声明队列
- 利用channel向队列发送消息
基本消息队列的消息接收流程
- 建立connection
- 创建channel
- 利用channel声明队列
- 定义consumer的消费行为handleDelivery()
- 利用channel将消费者与队列绑定
SpringAMQP
什么是SpringAMQP
AMQP(Advanced Message Queuing Protocol)
- 是用于在应用程序或之间传递业务消息的开放标准
- 该协议与语言和平台无关,更符合微服务中独立性的要求。
SpringAMQP是基于AMQP协议定义的一套API规范,提供了模板来发送和接受消息。包含两部分,其中spring-amqp是基础抽象,spring-rabbit是底层的默认实现。
SpringAMQP如何接收消息?
- 引入amqp的starter依赖
- 配置RabbitMQ地址
- 定义类,添加@Component注解
- 类中声明方法,添加@RabbitListener注解,方法参数就是消息
注意:消息一旦消费就会从队列中删除,RabbitMQ没有消息回溯功能
发布(Publish)、订阅(Subscribe)
发布订阅模式与之前案例的区别就是允许将同意消息发送给多个消费者。实现方式是加入了exchange(交换机)
常见的exchange类型包括:
- Fanout:广播
- Direct:路由
- Topic:话题
注意:exchange负责消息路由,而不是存储,路由失败则消息丢失
SpringAMQP - FanoutExchange
FanoutExchange交换机的作用
- 接受publisher发送的消息
- 将消息按照规则路由到绑定的队列
- 不能缓存消息,路由失败,消息会丢失
- FanoutExchange的会将消息路由到每个绑定的队列
DirectExchange
Direct交换机与Fanout交换机的差异
- Fanout交换机将消息路由给每一个与之绑定的队列
- Direct交换机根据RoutingKey判断路由给哪个队列
- 如果多个队列具有相同的RoutingKey,则与Fanout功能类似
基于@RabbitListener注解声明队列和交换机有哪些常见注解
- @Queue
- @Exchange
SpringAMQP - 消息转换器
Spring的对消息对象的处理时由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。
如果要修改只需要定义一个MessageConverter类型的Bean即可。推荐用JSON方式序列化,步骤如下:
在publisher服务引入依赖
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.10> </dependency>
- 在publisher服务声明MessageConverter:
- ```
@Bean
public MessageConverter jsonMessageConverter(){
return new Jackson2JsonMessageConverter();
}
SpringAMQP中消息的序列化和反序列化如何实现
- 利用MessageConverter实现的,默认是JDK的序列化
- 注意发送方和接收方必须使用相同的MessageConverter