消息发送:投递消息
消息代理:管理 暂存 转发消息
消息接收者:接收|处理消息的人,原来的服务提供方
消息延迟微妙级别,高可靠,可用性高
kafka高可用,高单机吞吐量,毫秒消息延迟,消息可靠性一般
消息队列
work queue 多个消费者绑定到一个队列,共同消费消息
消费者配置prefetch控制消费数量,处理完一条再处理下一条
交换机
fanout广播
广播到跟其绑定的queue
direct定向
发布者发送消息时,指定消息的routingkey
指定的queue,每个queue会设置与exchange的一个bindingkey
exchange将消息路由到bindingkey与消息routingkey一致的队列
exchange中绑定队列queue并设置routingkey
topic话题
topicExchange与directExchange类似
routingKey可以是多个单词列表,.分割
queue与exchange指定的bindingKey可使用通配符: # 0或多个单词 *一个单词
声明式交换队列
springamqp:
queue队列,queueBuilder
exchange:exchangeBuilder
binding:声明队列和交换机绑定关系,bindingBuilder
生产者重试
网络波动,可能客户端连接mq失败
spring:
rabbitmq:
connection-timeout: 1s
template:
retry:
enable: true#开启超时重试
initial-interval:1000ms#失败后初始等待时间
multiplier: 1#失败后下次等待的时长倍数,initial-interval*multiplier
max-attempts: 3#最大重试次数
网络不稳定,重试机制可提高消息发送成功率,springAMQP提供的重试机制是阻塞式的,多次等待过程中当前线程被阻塞,影响性能
生产者确认
机制:publisher confirm和publisher return,mq成功收到消息会返回确认消息给生产者:
消息投递到了mq,但是路由失败,此时会通过publisherReturn返回路由异常原因,返回ack
临时消息投递到mq,入队成功 返回ack 投递成功
持久消息投递到mq,入队完成持久化 返回ack 投递成功
其他情况返回nack,投递失败
spring:
rabbitmq:
publisher-confirm-type: correlated#none关闭simple同步阻塞等待mq回执消息correlated异步回调方式返回回执消息
publisher-return: true
每个rabbitTemplate只能配置一个returnCallback
nack可以有限次重试依然失败则记录异常信息
mq可靠性
默认mq将接收到的信息保存在内存中降低消息收发延迟
mq宕机 消息丢失;消费者故障或处理过慢导致消息积压 引发mq阻塞
数据持久化:
交换机持久化:
队列持久化:
消息持久化:
惰性队列:lazy queue
接收到消息后直接存入磁盘而非内存
消费者消费时才从磁盘中的读取并加载内存
支持数百万条的消息存储
通过配置让交换机 队列 以及发送的消息都持久化,消息持久化到磁盘
mq在3.6版本引入lazyQueue,在3.12版本后称为队列的默认模式
开启持久化和生产者确认,mq只有在消息持久化完成才能给生产者返回ack回执
消费者确认
确认机制:处理消息结束后 应该向mq发送回执,消息处理状态
回执:
ack 成功,mq删除该消息
nack消息处理失败,mq需要再次投递消息
reject处理失败并拒绝该消息,mq从队列中删除该信息
ack处理方式:
none不处理,消息投递给消费者立刻ack,消息会立刻从mq删除,非常不安全
manual手动模式,业务代码中调用api,发送ack或reject,存在业务入侵
auth自动模式 springAMQP利用aop对我们消息处理逻辑做了环绕增强,当业务正常执行时自动返回ack
失败重试
消费者出现异常,消息不断requeue重新入队,重新发送给消费者,再次异常 无限循环,mq消息处理飙升,利用retry消费者异常利用本地重试
java
spring:
rabbitmq:
listener:
simple:
prefetch: 1
retry:
enabled: true#消费者失败重试
initial-interval: 1000ms#初始的失败等待时长1s
multiplier: 1#下次失败的等待时长倍数
max-attempts: 3#最大重试次数
stateless: true#true无状态false有状态 如果业务中含事务 false
失败消息处理策略
重试次数耗尽,消息依然失败,需要messageRecoverer接口来处理
rejectAndDontRequeueRecoverer重试耗尽直接reject 弄丢消息
immediateRequeueMessageRecoverer重试耗尽返回nack ,消息重新入队
republishMessageRecoverer重试耗尽,将失败消息投递到指定的交换机
开启消费者确认机制auth,spring确认消息处理成功返回ack异常返回nack
开启消费者失败重试机制,设置messageRecoverer多次重试失败将消息投递到异常交换机 人工处理
服务间状态一致性
幂等:执行一次和多次对业务状态的影响是一致的
1.服务成功后利用mq消息通知其他服务完成状态同步
2.为保证mq消息的可靠性,生产者确认 消费者确认 消费者失败重试 确保消息投递和处理的可靠性
3.开启mq持久化
4.幂等判断,避免重复处理
消息处理失败:定时任务 查询失败的状态 重试 最终一致性
幂等性保障
消费多条相同消息 得到和消费该消费一次相同的结果
延迟消息
死信交换机
消费者使用basic.reject 或 basic.nack 声明消费失败 消息的requeue参数设置为false
消息过期消息 超时无人消费
要投递的队列消息堆积满了,最早的消息可能成为死信
队列通过dead-letter-exchange属性指定了一个交换机,该队列中死信会传递到这个交换机dlx
延迟消息插件
支持延迟消息功能的交换机,当消息投递到交换机后可以暂存一定时间,到期后再投递到队列
取消超时
消息追踪firehose
将生产者投递给mq的消息,mq投递给消费者的消息 按指定格式发送到默认的topic类型的exchange上:amq.rabbitmq.trace,routing为publish.exchangename和deliver.queuename,exchangename和queuename为实际exchange和queue名称,对应生产者投递到exchange到消息,和消费者从queue上获取的消息
开启影响写入功能,rabbitmqctl trace_on: 开启firehose命令 rabbitmqctl trace_off关闭
消息可靠性
冗余队列 监听服务 多次判断 定时重试