RabbitMQ工作模型
交换机:绑定列表 交换机和队列是多对多的关系
交换机常见的路由方式
1、direct直连
routing key路由键和binding key绑定建一致,交换机的消息只会路由到对应的队列中
2、topic主题
绑定建有个通配符的概念(# 0个或多个单词,* 不多不少一个单词)
路由键根据绑定建通配符的关系,将消息转发到符合要求的队列中
3、fanout广播
不需要指定任何的绑定建,生产消息也不需要带路由键,会把消息发送到所有与交换机绑定的队列中
死信队列
什么情况下消息会变成死信消息
1、消费者拒绝
2、消息过期
3、超过了队列的最大长度
生产端发送消息至服务端相关流程
1, 获取Conection
2, 获取Channel
3, 定义Exchange,Queue
4, 使用一个RoutingKey将Queue Binding到一个Exchange上
5, 通过指定一个Exchange和一个RoutingKey来将消息发送到对应的Queue上,
6, 接收方在接收时也是获取connection,接着获取channel,然后指定一个Queue直接到它关心的Queue上取消息,它对Exchange,RoutingKey及如何binding都不关心,到对应的Queue上去取消息就OK了;
可靠性投递
1、生产者发送消息到服务端
a、事务模式
channel.txSelect()设置成事务模式,channel.txCommit()提交事务,channel.txRollback()回滚事务
b、服务端确认模式
channel.confirmSelect()设置成确认模式
if(channel.waitForConfirms()){消息发送成功}
2、路由保证
a、mandatory=属性设置为true + ReturnListener
b、指定交换机的备份交换机
3、队列中消息的可靠性,持久化
4、消费者和队列之间的可靠,消费者确认机制
a、消费端自动的ACK机制,接受到消息就发送ACK
b、消费端手动ACK机制,消息正常消费完才发送ACK
关于消息的重复执行
首先我们可以确认的是,触发消息重复执行的条件会是很苛刻的! 也就说 在大多数场景下不会触发该条件!!! 一般出在任务超时,或者没有及时返回状态,引起任务重新入队列,重新消费! 在rabbtimq里连接的断开也会触发消息重新入队列。
消费任务类型最好要支持幂等性,这样的好处是 任务执行多少次都没关系,顶多消耗一些性能! 如果不支持幂等,比如发送信息? 那么需要构建一个map来记录任务的执行情况! 不仅仅是成功和失败,还要有心跳!!! 这个map在消费端实现就可以了!!! 这里会出现一个问题,有两个消费者 c1, c2 ,一个任务有可能被c1消费,如果再来一次,被c2执行? 那么如何得知任务的情况? 任务派发! 任务做成hash,固定消费者!
坚决不要想方设法在mq扩展这个future。
一句话,要不保证消息幂等性,要不就用map记录任务状态.