問題現象
在使用SpringCloud Stream集成RabbitMQ的時候報了這個錯:
2021-08-06 21:34:05.153 WARN 18660 --- [-172.28.165.129] o.s.b.a.amqp.RabbitHealthIndicator : Rabbit health check failed
org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
一開始我被Connection refused: connect
迷惑了,查了半天為啥連不上RabbitMQ。翻源碼、debug發現連接的地址沒錯,看RabbitMQ控制台也有connection和channel,說明實際還是連上了。
那為啥還報這個錯呢?
仔細一看拋異常的是RabbitHealthIndicator
,原來是SpringBoot Actuator想要監控RabbitMQ的連接狀態,但是連接被拒絕。
我的配置文件如下:
spring:
cloud:
stream:
binders: # 在此處配置要綁定的rabbitmq的服務信息;
defaultRabbit: # 表示定義的名稱,用於於binding整合
type: rabbit # 消息組件類型
inheritEnvironment: false
environment: # 設置rabbitmq的相關的環境配置
spring:
rabbitmq:
host: 172.22.234.51
port: 5672
username: admin
password: 123
原因
就是因為我使用了spring.cloud.stream.binders.*.environment
屬性配置rabbitMQ的相關信息,但是沒配置spring.rabbitmq
。這就導致自動配置檢測到類路徑下有rabbit相關的類,就配置了rabbit相關的Bean。
其中org.springframework.boot.actuate.amqp.RabbitHealthIndicator
負責監控rabbit的連接狀況,通過下面這個配置類自動配置。
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RabbitTemplate.class)
@ConditionalOnBean(RabbitTemplate.class)
@ConditionalOnEnabledHealthIndicator("rabbit")
@AutoConfigureAfter(RabbitAutoConfiguration.class)
public class RabbitHealthContributorAutoConfiguration
extends CompositeHealthContributorConfiguration<RabbitHealthIndicator, RabbitTemplate> {
@Bean
@ConditionalOnMissingBean(name = { "rabbitHealthIndicator", "rabbitHealthContributor" })
public HealthContributor rabbitHealthContributor(Map<String, RabbitTemplate> rabbitTemplates) {
return createContributor(rabbitTemplates);
}
}
但是沒有檢測到spring.rabbitmq
相關的配置,就使用了默認的配置,嘗試連接localhost:5672
,然后就出現了org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
。
問題的關鍵在於,spring.cloud.stream.binders.*.environment
為每個binder創建了單獨的上下文環境,跟application context是完全隔離的。所以,僅僅配置了spring.cloud.stream.binders.*.environment
,使Actuator從application context中沒有找到rabbitmq的配置。
參考Spring Cloud Stream and RabbitMQ health check
解決方法
-
RabbitHealthIndicator
需要spring.rabbitmq
的配置,就給他:將spring.cloud.stream.binders.*.environment
里面的配置拿到spring.rabbitmq
中。 -
禁用
RabbitHealthIndicator
。上面提到的配置類上還有一個@ConditionalOnEnabledHealthIndicator("rabbit")
,意思就是:配置management.health.rabbit.enabled
為true的時候生效。禁用即可解決。management: health: rabbit: enabled: true
-
在localhost安裝一個RabbitMQ(開玩笑的)