Error en Chequeo de Salud de RabbitMQ en Spring Cloud Stream

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

  1. RabbitHealthIndicator requiere la configuración de spring.rabbitmq, por lo que se debe proporcionar: mover la configuración de spring.cloud.stream.binders.*.environment a spring.rabbitmq.
  2. Deshabilitar RabbitHealthIndicator. La clase de configuración mancionada anteriormente tiene la anotación @ConditionalOnEnabledHealthIndicator("rabbit"), lo que significa que la configuración management.health.rabbit.enabled debe ser true para que sea efectiva. Deshabilitarla resuelve el problema.
management:
  health:
    rabbit:
      enabled: false


  1. Instalar RabbitMQ en localhost (como broma)

Etiquetas: Spring Cloud RabbitMQ Spring Boot Actuator Health Check

Publicado el 6-13 16:04