当前位置:   article > 正文

RabbitMQ 连接异常导致容器中的SpringBoot 项目退出问题分析_at org.springframework.amqp.rabbit.support.rabbite

at org.springframework.amqp.rabbit.support.rabbitexceptiontranslator.convert

1、首先描述一下问题:

      今日在开发环境提测时,发现了部署在容器中的后台服务一直在重新启动,导致无法提供服务。

2、项目背景

    采用了 Springboot+nacos,消息中心使用mq,使用依赖

  1. // rabbitmq
  2. implementation 'org.springframework.boot:spring-boot-starter-amqp:2.1.7.RELEASE'

3、分析定位问题

   1)步骤重现,无特定步骤使用平台几分钟后便无法提供访问。

   2)查看k8s Pod 详情,使用kubectl describe pod ,发现pod 健康状态为Unhealthy,导致无法对外提供服务。

   3)查看deployment的健康检查机制

  1. livenessProbe:
  2. httpGet:
  3. scheme: HTTP
  4. path: /actuator/health
  5. port: 20016
  6. initialDelaySeconds: 120
  7. periodSeconds: 15

      使用了springboot 框架的actuator 健康检查

   4)再查看pod的日志信息

  1. 2020-11-19 20:23:12 | INFO | grpc-default-executor-7 | org.springframework.amqp.rabbit.connection.CachingConnectionFactory | Attempting to connect to: [192.168.**.***]
  2. 2020-11-19 20:23:12 | ERROR | grpc-default-executor-7 | com.***i.mq.impl.PlatformMqServiceImpl | 发送消息失败,Exception:
  3. org.springframework.amqp.AmqpIOException: java.io.IOException
  4. at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:71)
  5. at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:530)
  6. at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:702)
  7. at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:214)
  8. at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:2076)
  9. at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2050)
  10. at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2030)
  11. at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:403)
  12. ...
  13. at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:172)
  14. at org.apache.skywalking.apm.plugin.grpc.v1.CallServerInterceptor$ServerCallListener.onHalfClose(CallServerInterceptor.java:144)
  15. at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:331)
  16. at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:817)
  17. at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
  18. at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
  19. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  20. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  21. at java.lang.Thread.run(Thread.java:748)
  22. Caused by: java.io.IOException: null
  23. at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:126)
  24. at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:122)
  25. at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:373)
  26. at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1104)
  27. at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1054)
  28. at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:484)
  29. ... 50 common frames omitted
  30. Caused by: com.rabbitmq.client.ShutdownSignalException: connection error
  31. at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
  32. at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
  33. at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:494)
  34. at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:315)
  35. ... 53 common frames omitted
  36. Caused by: java.io.EOFException: null
  37. at java.io.DataInputStream.readUnsignedByte(DataInputStream.java:290)
  38. at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:91)
  39. at com.rabbitmq.client.impl.SocketFrameHandler.readFrame(SocketFrameHandler.java:164)
  40. at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:596)
  41. ... 1 common frames omitted
  42. 2020-11-19 20:23:12 | INFO | XNIO-1 task-7 | org.springframework.amqp.rabbit.connection.CachingConnectionFactory | Attempting to connect to: [192.168.17.193]
  43. 2020-11-19 20:23:12 | WARN | AMQP Connection 192.168.17.193:5672 | com.rabbitmq.client.impl.ForgivingExceptionHandler | An unexpected connection driver error occured (Exception message: Connection reset)
  44. 2020-11-19 20:23:12 | WARN | XNIO-1 task-7 | org.springframework.boot.actuate.amqp.RabbitHealthIndicator | Rabbit health check failed
  45. org.springframework.amqp.AmqpIOException: java.io.IOException
  46. at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:71)
  47. at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:530)
  48. at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:702)
  49. at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:214)
  50. at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:2076)
  51. at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2050)
  52. at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2030)
  53. at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.getVersion(RabbitHealthIndicator.java:49)
  54. at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.doHealthCheck(RabbitHealthIndicator.java:44)
  55. at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82)
  56. at org.springframework.boot.actuate.health.CompositeHealthIndicator.health(CompositeHealthIndicator.java:95)
  57. at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:50)
  58. at org.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:53)
  59. at sun.reflect.GeneratedMethodAccessor233.invoke(Unknown Source)
  60. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  61. at java.lang.reflect.Method.invoke(Method.java:498)
  62. at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
  63. at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:76)
  64. at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)
  65. at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$ServletWebOperationAdapter.handle(AbstractWebMvcEndpointHandlerMapping.java:278)
  66. at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(AbstractWebMvcEndpointHandlerMapping.java:334)
  67. at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source)
  68. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  69. at java.lang.reflect.Method.invoke(Method.java:498)
  70. at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
  71. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
  72. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
  73. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
  74. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
  75. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
  76. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
  77. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
  78. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
  79. at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
  80. at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
  81. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
  82. at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
  83. at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
  84. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
  85. at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
  86. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  87. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  88. at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
  89. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  90. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  91. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  92. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
  93. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  94. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  95. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  96. at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
  97. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  98. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  99. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  100. at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
  101. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  102. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  103. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  104. at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
  105. at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
  106. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  107. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  108. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  109. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
  110. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
  111. at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
  112. at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
  113. at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
  114. at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
  115. at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
  116. at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
  117. at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
  118. at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
  119. at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
  120. at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
  121. at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
  122. at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
  123. at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
  124. at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
  125. at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
  126. at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
  127. at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
  128. at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
  129. at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
  130. at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
  131. at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
  132. at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
  133. at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
  134. at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
  135. at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
  136. at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
  137. at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
  138. at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
  139. at org.apache.skywalking.apm.plugin.undertow.v2x.SWRunnable.run(SWRunnable.java:48)
  140. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  141. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  142. at java.lang.Thread.run(Thread.java:748)
  143. Caused by: java.io.IOException: null
  144. at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:126)
  145. at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:122)
  146. at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:373)
  147. at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1104)
  148. at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1054)
  149. at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:484)
  150. ... 95 common frames omitted
  151. Caused by: com.rabbitmq.client.ShutdownSignalException: connection error
  152. at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
  153. at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
  154. at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:494)
  155. at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:315)
  156. ... 98 common frames omitted
  157. Caused by: java.net.SocketException: Connection reset
  158. at java.net.SocketInputStream.read(SocketInputStream.java:210)
  159. at java.net.SocketInputStream.read(SocketInputStream.java:141)
  160. at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
  161. at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
  162. at java.io.DataInputStream.readUnsignedByte(DataInputStream.java:288)
  163. at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:91)
  164. at com.rabbitmq.client.impl.SocketFrameHandler.readFrame(SocketFrameHandler.java:164)
  165. at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:596)
  166. ... 1 common frames omitted
  167. 2020-11-19 20:23:12 | INFO | Thread-10 | com.alibaba.cloud.nacos.registry.NacosServiceRegistry | De-registering from Nacos Server now...
  168. 2020-11-19 20:23:12 | INFO | Thread-10 | com.alibaba.cloud.nacos.registry.NacosServiceRegistry | De-registration finished.
  169. 2020-11-19 20:23:12 | INFO | Thread-10 | org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor | Shutting down ExecutorService 'applicationTaskExecutor'
  170. 2020-11-19 20:23:12 | INFO | Thread-10 | com.alibaba.druid.pool.DruidDataSource | {dataSource-1} closing ...
  171. 2020-11-19 20:23:12 | INFO | Thread-10 | com.alibaba.druid.pool.DruidDataSource | {dataSource-1} closed
  172. 2020-11-19 20:23:12 | INFO | Thread-10 | io.undertow.servlet | Destroying Spring FrameworkServlet 'dispatcherServlet'

查到报错:Rabbit health check failed, mq的健康检查未通过,导致容器/actuator/health 健康检查时显

  1. {
  2. "status": "DOWN"
  3. }

由于spring-boot-actuator 不太了解,查阅资料后得知,当项目中使用了mq 时,spring boot 自动生成mq的健康检查。mq无法连接时,导致整体的项目健康检查未通过,pod 重启

从前往后追从/actuator/health开始

  1. package org.springframework.boot.actuate.health;
  2. import ...
  3. @Endpoint(id = "health")
  4. public class HealthEndpoint {
  5. private final HealthIndicator healthIndicator;
  6. /**
  7. * Create a new {@link HealthEndpoint} instance that will use the given
  8. * {@code healthIndicator} to generate its response.
  9. * @param healthIndicator the health indicator
  10. */
  11. public HealthEndpoint(HealthIndicator healthIndicator) {
  12. Assert.notNull(healthIndicator, "HealthIndicator must not be null");
  13. this.healthIndicator = healthIndicator;
  14. }
  15. @ReadOperation
  16. public Health health() {
  17. return this.healthIndicator.health();
  18. }
  19. ...
  20. }

由端点来提供接口并返回数据最终调用HealthIndicator .health()方法。

  1. package org.springframework.boot.actuate.autoconfigure.health;
  2. import ...
  3. @Configuration
  4. @ConditionalOnSingleCandidate(HealthIndicatorRegistry.class)
  5. @ConditionalOnEnabledEndpoint(endpoint = HealthEndpoint.class)
  6. class HealthEndpointConfiguration {
  7. @Bean
  8. @ConditionalOnMissingBean
  9. public HealthEndpoint healthEndpoint(HealthAggregator healthAggregator, HealthIndicatorRegistry registry) {
  10. return new HealthEndpoint(new CompositeHealthIndicator(healthAggregator, registry));
  11. }
  12. }

由自动转装配的bean 对象实现了构造方法,查看一下CompositeHealthIndicator.health()实现

  1. package org.springframework.boot.actuate.health;
  2. import ...
  3. public class CompositeHealthIndicator implements HealthIndicator {
  4. ...
  5. @Override
  6. public Health health() {
  7. Map<String, Health> healths = new LinkedHashMap<>();
  8. for (Map.Entry<String, HealthIndicator> entry : this.registry.getAll().entrySet()) {
  9. healths.put(entry.getKey(), entry.getValue().health());
  10. }
  11. return this.aggregator.aggregate(healths);
  12. }
  13. }

遍历registry 中所有 对象获取health().HealthIndicatorRegistry 由下述方法实现

  1. package org.springframework.boot.actuate.autoconfigure.health;
  2. import ...
  3. @Configuration
  4. @EnableConfigurationProperties({ HealthIndicatorProperties.class })
  5. public class HealthIndicatorAutoConfiguration {
  6. ...
  7. @Bean
  8. @ConditionalOnMissingBean(HealthIndicatorRegistry.class)
  9. public HealthIndicatorRegistry healthIndicatorRegistry(ApplicationContext applicationContext) {
  10. return HealthIndicatorRegistryBeans.get(applicationContext);
  11. }
  12. ...
  13. }

get方法如下

  1. package org.springframework.boot.actuate.autoconfigure.health;
  2. import ...
  3. final class HealthIndicatorRegistryBeans {
  4. private HealthIndicatorRegistryBeans() {
  5. }
  6. public static HealthIndicatorRegistry get(ApplicationContext applicationContext) {
  7. Map<String, HealthIndicator> indicators = new LinkedHashMap<>();
  8. indicators.putAll(applicationContext.getBeansOfType(HealthIndicator.class));
  9. if (ClassUtils.isPresent("reactor.core.publisher.Flux", null)) {
  10. new ReactiveHealthIndicators().get(applicationContext).forEach(indicators::putIfAbsent);
  11. }
  12. HealthIndicatorRegistryFactory factory = new HealthIndicatorRegistryFactory();
  13. return factory.createHealthIndicatorRegistry(indicators);
  14. }
  15. ...
  16. }

从applicationContext中获取所有HealthIndicator对象。打断点后发现确实存在RabbitHealthIndicator 的bean 对象。

RabbitHealthIndicator.health()实现如下

  1. package org.springframework.boot.actuate.amqp;
  2. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  3. import org.springframework.boot.actuate.health.AbstractHealthIndicator;
  4. import org.springframework.boot.actuate.health.Health;
  5. import org.springframework.boot.actuate.health.HealthIndicator;
  6. import org.springframework.util.Assert;
  7. /**
  8. * Simple implementation of a {@link HealthIndicator} returning status information for the
  9. * RabbitMQ messaging system.
  10. *
  11. * @author Christian Dupuis
  12. * @since 1.1.0
  13. */
  14. public class RabbitHealthIndicator extends AbstractHealthIndicator {
  15. private final RabbitTemplate rabbitTemplate;
  16. public RabbitHealthIndicator(RabbitTemplate rabbitTemplate) {
  17. super("Rabbit health check failed");
  18. Assert.notNull(rabbitTemplate, "RabbitTemplate must not be null");
  19. this.rabbitTemplate = rabbitTemplate;
  20. }
  21. @Override
  22. protected void doHealthCheck(Health.Builder builder) throws Exception {
  23. builder.up().withDetail("version", getVersion());
  24. }
  25. private String getVersion() {
  26. return this.rabbitTemplate
  27. .execute((channel) -> channel.getConnection().getServerProperties().get("version").toString());
  28. }
  29. /****此方法由父类AbstractHealthIndicator 实现******/
  30. @Override
  31. public final Health health() {
  32. Health.Builder builder = new Health.Builder();
  33. try {
  34. doHealthCheck(builder);
  35. }
  36. catch (Exception ex) {
  37. if (this.logger.isWarnEnabled()) {
  38. String message = this.healthCheckFailedMessage.apply(ex);
  39. this.logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE, ex);
  40. }
  41. builder.down(ex);
  42. }
  43. return builder.build();
  44. }
  45. }

可以看到当mq的健康检查未通过时,会有报错信息Rabbit health check failed,至此问题定位完毕。

4、解决问题

   如果mq 对项目影响较大,则由此健康检查保证项目对外服务时,是可用状态。

   如果mq的影响不大,健康检查可有可无,则可以通过配置来忽略mq的健康检查。

management.health.rabbit.enabled=false

此配置如何生效 可以查看参考文章《SpringBoot健康检查实现原理》,这里就不在赘述。

5、反思

    平时还需多查看源码,多积累,方能快速的定位问题。

 

 

参考文章:

Spring boot 2.0 Actuator 的健康检查

spring-boot-actuator中health的工作原理解析

SpringBoot健康检查实现原理

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/381560?site
推荐阅读
相关标签
  

闽ICP备14008679号