发送方直接把消息传递给接收者, 如果中间有很多环节, 有一步出错, 那么所有操作都要回滚
同步调用的缺点:
- 拓展性差
- 性能下降
- 级联失败
异步调用方式其实就是基于消息通知的方式,一般包含三个角色:
消息发送者:投递消息的人,就是原来的调用方
消息Broker:管理、暂存、转发消息,你可以把它理解成微信服务器
消息接收者:接收和处理消息的人,就是原来的服务提供方
异步调用中, 发送方把消息发送给消息broker, 就算完成发送任务.
接收者从消息 breker 那里订阅消息
这样,发送消息的人和接收消息的人就完全解耦了。
此时, 如果发送方发送消息出错, 不需要全部回滚, 只需要将错误信息重新发布给消息代理
如果接受方接受消息过程出现错误, 那么消息代理重传就好, 发送方还是可以正常进行其他操作
异步调用的优势:
- 耦合度更低
- 性能更好
- 业务拓展性强
- 故障隔离,避免级联失败
异步通信的缺点:
- 完全依赖于Broker的可靠性、安全性和性能
- 架构复杂,后期维护和调试麻烦
消息Broker,目前常见的实现方案就是消息队列(MessageQueue),简称为MQ.
RabbitMQ是基于Erlang语言开发的开源消息通信中间件.
打开这个目录(我的电脑是)
C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.7.4\sbin
双击这个文件
等待命令框为这个状态
点击跳转官网地址
RabbitMQ
基于不同用户,将管理权限分离。
基于不同的 virtual host ,将每个项目的数据隔离。
将 virtual hosts 切换到 /zrj 之后, 查看 queue, 会发现之前创建的 test.queue 已经看不见了, 这就是基于 用户和 virtual hosts 的数据隔离效果
RabbitMQ 基于 AMQP 协议, 因此具有跨语言的特性.
Spring 官方基于 RabbitMQ 提供了一套消息收发管理工具 ---- Spring AMQP
Spring AMQP 提供的功能
- 自动声明队列、交换机及其绑定关系
- 基于注解的监听器模式,异步接收消息
- 封装了RabbitTemplate工具,用于发送消息
如果你很懒, 不想自己创建, 就去bilibili黑马的课程里, 找资源吧
(毕竟我也是在那里学的)
创建项目, 导入依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
我们查看 的 convertAndSend 方法可以看到, 由于多态, 参数的选择有很多方案, 上面使用的是
convertAndSend(String routingKey, Object object)
因为所有的数据发送都是 Object , 因此我们接收方那里收到的, 也是 Object 类型, 如果想取出使用, 记得转换类型
简单的说就是多个消费者消费同一个队列中的消息
通常情况下, 队列会采用轮询的方式, 每个消费者均分 队列中的消息
修改配置信息, 设定么个消费者每次获取消息的最大数量 (原先是 几个消费者 平均分掉 所有消息), 消费完成获取的消息之后才能获取下一条消息
注意: Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!
交换机的类型:
Fanout:广播,将消息交给所有绑定到交换机的队列。我们最早在控制台使用的正是Fanout交换机
Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列
Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符
Headers:头匹配,基于MQ的消息头匹配,用的较少。
发送消息, 并接收处理
可以看到, Fanout 交换机把消息 广播 给了绑定它的所有队列
Direct 模型下, 队列与交换机的绑定会指定一个 RoutingKey(路由key)
消息的发送方在向 Exchange 发送消息时吗也必须指定消息的 RoutingKey
Exchange 会将消息交给具有相同 RoutingKey 的队列
此时会发现, 对于不同的消息发送, 会有不同的处理
当 RoutingKey 为 green / blue 时, 只有绑定对应的 RoutingKey 的消费者都会进行消息处理
和 Direct 交换机基本类似, 但是绑定的 RoutingKey 可以使用通配符
通配符规则:
- #:匹配一个或多个词
- *:匹配不多不少恰好1个词
消息处理
使用 Spring AMQP 提供的 API 来声明队列和交换机, 而不是使用 RabbitMQ 控制台来操作
由于要绑定多个 key 的情况, 基于 @Bean 的方式声明队列和交换机会很麻烦, 因此 Spring AMQP 提供了注解的方式来声明 交换机和队列