18. RabbitMQ
18.1. RabbitMQ简介
- 首先引入一个消息队列中间件概念: 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性[架构] 使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ
- RabbitMQ是一种消息中间件,用于处理来自客户端的异步消息。服务端将要发送的消息放入到队列池中。接收端可以根据RabbitMQ配置的转发机制接收服务端发来的消息。RabbitMQ依据指定的转发规则进行消息的转发、缓冲和持久化操作,主要用在多服务器间或单服务器的子系统间进行通信,是分布式系统标准的配置。
- RabbitMQ的使用场景:** 服务解耦、流量削峰、异步调用**
服务解耦:
- 假设有这样一个场景, 服务A产生数据, 而服务B,C,D需要这些数据, 那么我们可以在A服务中直接调用B,C,D服务,把数据传递到下游服务即可,但是,随着我们的应用规模不断扩大,会有更多的服务需要A的数据,如果有几十甚至几百个下游服务,而且会不断变更,再加上还要考虑下游服务出错的情况,那么A服务中调用代码的维护会极为困难,这是由于服务之间耦合度过于紧密- A服务只需要向消息服务器发送消息,而不用考虑谁需要这些数据;下游服务如果需要数据,自行从消息服务器订阅消息,不再需要数据时则取消订阅即可
流量削峰:
- 假设我们有一个应用,平时访问量是每秒300请求,我们用一台服务器即可轻松应对而在高峰期,访问量瞬间翻了十倍,达到每秒3000次请求,那么单台服务器肯定无法应对,这时我们可以考虑增加到10台服务器,来分散访问压力,但如果这种瞬时高峰的情况每天只出现一次,每次只有半小时,那么我们10台服务器在多数时间都只分担每秒几十次请求,这样就有点浪费资源了- 流量削峰情况下,瞬间出现的大量请求数据,先发送到消息队列服务器,排队等待被处理,而我们的应用,可以慢慢的从消息队列接收请求数据进行处理,这样把数据处理时间拉长,以减轻瞬时压力
异步调用:
- 考虑定外卖支付成功的情况,支付后要发送支付成功的通知,再寻找外卖小哥来进行配送,而寻找外卖小哥的过程非常耗时,尤其是高峰期,可能要等待几十秒甚至更长。这样就造成整条调用链路响应非常缓慢- 引入RabbitMQ消息队列,订单数据可以发送到消息队列服务器,那么调用链路也就可以到此结束,订单系统则可以立即得到响应,整条链路的响应时间只有200毫秒左右,寻找外卖小哥的应用可以以异步的方式从消息队列接收订单消息,再执行耗时的寻找操作
原文链接:RabbitMQ_rabbitmq csdn-CSDN博客
18.2. 一些概念解析
- RabbitMQ Server:也叫broker server,它是一种传输服务。他的角色就是维护一条从Producer到Consumer的路线,保证数据能够按照指定的方式进行传输。
- Producer:消息生产者,如图A、B、C,数据的发送方。消息生产者连接RabbitMQ服务器然后将消息投递到Exchange。
- Consumer:消息消费者,如图1、2、3,数据的接收方。消息消费者订阅队列,RabbitMQ将Queue中的消息发送到消息消费者。
- Exchange:生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个或多个Queue中(或者丢弃)Exchange并不存储消息。RabbitMQ中的Exchange有direct、fanout、topic、headers四种类型,每种类型对应不同的路由规则。
- Queue:(队列)是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅队列来获取消息的,RabbitMQ中的消息都只能存储在Queue中,多个消费者可以订阅同一个Queue,其中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
- RoutingKey:生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则。
Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
Producer: 消息生产者,就是投递消息的程序
Consumer: 消息消费者,就是接受消息的程序
Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
注 :由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。
18.3. RabbitMQ的三种模式
18.3.1. 直接模式
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
消息一次发给一个队列
18.3.2. 分裂模式
任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有Queue上。
- 可以理解为路由表的模式
- 这种模式不需要RouteKey
- 这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个Queue,一个Queue可以同多个Exchange进行绑定。
- 如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。
18.3.3. 主题模式
- 任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上。此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模糊匹配的意思,
a.# #.b a.b
- 注:交换器说到底是一个名称与队列绑定的列表。当消息发布到交换器时,实际上是由你所连接的信道,将消息路由键同交换器上绑定的列表进行比较,最后路由消息。任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上
- 新建一个交换器,类型选择topic -- 点击新建的交换器topictest
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RabbitMQApplication.class)
public class RabbitTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void send1(){//给队列中放东西测试
String message = "1111111_syx";
rabbitTemplate.convertAndSend("syx01","直接添加队列"+message);
}
@Test
public void send2(){//给队列中放东西测试
String message = "1111111_syx";
rabbitTemplate.convertAndSend("syx","","分裂添加队列"+message);
}
@Test
public void send3(){//给队列中放东西测试
String message = "1111111_syx";
rabbitTemplate.convertAndSend("bx","a.111","主题添加队列a.#==="+message);
}
spring:
rabbitmq:
host: 192.168.134.128
server:
port: 8081
@Component
@RabbitListener(queues = "syx01")
public class RabbitMQLinster01 {
@RabbitHandler
public void get(String message){
System.out.println("syx01接收到的信息"+message);
}
}
本文转载自: https://blog.csdn.net/bear_309/article/details/141781411
版权归原作者 白熊bro 所有, 如有侵权,请联系我们删除。
版权归原作者 白熊bro 所有, 如有侵权,请联系我们删除。