RabbitMQ
RabbitMQ
MQ(MessageQueue),消息队列,用来存放消息的队列
Docker安装RabbitMQ
拉取镜像
docker pull rabbitmq:3-management |
运行
docker run \ |
访问
服务器IP:15672
SpringAMQP初体验
Advanced Message Queuing Protocol,是用于在应用程序之间传递业务消息的开放标准。该协议与语言和平台无关,更符合微服务中独立性的要求。
Spring AMQP是基于AMQP协议定义的一套API规范,提供了模板来发送和接收消息。包含两部分,其中spring-amqp是基础抽象,spring-rabbit是底层的默认实现。
SpringAmqp网址:Spring AMQP
引入依赖
<dependency> |
publisher
yml
spring: |
test-java
|
consumer
yml
spring: |
java
|
运行启动类
WorkQueue模式
模拟workqueue,实现一个队列绑定多个消费者
- 在publisher服务中,定义测试方法,每秒产生50条消息,发送到simple.queue
- 在consumer服务中定义两个监听者,都监听simple.queue
- 消费者01每秒处理50条消息,消费者02每秒处理10条消息
Publisher发布的消息存于 queue 消息队列中,两个 consumer 消费者绑定这个消息队列,两个消费者获取不到相同的消息
publisher
|
consumer
|
运行
先启动 consumer ,后启动 publisher 发布消息,通过查看日志得知,50条消息被两个消费者平均分配
这是因为消息预取机制(虽然没有处理完消息,但是可以获取下一条消息),消息发布到队列当中时,两个消费者轮流从中接收消息,应为消费者02处理较慢,所以最后的日志都是消费者02
消费者02 接收到simple.queue的消息为:hello,spring amqp_0,16:48:51.241 |
可以通过更改配置来解决这个问题
spring: |
发布,订阅模式
发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)。
常见的exchange类型:
- Fanout:广播
- Direct:路由
- Topic:话题
exchange 负责消息路由,而不是存储,路由失败则消息丢失
交换机将消息路由给两个队列,这样与queue01绑定的消费者和与queue02绑定的消费者接收的消息就一样了
FanoutExchange
FanoutExchange会将接收到的消息路由到每一个跟其绑定的queue
实现方法:
- 在consumer服务中,利用代码声明队列和交换机,并将两者绑定
- 在consumer服务中,编写两个消费者的方法,分别监听fanout.queue01和fanout.queue02
- 在publisher中编写测试方法,向 itcast.fanout发送消息
consumer
添加配置类
package com.heroxin.consumer.config; |
新建两个消费者
|
启动 consumer,可以看到成功添加了交换机
publisher
|
发布消息
两个消费者都接收到了相同的消息
DirectExchange
Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。
- 每一个Queue都与Exchange设置一个BindingKey
- 发布者发布消息时,指定消息的RoutingKey
- Exchange将消息路由到BindingKey与RoutingKey移植的队列。
实现思路:
- 利用@RabbitListener声明Exchange,Queue,Routingkey
- 在consumer服务中,编写两个消费者方法,分别监听direct.queue01和direct.queue02
- 在publisher中编写测试方法,向heroxin.direct发送消息
consumer
|
publisher
此时,设定的 routing key 为 ‘blue’,只有binding key 为 ‘blue’ 的消费者能接收到消息
|
TopicExchange
TopicExchange与DirectExchange类似,区别在于routingKey必须是多个单词的列表,并且以 . 分割。
Queue与Exchange指定BindingKey时可以使用通配符:
- #:代指0个或多个单词
- *:代指一个单词
这个写法和DirectExchange一样,只是消费者的routing不一样,这里就不演示了