文章

🍀SpringBoot:项目集成 RabbitMQ 启动报错

在 Springboot 项目中,集成了RabbitMQ,集群A的配置如下:

rabbitmq.public.host = 101.1.1.1
rabbitmq.public.port = 25672
rabbitmq.public.username = user
rabbitmq.public.password = user@PassWord

但是当项目启动时报错:

ms-service 2025-03-28 09:31:22.227 [SimpleAsyncTaskExecutor-197] [,,,] INFO  o.s.a.r.c.CachingConnectionFactory - Attempting to connect to: [101.1.1.1]
ms-service 2025-03-28 09:31:22.227 [DiscoveryClient-InstanceInfoReplicator-0] [,,,] WARN  o.s.b.a.a.RabbitHealthIndicator - Rabbit health check failed
org.springframework.amqp.AmqpIOException: java.net.SocketTimeoutException: connect timed out
        at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:71)
        at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:476)
        at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:614)
        at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:240)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1797)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1771)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1752)
        at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.getVersion(RabbitHealthIndicator.java:48)
        at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.doHealthCheck(RabbitHealthIndicator.java:44)
        at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:84)
        at org.springframework.boot.actuate.health.CompositeHealthIndicator.health(CompositeHealthIndicator.java:68)
        at org.springframework.cloud.netflix.eureka.EurekaHealthCheckHandler.getHealthStatus(EurekaHealthCheckHandler.java:103)
        at org.springframework.cloud.netflix.eureka.EurekaHealthCheckHandler.getStatus(EurekaHealthCheckHandler.java:99)
        at com.netflix.discovery.DiscoveryClient.refreshInstanceInfo(DiscoveryClient.java:1382)
        at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:117)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketTimeoutException: connect timed out
        at java.net.PlainSocketImpl.socketConnect(Native Method) 

经过排查可以确定,MQ的配置信息时没有问题的

然后我讲配置信息换成集群B

rabbitmq.public.host = 101.1.1.2
rabbitmq.public.port = 5672
rabbitmq.public.username = user
rabbitmq.public.password = user@PassWord

项目就可以正常启动

ms-service 2025-03-28 09:36:11.864 [DiscoveryClient-InstanceInfoReplicator-0] [,,,] INFO  o.s.a.r.c.CachingConnectionFactory - Attempting to connect to: [101.1.1.2]
ms-service 2025-03-28 09:36:11.912 [main] [,,,] INFO  s.d.s.w.s.ApiListingReferenceScanner - Scanning for api listing references
ms-service 2025-03-28 09:36:12.143 [DiscoveryClient-InstanceInfoReplicator-0] [,,,] INFO  o.s.a.r.c.CachingConnectionFactory - Created new connection: rabbitConnectionFactory#795bc4b8:0/SimpleConnection@8aa9094 [delegate=amqp://user@101.1.1.2:5672/, localPort= 50742]

从配置看两个集群只有端口不一致,通过命令查看MQ IP占用情况发现,集群A的配置端口虽然是25672,但是服务器连的却是5672

netstat -an | grep 101.1.1.1

连接工厂代码如下:

    @Bean("rabbitConnectionFactory")
    public ConnectionFactory mqConnectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setAddresses(host);
        connectionFactory.setPort(port);
        return connectionFactory;
    }

这段代码在配置host时使用了 `connectionFactory.setAddresses(host);` ,通过查看这段代码的源代码发现,它会重写配置,传入的格式为:host[:port],如果没有port,会默认赋值 5672

解决方案就是,使用setHost方法

    @Bean("rabbitConnectionFactory")
    public ConnectionFactory mqConnectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        return connectionFactory;
    }

License:  CC BY 4.0