Spring AMQP无法在RabbitMQ重启后自动重连问题求助
解决Spring RabbitMQ在RabbitMQ重启后无法自动重连的问题
从你提供的日志和环境信息来看,你使用的是Spring Rabbit 1.3.6.RELEASE + RabbitMQ Client 4.3.0 + Spring 3.1.4.RELEASE,核心问题是RabbitMQ服务重启后,SimpleMessageListenerContainer没有自动触发重连逻辑,导致监听器失效,必须重启应用才能恢复。下面针对你的版本给出具体的解决方案:
一、确保ConnectionFactory开启自动恢复能力
RabbitMQ Client 4.x已经原生支持连接自动恢复,但需要Spring Rabbit的CachingConnectionFactory启用该特性。你需要在配置中添加以下设置:
XML配置方式:
<bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> <property name="host" value="你的RabbitMQ地址"/> <property name="username" value="用户名"/> <property name="password" value="密码"/> <property name="port" value="5672"/> <!-- 开启连接自动恢复 --> <property name="recoveryEnabled" value="true"/> <!-- 设置网络恢复间隔(单位:毫秒,这里设置5秒重试一次) --> <property name="networkRecoveryInterval" value="5000"/> <!-- 保持合理的通道缓存大小 --> <property name="channelCacheSize" value="10"/> </bean>
Java配置方式(如果使用JavaConfig):
@Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory("你的RabbitMQ地址"); connectionFactory.setUsername("用户名"); connectionFactory.setPassword("密码"); connectionFactory.setPort(5672); connectionFactory.setRecoveryEnabled(true); connectionFactory.setNetworkRecoveryInterval(5000); connectionFactory.setChannelCacheSize(10); return connectionFactory; }
二、配置SimpleMessageListenerContainer的重试与恢复机制
接下来需要确保消息监听容器在连接断开后,能够自动尝试重启消费者并重新声明队列:
XML配置方式:
<bean id="messageListenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="queues" ref="你的队列Bean"/> <property name="messageListener" ref="你的消息监听器Bean"/> <!-- 设置手动确认(和你日志中的acknowledgeMode=MANUAL对应) --> <property name="acknowledgeMode" value="MANUAL"/> <!-- 开启容器自动启动 --> <property name="autoStartup" value="true"/> <!-- 设置队列不存在时不致命,允许重试声明 --> <property name="missingQueuesFatal" value="false"/> <!-- 设置失败声明的重试间隔(毫秒) --> <property name="failedDeclarationRetryInterval" value="3000"/> <!-- 设置消费者恢复间隔(毫秒) --> <property name="recoveryInterval" value="5000"/> <!-- 设置并发消费者数量,根据你的业务调整 --> <property name="concurrentConsumers" value="3"/> </bean>
三、关键参数说明
recoveryEnabled=true:开启RabbitMQ连接的自动恢复,底层客户端会在连接断开后尝试重新建立连接networkRecoveryInterval:控制连接恢复的重试间隔,避免过于频繁的重试missingQueuesFatal=false:当RabbitMQ重启后队列可能需要重新声明,这个参数确保容器不会因为队列暂时不存在而停止运行,而是定期重试failedDeclarationRetryInterval:队列声明失败后的重试间隔recoveryInterval:消费者线程异常退出后的重启间隔
四、验证效果
配置完成后,重启你的应用(这是最后一次需要手动重启),然后模拟RabbitMQ服务重启,观察日志:
- 应该能看到容器打印类似
Attempting to recover consumer的日志 - 当RabbitMQ恢复后,容器会自动重建连接、声明队列并恢复消息消费
附你提供的异常日志:
2018-05-10 09:10:01,561[SimpleAsyncTaskExecutor-34]|DEBUG|org.springframework.beans.factory.support.DefaultListableBeanFactory|13-org.springframework.beans-3.1.4.RELEASE|Returning cached instance of singleton bean 'org.springframework.amqp.core.Queue#3' 2018-05-10 09:10:01,560[SimpleAsyncTaskExecutor-27]|DEBUG|org.springframework.amqp.rabbit.listener.BlockingQueueConsumer|435-wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar-0.0.0|Closing Rabbit Channel: null 2018-05-10 09:10:01,563[SimpleAsyncTaskExecutor-34]|DEBUG|org.springframework.amqp.rabbit.listener.BlockingQueueConsumer|435-wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar-0.0.0|Starting consumer Consumer: tags=[[]], channel=null, acknowledgeMode=MANUAL local queue size=0 2018-05-10 09:10:01,560[SimpleAsyncTaskExecutor-32]|DEBUG|org.springframework.beans.factory.support.DefaultListableBeanFactory|13-org.springframework.beans-3.1.4.RELEASE|Returning cached instance of singleton bean 'org.springframework.amqp.core.Queue#1' 2018-05-10 09:10:01,559[SimpleAsyncTaskExecutor-29]|WARN|org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer|435-wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar-0.0.0|Consumer raised exception, processing can restart if the connection factory supports it org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:54)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:195)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:371)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils$1.createConnection(ConnectionFactoryUtils.java:80)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.doGetTransactionalResourceHolder(ConnectionFactoryUtils.java:130)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.getTransactionalResourceHolder(ConnectionFactoryUtils.java:67)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:365)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1009)[435:wrap_file_._jetstream_thirdparty_spring-rabbit-1.3.6.RELEASE.jar:0] at java.lang.Thread.run(Thread.java:745)[:1.7.0_80] Caused by: java.net.ConnectException: Connection refused at java.net.PlainSocketImpl.socketConnect(Native Method)[:1.7.0_80] at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)[:1.7.0_80] at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)[:1.7.0_80] at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)[:1.7.0_80] at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)[:1.7.0_80] at java.net.Socket.connect(Socket.java:579)[:1.7.0_80] at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:625)[:1.7.0_80] at com.rabbitmq.client.impl.SocketFrameHandlerFactory.create(SocketFrameHandlerFactory.java:50)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:61)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.init(AutorecoveringConnection.java:99)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:925)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:884)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:842)[432:com.rabbitmq.client:4.3.0] at com.rabbitmq.client.ConnectionF
内容的提问来源于stack exchange,提问作者user55926
相关产品推荐
相关产品推荐

