消息“丢失”的可能原因及解决办法
消息“丢失”是指消息已经从客户端成功发送到了服务端,且服务端返回了成功的响应。但是在消费时,该消息未被推送给客户端且已经从服务端删除,未来无法消费该消息。
可能原因
一般情况下,云消息队列 RabbitMQ 版并不会出现消息丢失,只要遵循使用限制,在最大消息保留时间内对消息进行消费,且在最大重试次数前作出有效应答,即可确保消息不丢失。使用限制,请参见使用限制。
客户端未收到消息,通常是如下几种原因:
生产者问题
消息未发送成功,这种情况下,消息一般未到达服务端,或者并未被发送到指定Queue,从而导致这条消息未被记录、存储。自然也就无法消费到。
消费者问题
消费者运行异常,导致消息无法消费到。
消费者代码问题,导致未收到队列的消息推送。
队列中存在消息堆积,导致消息无法消费到。
QoS等参数设置不合理,导致消息超过重推次数上限进入死信。
解决办法
您可以参考如下流程进行自助诊断。
生产者问题
确认消息成功发送进入RabbitMQ实例
可以为每条消息设置单独的Message ID,在消息发送时携带Message ID发往云消息队列 RabbitMQ 版服务端,此时这条消息便可依据这唯一Message ID进行跟踪。
针对某些未消费消息,可以根据Message ID在如下几个位置进行查询。
若根据上述几个方法查到消息确实已经被云消息队列 RabbitMQ 版服务端存储,则可以重点排查后续的消息推送过程是否存在异常。
若是没有查询到消息,则需要检查生产者代码的参数是否正确,队列是否正确绑定。
消费者问题
消息的推送事件可以在消息轨迹内看到。若消息有推送事件,需要查看所在队列是否存在堆积,导致消息推送阻塞。若无堆积情况,或消息有推送事件,但是客户端一直未消费到,则需要针对消费者的运行情况进行排查。
确认消费者运行正常
检查消费者运行情况,例如CPU、内存等资源是否充足,是否存在FullGC等现象。
检查网络链路是否一切正常,例如是否存在丢包等网络异常事件。
若上述物理资源均不存在瓶颈,可以检查云消息队列 RabbitMQ 版日志服务中的推送事件,根据RemoteAddress(客户端IP)这一字段进行筛查。若每个IP的推送事件均符合预期,且持续推送,则代表该消费者仍然存活,拥有消费能力。
消费者代码问题
检查消费者代码参数是否正确,是否按预期监听指定队列。
检查同一个Channel是否监听了多个队列。若队列间消息量差距较大,由于Channel共享QoS,可能会导致某些队列的消费过程被其它队列阻塞。
确认“丢失”消息所在队列是否有堆积
若物理资源、消费者运行均正常,则可以查看消息所在队列是否存在堆积。由于队列模型的特点,堆积严重的队列必须先将前面的消息消费完成后才会对后续消息进行推送。队列堆积情况可以通过控制台的监控指标,选取指定队列进行查看。具体操作,请参见监控指标。
若您的实例是企业版、铂金版、Serverless版,还可以直接进入控制台中的Dashboard进行查看,即下图的Ready Message项。
确定存在消息堆积的情况,请参见消息堆积的可能原因及解决办法。
查看该队列QoS等参数设置是否合理
QoS参数会在很大程度上影响消费者的消费行为。消费者消费较慢,QoS设置较小,因此消息堆积,无法推送给消费者。消费者消费较慢,但是QoS设置较大,消息在服务端视角已经推送给消费者,但是由于消费者的消费能力低下,并未消费到这条消息。此时若消费者崩溃,则这条消息会重新入队等待推送。
若QoS设置异常,且重推次数较少,这些已经被拉取到的消息频繁被客户端遗失,则可能导致该消息超过重推次数上限从而进入死信。
因此,请针对每个队列的消费耗时,酌情设置QoS值。详情请参见消费消息时需要注意什么?。
若上述方法均无法帮助您定位到消息“丢失”的原因,可以提交工单联系技术支持。