spring rabbitmq consumer reconnect源码分析
一、起因
某日深夜,生产环境,rabbitmq服务器集群宕机,收到企微告警,以为rabbitmq server端有灾难恢复和高可用机制,业务不会受影响,就没关注该异常。
早上,到公司之后,就被运维告知,负责的某个服务消费的queue有消息积压,和平常的业务表现不同,隐约感觉和晚上的rabbitmq服务器异常有关。检查服务日志,发现服务没有消费rabbitmq数据,grafana上消费的某些queue consumer数量为0,而某些queue consumer正常。
疑问:该服务对rabbitmq的使用,抽象一下,A->B->C,其中A\B\C是queue,现象是rabbitmq server发生宕机恢复后,服务对A\B queue consumer 数量为0,服务对A\B queue consumer 数量正常,spring rabbitmq consumer reconnect客户端机制是怎么样的?为什么会有差异?
二、源码分析
带着疑问,分析服务业务代码,阅读spring rabbitmq源码。
结论:发现服务对A\B\C queue的消费,有差异,差异造成了rabbitmq server发生宕机恢复后,consumer reconnect表现形式不同,其中A\B使用的是@RabbitListener注解,底层是SimpleMessageListenerContainer,C是继承的接口MessageListener,底层是DirectMessageListenerContainer。
从日志搜索关键字,
- SimpleMessageListenerContainer,有限次重试reconnect,日志只有打印几次关键字:“Consumer threw missing queues exception, fatal=true”,“Stopping container from aborted consumer”,“Restarting Consumer XXX”。
- DirectMessageListenerContainer,有不断重试reconnect,日志有不断打印关键字:***”Queue not present, scheduling consumer XXX for queue XXX for restart”***
生产环境,springboot版本为2.4.6,spring-rabbit版本为2.3.7;以下源码,springboot版本为3.1.5,spring-rabbit版本为3.0.10。
1.SimpleMessageListenerContainer
SimpleMessageListenerContainer消费者consumer核心逻辑在org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.AsyncMessageProcessingConsumer类,AsyncMessageProcessingConsumer是一个Runnable,主要逻辑在run方法,主要是控制逻辑,真正的消费逻辑,在内部属性BlockingQueueConsumer类,源码片段如下:
1
|
#org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.AsyncMessageProcessingConsumer |