如果是程序问题导致消费失败的情况,短时间内(未修复bug之前),当重试次数消耗完之后,消息则会被丢弃。 所以需要有对应方案,也就是配置死信队列。(SpringCloud Stream)
产生死信队列消息有两种方式:
1.当消息处理消费失败后,SpringCloud Stream 会自动默认重试3次(可通过配置maxAttempts来修改消费该队列消息的最大次数),重试三次失败后,RepublishMessageRecoverer类recover方法会将改变routingkey为队列名称发送至死信队列。
2.当队列里消息堆积过多时,超时未被消费的消息会放入到死信队列中。
死信队列需要开发人员手动进行配置,如下图:
我们并不是直接声明一个公共的死信队列,然后所以死信消息就自己跑到死信队列里去了。而是为每个需要使用死信的业务队列配置一个死信交换机,同一个项目或者同一个类型的业务的死信交换机可以共用一个,然后为每个业务队列分配一个单独的路由key。有了死信交换机和路由key后,接下来,就像配置业务队列一样,配置死信队列,然后绑定在死信交换机上。死信队列并不是什么特殊的队列,只不过是绑定在死信交换机上的队列。死信交换机也不是什么特殊的交换机,只不过是用来接收死信的交换机。
通过配置死信队列,可以让未正确处理的消息暂存到另一个队列中,处理死信队列的消息一般有两种方式:
1.由于程序执行,一些数据有问题,程序无法再继续进行处理,所以需要负责该任务的开发人员进行手动去处理。
2.当队列里消息堆积过多时,超时的消息也会放入到死信队列中,由于死信队列其实也是和普通消息一样,也是可以订阅的,所以可以订阅死信队列消息,然后开发人员定义死信队列消息消费逻辑,通过程序再处理那些超时的消息。(我们可以将所有队列绑定同一个死信队列,然后订阅这个死信队列,输出该队列成为死信队列的原因,保存到日志表中,再由开发人员去查看日志进行处理。)
访问Rabbitmq可视化界面可查看死信队列消息:
Get messages功能
点击队列名称查看队列信息,点击Get messages 按钮可获取死信队列里的消息信息
在打印的堆栈信息中,可以看到造成错误的信息、时间戳、监听的自定义的header信息和header信息的值,可根据这些去追踪该消息消费失败的原因。
其他header信息
routeTo:这是自己定义的头信息
x-exception-message:异常信息
x-exception-stacktrace:堆栈信息
x-original-exchange:绑定的交换机
x-original-routingKey:队列
Move messages功能
点击 Move messages 按钮死信队列的所有消息全部被重新投递到目标队列,通过 Move messages 功能,是可以将死信重新投递到原队列,而且也可以被正常重新消费。也可以通过订阅死信队列的方式来定义死信队列消息消费逻辑,然后通过程序再处理那些超时的消息。
Delete Queue功能
删除当前队列
Purge Message 功能
清除当前队列里的信息
关于死信队列的其他配置:
参考SpringCloud Stream官方文档:https://github.com/spring-cloud/spring-cloud-stream-binder-rabbit