Problema Detectado
Al utilizar Spring Cloud Stream con RabbitMQ, se presenta el siguiente error:
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
Inicialmente, el mensaje Connection refused: connect causó confusión, llevando a investigar por qué no se podía conectar a RabbitMQ. Tras revisar el código fuente y hacer debugging, se descubrió que la dirección de conexión era correcta, y el panel de control de RabbitMQ mostraba conexiones y canales activos, lo que indicaba que la conexión se establecía correctamente.
Entonces, ¿por qué se genera este error?
Al examinar detenidamente, se observa que la excepción es lanzada por RabbitHealthIndicator, lo que significa que Spring Boot Actuator intenta monitorear el estado de conexión de RabbitMQ, pero la conexión es rechazada.
La configuración utilizada es la siguiente:
spring:
cloud:
stream:
binders: # Configuración del servicio RabbitMQ
defaultRabbit: # Nombre definido para integrar con binding
type: rabbit # Tipo de componente de mensaje
inheritEnvironment: false
environment: # Configuración del entorno de RabbitMQ
spring:
rabbitmq:
host: 172.22.234.51
port: 5672
username: admin
password: 123
Causa del Problema
La razón es que se utilizó la propiedad spring.cloud.stream.binders.*.environment para configurar la información de RabbitMQ, pero no se configuró spring.rabbitmq. Esto hace que la autoconfiguración detecte clases relacionadas con rabbit en el classpath y configure los beans correspondientes.
org.springframework.boot.actuate.amqp.RabbitHealthIndicator es responsable de monitorear el estado de conexión de rabbit, y es configurado automáticamente mediante la siguiente clase:
@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);
}
}
Sin embargo, al no detectar configuraciones relacionadas con spring.rabbitmq, utiliza la configuración predeterminada, intentando conectar a localhost:5672, lo que provoca la excepción org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect.
El problema clave es que spring.cloud.stream.binders.*.environment crea un entorno de contexto aislado para cada binder, completamente separado del application context. Por lo tanto, solo configurar spring.cloud.stream.binders.*.environment hace que Actuator no encuentre la configuración de rabbitmq en el application context.
Soluciones
RabbitHealthIndicatorrequiere la configuración despring.rabbitmq, por lo que se debe proporcionar: mover la configuración despring.cloud.stream.binders.*.environmentaspring.rabbitmq.- Deshabilitar
RabbitHealthIndicator. La clase de configuración mancionada anteriormente tiene la anotación@ConditionalOnEnabledHealthIndicator("rabbit"), lo que significa que la configuraciónmanagement.health.rabbit.enableddebe ser true para que sea efectiva. Deshabilitarla resuelve el problema.
management:
health:
rabbit:
enabled: false
- Instalar RabbitMQ en localhost (como broma)