问题
某一次对指标功能扩展后,访问/actuator/metrics
或/actuator/prometheus
,发现jvm相关指标丢失。
解决
搜索一段时间后,找到两个相关内容:
- Spring Boot 2 Actuator doesnt publish jvm metric
- Spring Actuator JVM metrics not showing when GlobalMethodSecurity is enabled
这两个问题最终都指向了一个github issue:
Some metrics are lost when Spring Data is on the classpath
基本都是spring boot 版本升级后导致的,但是我自己的问题并不是升级导致的。
issue中提到
The problem’s due to some premature initialisation of the
MeterRegistry
.
即一些操作导致了MeterRegistry
过早地初始化,最终导致MeterRegistry
的BeanPostProcessor
提前执行,少注册了部分指标。
结合搜索到的三个内容,总结了以下两种解决方案:
- 重新执行
MeterRegistry
的BeanPostProcessor
的postProcessAfterInitialization
方法,这样即使MeterRegistry
过早初始化,也能在第二次初始化时完成指标注册;@Configuration public class ActuatorMetricsConfig { @Bean InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, PrometheusMeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } }
- 在
@Bean
注解的方法中自动注入MeterRegistry
时,使用@Lazy
修饰,这样可以防止MeterRegistry
过早初始化:@Configuration(proxyBeanMethods = false) @ConditionalOnClass(DruidDataSource.class) @Slf4j static class DruidDataSourceMetricsConfiguration { @Bean public DruidDataSourceBeanPostProcessor dataSourceBeanPostProcessor(@Lazy MeterRegistry registry) { return new DruidDataSourceBeanPostProcessor(registry); } }
尝试两种方法都可以让所有指标注册成功,但使用@Lazy
注解看起来是更加优雅的方式,并且自动注入MeterRegistry
是导致MeterRegistry
过早初始化的罪魁祸首,从这里解决问题也非常合乎情理。