Spring Boot 2 Actuator 不发布 jvm 指标

Posted

技术标签:

【中文标题】Spring Boot 2 Actuator 不发布 jvm 指标【英文标题】:Spring Boot 2 Actuator doesnt publish jvm metric 【发布时间】:2019-02-08 10:32:57 【问题描述】:

我正在运行 Spring Boot 2 应用程序并添加了执行器 spring boot 启动器依赖项。我启用了所有 Web 端点,然后调用:

http://localhost:8080/actuator/metrics

结果是:


    "names": ["jdbc.connections.active", 
              "jdbc.connections.max", 
              "jdbc.connections.min", 
              "hikaricp.connections.idle", 
              "hikaricp.connections.pending", 
              "hikaricp.connections", 
              "hikaricp.connections.active", 
              "hikaricp.connections.creation", 
              "hikaricp.connections.max", 
              "hikaricp.connections.min", 
              "hikaricp.connections.usage", 
              "hikaricp.connections.timeout", 
              "hikaricp.connections.acquire"]

但我缺少所有 JVM 统计信息和其他内置指标。我在这里想念什么?我读到的所有内容都说这些指标应该随时可用。

感谢任何提示。

【问题讨论】:

查看代码后的一些发现。也许核心开发人员知道一些事情:由于某种原因 MeterRegistryPostProcessor 不会应用于我的 GraphiteMeterRegistry ,因此没有得到配置。这就是我从阅读(整个)代码中猜到的。但是 GraphiteMeterRegistry 肯定是作为 bean 加载的(如 /actuator/beans 中所示) 我在 Spring Boot v2.0.4.RELEASE 上运行时遇到了完全相同的问题。 启用@EnableGlobalMethodSecurity 时,Spring Boot 2.1.2 出现同样的问题 【参考方案1】:

我想与您分享这些发现。问题是第 3 方库(Shiro)和我的配置。 micrometer 的 bean 加载混淆了,导致配置 MicroMeterRegistry(在我的情况下为 PrometheusMeterRegistry)的所需 PostProcessingBean 初始化太晚。

我不知道通过不同的 Bean (PostProcessor) 配置注册表是否明智,这可能会导致我遇到的情况......注册表应该配置自己而不依赖其他可能构建得太晚的 Bean。

【讨论】:

【参考方案2】:

万一这种情况发生在其他人身上: 我有一个类似的问题(除了它不是 Graphite 而是 Prometheus,而且我没有使用 Shiro)。

基本上我只有 Hikari 和 HTTP 指标,没有其他指标(没有像 GC 这样的 JVM 指标)。

在找出根本原因之前,我撞了几堵墙:Spring Boot Autoconfigure 中有一个 Hikari 自动配置后处理器急切地检索 MeterRegistry,所以之前所有 Metric bean 都没有时间初始化。

令我惊讶的是,在 Github 中查看这段代码时,我没有找到它。所以我将我的spring-boot-starter-parent 版本从2.0.4.RELEASE 提升到2.1.0.RELEASE,现在一切正常。我正确地获得了所有指标。

【讨论】:

【参考方案3】:

正如我所料,这个问题是由 bean 的加载顺序引起的。

我在项目中使用了 Shiro。

Shiro 的验证方法使用 MyBatis 从数据库中读取数据。

我对MyBatis的Mapper文件使用了@Autowired,导致SpringBoot无法组装Actuator metrics相关的bean(不知道具体是什么原因)。

所以我通过手动组装禁用了 Mapper 文件的自动组装

代码如下:

public class SpringContextUtil implements ApplicationContextAware 

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException 
        SpringContextUtil.applicationContext = applicationContext;
    

    public static ApplicationContext getApplicationContext() 
        return applicationContext;
    

    public static Object getBean(String beanId) throws BeansException 
        return applicationContext.getBean(beanId);
    

然后

StoreMapper userMapper = (UserMapper) SpringContextUtil.getBean("userMapper");
UserModel userModel = userMapper.findUserByName(name);

问题暂时可以解决。这只是权宜之计,但目前我没有更好的办法。

【讨论】:

【参考方案4】:

我在/actuator/prometheus中找不到process_update_seconds,所以我花了一些时间来解决我的问题。

我的解决方案:

重写HikariDataSourceMetricsPostProcessorMeterRegistryPostProcessor

HikariDataSourceMetricsPostProcessor 的排序为 Ordered.HIGHEST_PRECEDENCE + 1;

package org.springframework.boot.actuate.autoconfigure.metrics.jdbc;
...

class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor, Ordered 

    ...

    public int getOrder() 
        return Ordered.HIGHEST_PRECEDENCE + 1;
    


MeterRegistryPostProcessor 的排序为 Ordered.HIGHEST_PRECEDENCE;

package org.springframework.boot.actuate.autoconfigure.metrics;
...
import org.springframework.core.Ordered;

class MeterRegistryPostProcessor implements BeanPostProcessor, Ordered 
    ...
    @Override
    public int getOrder() 
        return Ordered.HIGHEST_PRECEDENCE;
    


在我的例子中,我使用了 shiro 并使用 jpa 来保存用户会话 ID。我发现MeterRegistryPostProcessorHikariDataSourceMetricsPostProcessor 的顺序导致了问题。 MeterRegistry 因为加载顺序没有绑定metirc。

也许我的解决方案会帮助你解决问题。

【讨论】:

【参考方案5】:

我有a working sample with Spring Boot, Micrometer, and Graphite 并确认开箱即用的MeterBinders 的工作方式如下:


  "names" : [ "jvm.memory.max", "process.files.max", "jvm.gc.memory.promoted", "tomcat.cache.hit", "system.load.average.1m", "tomcat.cache.access", "jvm.memory.used", "jvm.gc.max.data.size", "jvm.gc.pause", "jvm.memory.committed", "system.cpu.count", "logback.events", "tomcat.global.sent", "jvm.buffer.memory.used", "tomcat.sessions.created", "jvm.threads.daemon", "system.cpu.usage", "jvm.gc.memory.allocated", "tomcat.global.request.max", "tomcat.global.request", "tomcat.sessions.expired", "jvm.threads.live", "jvm.threads.peak", "tomcat.global.received", "process.uptime", "tomcat.sessions.rejected", "process.cpu.usage", "tomcat.threads.config.max", "jvm.classes.loaded", "jvm.classes.unloaded", "tomcat.global.error", "tomcat.sessions.active.current", "tomcat.sessions.alive.max", "jvm.gc.live.data.size", "tomcat.servlet.request.max", "tomcat.threads.current", "tomcat.servlet.request", "process.files.open", "jvm.buffer.count", "jvm.buffer.total.capacity", "tomcat.sessions.active.max", "tomcat.threads.busy", "my.counter", "process.start.time", "tomcat.servlet.error" ]

注意graphite 分支上的示例,而不是master 分支。

如果你能以你所看到的方式破坏样本,我可以再看看。

【讨论】:

以上是关于Spring Boot 2 Actuator 不发布 jvm 指标的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Actuator 的“httptrace”端点在 Spring Boot 2.2.0 中不再存在

Spring Boot Actuator 2.0 使用

Spring Boot 2.x Actuator

spring-boot 监控 Actuator

关于spring-boot-actuator的httptrace端点不生效问题解决办法

Spring Boot Actuator 整合 Prometheus