RabbitMQ-原理【从生产者近MQ出消费者过程】

样式再修改
首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。
如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。
1 代表消息从生产者发送到Exchange; 2 代表消息从Exchange路由到Queue; 3 代表消息在Queue中存储;
4 代表消费者订阅Queue并消费消息。
1、确保消息发送到RabbitMQ服务器
可能因为网络或者Broker的问题导致1失败,而生产者是无法知道消息是否正确发送到Broker的。 有两种解决方案,第一种是Transaction(事务)模式,第二种Confirm(确认)模式。
在通过channel.txSelect方法开启事务之后,我们便可以发布消息给RabbitMQ了,如果事务提交成功,则消息一定 到达了RabbitMQ中,如果在事务提交执行之前由于RabbitMQ异常崩溃或者其他原因抛出异常,这个时候我们便 可以将其捕获,进而通过执行channel.txRollback方法来实现事务回滚。使用事务机制的话会“吸干”RabbitMQ的性 能,一般不建议使用。
生产者通过调用channel.confirmSelect方法(即Confirm.Select命令)将信道设置为confirm模式。一旦消息被投 递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),这就使得 生产者知晓消息已经正确到达了目的地了。
参考:
com.gupaoedu.transaction com.gupaoedu.confirm
2、确保消息路由到正确的队列
可能因为路由关键字错误,或者队列不存在,或者队列名称错误导致2失败。 使用mandatory参数和ReturnListener,可以实现消息无法路由的时候返回给生产者。 另一种方式就是使用备份交换机(alternate-exchange),无法路由的消息会发送到这个交换机上。
Map<String,Object> arguments = new HashMap<String,Object>(); arguments.put(“alternate-exchange”,“ALTERNATE_EXCHANGE”); // 指定交换机的备份交换机
channel.exchangeDeclare(“TEST_EXCHANGE”,“topic”, false, false, false, arguments);
参考:
com.gupaoedu.returnlistener 3、确保消息在队列正确地存储
可能因为系统宕机、重启、关闭等等情况导致存储在队列的消息丢失,即3出现问题。 解决方案:
1、队列持久化
2、交换机持久化
3、消息持久化
4、集群,镜像队列,参考下一节
4、确保消息从队列正确地投递到消费者 如果消费者收到消息后未来得及处理即发生异常,或者处理过程中发生异常,会导致4失败。
// String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
// String exchange, boolean durable
channel.exchangeDeclare(“MY_EXCHANGE”,“true”);
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() .deliveryMode(2) // 2代表持久化,其他代表瞬态
.build();
channel.basicPublish("", QUEUE_NAME, properties, msg.getBytes());

为了保证消息从队列可靠地达到消费者,RabbitMQ提供了消息确认机制(message acknowledgement)。消费 者在订阅队列时,可以指定autoAck参数,当autoAck等于false时,RabbitMQ会等待消费者显式地回复确认信号 后才从队列中移去消息。
如果消息消费失败,也可以调用Basic.Reject或者Basic.Nack来拒绝当前消息而不是确认。如果requeue参数设置为 true,可以把这条消息重新存入队列,以便发给下一个消费者(当然,只有一个消费者的时候,这种方式可能会出 现无限循环重复消费的情况,可以投递到新的队列中,或者只打印异常日志)。
5、消费者回调 消费者处理消息以后,可以再发送一条消息给生产者,或者调用生产者的API,告知消息处理完毕。
参考:二代支付中异步通信的回执,多次交互。某提单APP,发送碎屏保消息后,消费者必须回调API。 6、补偿机制
对于一定时间没有得到响应的消息,可以设置一个定时重发的机制,但要控制次数,比如最多重发3次,否则会造 成消息堆积。
参考:ATM存款未得到应答时发送5次确认;ATM取款未得到应答时,发送5次冲正。根据业务表状态做一个重发。 7、消息幂等性
服务端是没有这种控制的,只能在消费端控制。
如何避免消息的重复消费?
消息重复可能会有两个原因: 1、生产者的问题,环节1重复发送消息,比如在开启了Confirm模式但未收到确认。 2、环节4出了问题,由于消费者未发送ACK或者其他原因,消息重复投递。 对于重复发送的消息,可以对每一条消息生成一个唯一的业务ID,通过日志或者建表来做重复控制。 参考:银行的重账控制环节。
8、消息的顺序性
消息的顺序性指的是消费者消费的顺序跟生产者产生消息的顺序是一致的。 在RabbitMQ中,一个队列有多个消费者时,由于不同的消费者消费消息的速度是不一样的,顺序无法保证。 参考:消息:1、新增门店 2、绑定产品 3、激活门店,这种情况下消息消费顺序不能颠倒。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值