英文:
SpringBoot : Consul Health indicator missing from the Health endpoint
问题
我有一个基于 SpringBoot 的 Web 应用程序,它公开了一个 Consul 健康指示器 bean。
这个 bean 被 SpringBoot 的自动配置正确地创建和初始化,然而,尽管关联的配置属性 "management.health.consul.enabled" 被设置为 true,但该指示器在执行器健康端点中没有显示出来:
{
"status": "UP",
"components": {
"Kafka": {...},
"SchemaRegistry": {...},
"discoveryComposite": {...},
"diskSpace": {...},
"ping": {...},
"refreshScope": {...}
}
}
进一步检查后,我发现以下代码片段负责获取所有可用的指示器(HealthEndpointConfiguration.java):
@Bean
@ConditionalOnMissingBean
HealthContributorRegistry healthContributorRegistry(ApplicationContext applicationContext,
HealthEndpointGroups groups) {
Map<String, HealthContributor> healthContributors = new LinkedHashMap<>(
applicationContext.getBeansOfType(HealthContributor.class));
if (ClassUtils.isPresent("reactor.core.publisher.Flux", applicationContext.getClassLoader())) {
healthContributors.putAll(new AdaptedReactiveHealthContributors(applicationContext).get());
}
return new AutoConfiguredHealthContributorRegistry(healthContributors, groups.getNames());
}
在那里设置一个断点,我发现确实 ConsulHealthIndicator bean 不会出现在 applicationContext.getBeansOfType(HealthContributor.class) 调用的输出中,如下所示:
但是,当我使用父应用程序上下文进行相同的调用时,我得到以下结果:
有人可以解释一下为什么这个特定的 bean 在 根上下文 中存在,但在 子上下文 中却不存在吗?
是否有一种方法可以强制在子上下文中初始化它,以便它能正确地注册在健康端点中?
我目前使用的版本是
- SpringBoot 2.3.1.RELEASE
- spring-cloud-starter-consul-all 2.2.4.RELEASE
提前感谢您的帮助。
编辑
我附上了一个示例项目,以便重现这个问题。
我还包含了应用程序使用的 Consul 配置(您可以通过 consul import 命令导入它)。
运行上面的示例并访问健康端点(localhost:8080/monitoring/health),您将清楚地看到 Consul 组件在列表中丢失了。
英文:
I have a SpringBoot based web application that exposes a consul health indicator bean.
The bean is correctly created and initialized by springboot's autoconfiguration, yet, the indicator is not showing in the actuator health endpoint despite the fact that the associated configuration property "management.health.consul.enabled" is set to true:
{
"status": "UP",
"components": {
"Kafka": {...},
"SchemaRegistry": {...},
"discoveryComposite": {...},
"diskSpace": {...},
"ping": {...},
"refreshScope": {...}
}
}
Upon further inspection, I found the bellow snippet that is responsible for fetching all the available indicators (HealthEndpointConfiguration.java) :
@Bean
@ConditionalOnMissingBean
HealthContributorRegistry healthContributorRegistry(ApplicationContext applicationContext,
HealthEndpointGroups groups) {
Map<String, HealthContributor> healthContributors = new LinkedHashMap<>(
applicationContext.getBeansOfType(HealthContributor.class));
if (ClassUtils.isPresent("reactor.core.publisher.Flux", applicationContext.getClassLoader())) {
healthContributors.putAll(new AdaptedReactiveHealthContributors(applicationContext).get());
}
return new AutoConfiguredHealthContributorRegistry(healthContributors, groups.getNames());
}
Setting a break point there, I see that indeed the ConsulHealthIndicator bean is not listed in the output of the applicationContext.getBeansOfType(HealthContributor.class) call as shows bellow :
But when I test the same call with the parent application context instead, I get the following :
Can someone please shed some light on why this particular bean is present in the root context but not in the child context ?
Is there a way to force it's initialisation in the child context so that it will get correctly registered in the health endpoint ?
I'm currently using
- SpringBoot 2.3.1.RELEASE
- spring-cloud-starter-consul-all 2.2.4.RELEASE
Thank you in advance.
EDIT
I've attached a sample project allowing the reproduction of the issue.
I've also included an the consul configuration that is used by the app (you can import it via consul import command).
Running the example above and going to the health endpoint (localhost:8080/monitoring/health) you will clearly see that the consul component is missing from the list.
答案1
得分: 0
为了使Consul指示器正常工作,我不得不提供自己的HealthContributorRegistry,在执行HealthContributor beans查找时,我考虑了父上下文:
@Bean
HealthContributorRegistry healthContributorRegistry(
ApplicationContext applicationContext, HealthEndpointGroups groups) {
Map<String, HealthContributor> healthContributors =
new LinkedHashMap<>(applicationContext.getBeansOfType(HealthContributor.class));
ApplicationContext parent = applicationContext.getParent();
while (parent != null) {
healthContributors.putAll(parent.getBeansOfType(HealthContributor.class));
parent = parent.getParent();
}
return new DefaultHealthContributorRegistry(healthContributors);
}
这是一个临时解决方案,理想情况下,Consul指示器应该像其他健康指标一样可以直接正常工作。
英文:
In order to get the consul indicator working, I had to supply my own HealthContributorRegistry where I take into account the parent context when performing the HealthContributor beans lookup :
@Bean
HealthContributorRegistry healthContributorRegistry(
ApplicationContext applicationContext, HealthEndpointGroups groups) {
Map<String, HealthContributor> healthContributors =
new LinkedHashMap<>(applicationContext.getBeansOfType(HealthContributor.class));
ApplicationContext parent = applicationContext.getParent();
while (parent != null) {
healthContributors.putAll(parent.getBeansOfType(HealthContributor.class));
parent = parent.getParent();
}
return new DefaultHealthContributorRegistry(healthContributors);
}
This is a temporary workaround, ideally the consul indicator should be working out of the box like the rest of the health contributors.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论