Window下启动rabbitmq
rabbitmq-server.bat
MQ的基本概念
Message Queue消息队列,在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信
分布式系统通信的两种方式: 直接远程调用 和 借助第三方完成间接通信
发送方为生产者,接收方为消费者
MQ的优劣势
优势:
应用解耦
异步提速
削峰填谷
劣势:
系统可用性减低
系统复杂度提高
一致性问题
应用解耦
系统的耦合性越高,容错性就月底,可维护性就越低
异步提速
提升用户体验和系统吞吐量(单位时间内处理请求的数目)
削峰填谷
提高系统稳定性
应用解耦 提高系统的容错性和可维护性
异步提速 提高系统吞吐量和用户体验
削峰填谷 提高系统稳定性
劣势
系统可用性减低
系统引入的外部依赖越多,系统稳定性越差,一旦MQ宕机,就会对业务造成影响。
系统复杂度提高
MQ的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。如何保证消息没被重复消费?怎么处理消息丢失的情况?如何保证消息传递的顺序性?
一致性问题
如何保证消息数据处理的一致性问题?
使用MQ需满足什么条件?
生产者不需要从消费者处获取反馈;
容许短暂的不一致性
确实有效果。即解耦、提速、削峰这些方面的收益,超过加入MQ,管理MQ的成本
快速入门
Rabbitmq执行图
docker run -d --hostname rabbitmq01 --name rabbitmqCluster01 -p 15672:15672 -p 5672:5672 -p 1883:1883 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' rabbitmq:3.8.2-management
Work Queues 工作队列模式
与简单模式相比,多了些消费端,多个消费端共同消费同一个队列中的消费者
Work Queues 模式下 多个消费者之间是一个竞争关系
Work Queues 对于任务过重或任务较多的情况使用工作队列可以提高任务处理的速度。
例如:短信服务部署多个,只需要有一个节点发送即可。
PubSub 订阅模式
该模式中,多了个Exchange角色,而且过程略有变化;
P: 生产者,发送给X(交换机)
C: 消费者,一直等待消息的到来
Queue: 消息队列,接受消息,缓存消息
Exchange: 交换机(X)。一方面,接受生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。具体操作,取决于Exchange的类型。常见的exchange类型
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key的队列
Topic:通配符,把消息交给符合routing key(路由模式)的队列
Exchange(交换机)只负责转发消息,不具备储存消息的能力,因此如果没有任何队列与Exchange绑定 ,或者没有符合路由规则的队列
,那么消息会丢失。
Routing 路由模式
队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由Key)
消息的发送方在向exchange发送消息时,必须指定消息的RoutingKey
Exchange不再把消息借给每一个绑定的队列,而是根据消息的Routing Key 进行判断,只有队列的RoutingKey与消息的Routing key完全一致,才会接受到消息。
P:生产者,向Exchange发送消息,发送消息时会指定一个routing key
X:exchange (交换机),接受生产者的消息,然后把消息递交给routing key完全匹配的队列
C1:消费者,所在队列指定了需要routing key 为error的消息
C2:消费者,所在队列指定了需要routing key 为info、error、warning的消息
Routing模式
要求队列在绑定交换机时要指定routing key
,消息会转发到符合 routing key的队列
TOPICS 通配符模式
Topic 主题模式可以实现Pub/Sub发布与订阅模式和Routing路由模式的功能,只是topic在配置routing key的时候可以使用通配符,显得更加灵活。
Spring 整合RabbitMQ
@RunWith就是一个运行器
@RunWith(JUnit4.class)就是指用JUnit4来运行
@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境
@RunWith(SpringRunner.class)
@RunWith(Suite.class)的话就是一套测试集合
@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件
单个文件
@ContextConfiguration(Locations="classpath:applicationContext.xml")
@ContextConfiguration(classes = SimpleConfiguration.class)
多个文件时,可用{}
@ContextConfiguration(locations = { "classpath:spring1.xml", "classpath:spring2.xml" })
SpringBoot整合 RabbitMQ
高级部分
消息的可靠性投递
使用rabbitmq时,作为消息发送方 出现消息丢失或投递失败的场景,rabbitmq提供了两种方式来控制消息的投递可靠性模式
Confirm确认模式
Return 退回模式
Confirm模式
Return模式
Consumer ACK
消息可靠性总结
持久化
Exchange要持久化
Queue 要持久化
Message 要持久化
生产方 确认confirm
消费方 确认ack
消息丢失 死信队列(死信交换机)
Broker高可用(集群)
Consumer 消费端 限流机制
手动签收之前最多只能获取几条消息,通过此方法来进行限流
TTL 队列过期
队列的统一过期
消息的单独过期
如果设置了消息过期时间,也设置了队列的过期时间, 则以时间短的为准
二者区别
队列过期,将队列中所有消息都移除
消息过期,只有消息在队列顶部,才会判断是否过期 (移除)
所以正常情况下,会对队列整体设置过期时间
死信队列DLX
死信队列。Dead letter Exchange(死信交换机)(Rabbitmq中的死信队列是死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX
消息成为死信的情况
:
队列消息长度到达限制 ;
消费者拒绝消费消息 ,basicNack/basicReject,并且不重回队列 ,requeue=false;
原队列存在消息过期设置,消息到达超时时间未被消费;
队列绑定死信交换机
给队列设置参数 : x-dead-letter-exchange 和 x-dead-letter-routing-key
绑定在队列中绑定死信交换机
死信队列就是普通队列
只是当消息成为死信后,队列绑定了死信交换机,则消息会被死信交换机重新路由回死信队列中
(死信队列,消息消费失败的一种方式)
延迟队列
消息进入队列后,可以被延迟一定的时间,再进行消费。
Rabbitmq中并没有提供延迟队列的功能
但可以使用:TTL(队列过期)+死信队列 组合实现延迟队列的效果
日志与监控
Rabbitmq默认日志存放 Var/log/rabbitmq/rabbitmq@xxx.log
Rabbitmqctl 管理和监控
消息补偿
消息幂等性保障
MQTT之QOS
MQTT 设计了 3 个 QoS 等级。
QoS 0:消息最多传递一次,如果当时客户端不可用,则会丢失该消息。
QoS 1:消息传递至少 1 次。
QoS 2:消息仅传送一次。
QoS 0 是一种 "fire and forget" 的消息发送模式:Sender (可能是 Publisher 或者 Broker) 发送一条消息之后,就不再关心它有没有发送到对方,也不设置任何重发机制。
QoS 1 包含了简单的重发机制,Sender 发送消息之后等待接收者的 ACK,如果没收到 ACK 则重新发送消息。这种模式能保证消息至少能到达一次,但无法保证消息重复。
QoS 2 设计了重发和重复消息发现机制,保证消息到达对方并且严格只到达一次。