本篇从以下几个问题进行解答
1、如何保证生产者不会把消息丢失
2、如何保证mq的消息持久化保存到硬盘
3、消费者消息确认
4、消费者消费失败重试机制
1、如何保证生产者不会把消息丢失
因为消息发送给消费者要进过多次网络传输,生产者->交换机->队列->消费者,中间经过了3次的数据传输,难免会丢失
rabbitmq提供了publisher confirm机制来避免消息发送到mq的过程中丢失,消息发送到mq后,会返回一个结果,标示处理成功 ,返回的结果分两种
publisher-confirm 发送者确认
消息发送成功给到交换机,返回ack
消息未发送成功给到交换机,返回nack
publisher-return 发送者回执
消息发送到交换机了,但是没有路由到队列里面去,返回ack,还会返回路由失败的原因
解决方案:
如果没有返回对应的成功标示,可以记录日志、或者再次重新发送、或者人工处理
2、如何保证mq的消息持久化保存到硬盘
因为mq的消息是内存存储,如果mq宕机或者服务挂了,重启之后消息就没了。那么怎么处理了?
其实很简单: 设置交换机、队列参数 durability 为 durable就好了,那么你的消息怎么持久勒?
其实也很简单:官方提供的MessageBuilder,设置DeliveryMode,具体代码:
Message msg = MessageBuilder
.withBody(message.getBytes(StandardCharsets.UTF_8))//消息体
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)//设置持久化
// .setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT)//设置不持久化
.build();
其实啊,我们springamqp已经帮我们做了交换机、队列、消息的持久化,但是,有些功能可以不用做持久化,这里具体根据业务分析,做不做持久化设置
3、消费者消息确认
有三种模式:
1)manual:手动发送ack ,需要自己写代码,try-catch进行处理(不推荐)
2)auto:自动ack,由spring帮我们处理了这个部分的代码,spring通过aop进行检测,没有异常,帮我们发送了ack,有异常,帮我们发送了nack
3) none: 关闭ack,
解决方案:代码配置:
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: auto #none 关闭 , manual 手动 , auto 自动
4、消费者消费失败重试机制
设置了消息重试,返回nack,如果消费者收到了消息,但是这个时候出现了异常,spring会再次把消息投递给消费者,代码还有问题,会再次投递,一直循环操作,这样会给系统带来很大压力,那么怎么解决了?
解决方案:代码配置
spring:
rabbitmq:
listener:
simple:
prefetch: 1
retry:
enabled: true #开启消费者失败重试
initial-interval: 1000 #初始的失败等待时间为1秒
multiplier: 1 #下次失败的等待时长倍数
max-attempts: 5 #最多重试次数
stateless: true #true无状态, false有状态 ,如果业务中包含事务,这里成false
当然啦,也可以记录日志、或者再次重新发送、或者人工处理,方法是活的
ok,今天的分享到这里就差不多了,咱们下期再见