Skip to content

Instantly share code, notes, and snippets.

@STRRL
Last active December 5, 2019 08:16
Show Gist options
  • Save STRRL/04602aaaab640b50afc4e9b668f78755 to your computer and use it in GitHub Desktop.
Save STRRL/04602aaaab640b50afc4e9b668f78755 to your computer and use it in GitHub Desktop.
Micrometer 快速整合文档

Micrometer 快速整合文档

该文档内容来自官方文档,包含部分自己的理解。

[toc]

Micrometer 简介

Micrometer 为大多数流行的监控系统的客户端提供了一个门面(facade)。可以用来监控你的 JVM-based 应用,而不需要为每个监控系统都写一个单独的实现。Micrometer 就像监控界的 SLF4J。

概念

Meter

A Meter is the interface for collecting a set of measurements (which we individually call metrics) about your application.
Meter 是采集度量(Metric)的接口。

Micrometer 中的 Meter 包括 Timer, Counter, Gauge, DistributionSummary, LongTaskTimer, FunctionCounter, FunctionTimer,TimeGauge.

Registry

Meters in Micrometer are created from and held in a MeterRegistry.
在 Micrometer 中,Meter 在 MeterRegistry 中创建,并保存在 MeterRegistry 中。
Each supported monitoring system has an implementation of MeterRegistry.
每个支持的监控系统都有一个 MeterRegistry 的实现

Composite registries

Micrometer provides a CompositeMeterRegistry to which multiple registries can be added, allowing you to publish metrics to more than one monitoring system simultaneously.
Micrometer 提供了 CompositeMeterRegistry 来添加多个 Registry,允许您同时将指标发布到多个监控系统。

安装

如果你的项目基于 Spring Boot 2.0.0.M5 及以上的版本,需引入spring-boot-starter-actuator。 如果你的项目基于 Spring Boot 1.5.x,则需要引入 micrometer-spring-legacy

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-spring-legacy</artifactId>
    <version>1.1.3</version>
</dependency>

如果你的项目基于 Spring Boot 更低的版本,快升级到 Spring Boot 1.5.x 或者更高吧。

曾经在 2018-09-17 统计各项目依赖版本时, Spring Boot 版本定下的版本号是 1.5.13.RELEASE

配置 Registry

Registry 是 Micrometer 用来输出监控数据的地方。Micrometer 默认的 Registry (SimpleMeterRegistry) 不会向任何地方输出。所以需要加入额外的 Registry,现在使用的方案是 Prometheus:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>1.1.3</version>
</dependency>

并且在application.yml中添加如下配置:

management:
  endpoint:
    health:
      show-details: always
  endpoints:
    web:
      exposure:
        include: health, info, prometheus

至少需要暴露health, info, prometheus 这三个 Endpoint.
其他请参照官方文档

如果应用没有办法使用自动配置(比如 Spring Boot 1.x 或者没有使用 spring 的 web 相关的组件), 也可以手动实现一个 web 接口调用io.micrometer.prometheus.PrometheusMeterRegistry#scrape()暴露监控数据. 比如:

@RestController
@RequestMapping("/")
public class PrometheusMetricController {
  @Autowired private PrometheusMeterRegistry meterRegistry;

  @GetMapping(value = "/actuator/prometheus", produces = "text/plain; version=0.0.4; charset=utf-8")
  public String metric() {
    return this.meterRegistry.scrape();
  }
}

对于非 Web 应用则需要使用 JMX Registry,由监控平台来"代理"发送数据:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-jmx</artifactId>
    <version>1.1.3</version>
</dependency>
  1. "代理"部分的实现涉及到 pushgateway 及其 java api,有兴趣的同学可以自行研究。
  2. micrometer-registry-prometheus内已经包含了有关pushgateway的类,不过请不要直接使用这部分的功能。

同样,其他不同 Registry 只需要引入对应的依赖即可。

已经内置的监控项

在添加监控项之前,可以先了解下已经默认实现的监控项,避免重复造轮子。

JVM 相关

  1. ClassLoader 相关监控
  2. 堆内存,非堆内存监控
  3. GC 监控
  4. 线程池监控
  5. CPU 占用监控

Web 相关

这部分没有具体研究过,下面只是根据各 AutoConfiguration 类进行的推测

  1. RestTemplate/AsyncRestTemplate 监控
  2. Jetty/Tomcat/Servlet 监控

数据库相关

  1. 数据库连接池监控

其他

  1. 监控各级别日志的消息个数
  2. Hibernate EntityManager 监控
  3. Kafka consumer 监控

为项目添加监控项

简而言之,Counter 只增不减,Gauge 绑定数据,Timer 记录持续时间 这三种基本的 Meter 可以覆盖大部分的情况了
下面将简单介绍三种指标的用法与适用场景。

一般来说,请使用这种方式将默认的 MeterRegistry 注入:

@Autowired
private MeterRegistry registry;

Counter

Counter 可以由以下方式进行初始化。 Fluent builder:

Counter counter = Counter
    .builder("counter")
    .baseUnit("beans") // optional
    .description("a description of what this counter does") // optional
    .tags("region", "test") // optional
    .register(registry);

调用 Counter 中的 increment()方法来计数。
下面这三种使用方式都是可以的。

counter.increment();
counter.increment(5);
counter.increment(1.2);

注: increment()方法的参数不可为负数,否则会带来非预期的错误。

适用场景:

  1. 方法调用次数,速率等
  2. 定时任务执行次数

注: 所有有关速率的监控项(请求的 tps,IO 的 ops),只需要添加记录总数的 counter 即可,速率的计算由监控系统实现

Gauge

Gauge 不像 Counter 那样可以调用increment()方法手动修改值,gauge 需要绑定一个方法才能进行工作。

Fluent builder:

Gauge gauge = Gauge
    .builder("gauge", myObj, myObj::gaugeValue)
    .description("a description of what this gauge does") // optional
    .tags("region", "test") // optional
    .register(registry);

适用场景: 能够直接通过 getter 获取到值的监控,如某个 Collection 的 size。

当然 Gauge 也可以调用 set() 方法手动设置值。

Timer

Timer 的使用方式比较多样:

Timer timer = Timer
    .builder("my.timer")
    .description("a description of what this timer does") // optional
    .tags("region", "test") // optional
    .register(registry);

timer 初始化后,可以使用多种方式进行记录数据:

  1. 调用record()直接记录一个时间段
  2. 调用record()直接执行并记录 Runnable 对象的执行时间
  3. 调用wrap()包装一个 Runnable 或 Callable 对象

Timer.Sample 用法:
SampleTimer的内部类,对计时这个操作提供了一个更好用的封装,精度是nanosecondsTimer.Sample类的定义很少,只有 20 行。 可以使用 Timer 的start方法返回一个Timer.Sample对象,然后使用Timer.Samplestop方法将计时器的数据存入 registry 中。 示例:

Timer.Sample sample = Timer.start(meterRegistry);
/**
 * codes here
**/
sample.stop(meterRegistry.timer('meter_name', "exception", "None","tag1", "value1", "tag2", "value2"));

除此之外,还有@Timed这种用法,可以去官方文档中查看资料。

Timer 只会在任务结束时才统计数据,对于长时间的计算任务,可以用LongTaskTimer进行监控,可以监控到任务已经运行了多久。

如何查看监控项

Spring Boot 2 可以直接通过/actuator/metrics访问到所有监控项目 Spring Boot 1.5.x 的/metrics不能访问到 micrometer 建立的监控项

如果引入了micrometer-registry-prometheus:
Spring Boot 1.5.x 请访问/prometheus Spring Boot 2 请访问/actuator/prometheus

如果引入了micrometer-registry-jmx: 请使用jconsole或其他工具查看micrometer下的MBean

监控项的命名及其他注意事项

  1. 在为监控项命名时,请全部使用英文小写,并使用.将各单词隔开。 (dot.case)
  2. 务必清楚的写明 description 字段
  3. 务必不要在 tags 中使用 job, instance 作为 key,这两个词是监控系统的保留字,其值在持久化时会被覆盖
  4. Meter 和 Logger 类似,Logger 以 logger name 为 id,Meter 以 name 和 tags 为 id。当以已经存在的 id 去初始化 Meter 时,会返回已存在的 Meter 实例。
  5. 对于内容大致相同的监控项,建议使用 tags 而不是 name 进行区分。例如默认实现中的 http request 监控,name 都是http.server.requests,增加了三个 tag: method, urlstatus来区分不同的请求.
  6. 对于同一个 Meter,tag 的数量是一致的,且 value 不能为 null。所以当某个 tag 的值需要为空时,也请不要使用空字符串,而是使用某个约定的值,如字符串None(参考WebMvcTags,line 53, private static final Tag EXCEPTION_NONE = Tag.of("exception", "None");).

命名示例:

http.server.requests
database.calls
jvm.heap.memory.used

命名反例:

http_server_requests
databaseCalls

其他

/actuator/health 与 HealthIndicator

health 的实现不属于 micrometer, 但是也是监控中比较重要的部分。

该接口在 Spring Cloud 中是自动发现来判断服务正常与否的关键指标。

简单来说,为应用增加一个 HealthIndicator,只需要实现AbstractHealthIndicator,然后注入到 Spring 上下文中就可以。 例子:

@Component
public class GrpcHealthIndicator extends AbstractHealthIndicator {

    @Autowired
    private GrpcServerRunner runner;

    @Override
    protected void doHealthCheck(Health.Builder builder) {
        int count = runner.getGrpcServiceBeans().size();
        builder.withDetail("gRPC Services Count", count).withDetail("gRPC Services", runner.getGrpcServiceBeans());
        if (count > 0) {
            builder.up();
        } else {
            builder.down();
        }
    }
}

更多详情请参考官方文档

/actuator/info 与 InfoContributor

与 health 一样, info 的实现也不属于 micrometer。 希望大家能够把项目名,版本等信息放到这里来,在应用 Spring Cloud 之前,监控平台将会用 /actuator/info 接口实现组件的自动发现。 spring-boot-maven-pluginspring-boot:build-info可以将组件的信息写入到META-INF/build-info.properties文件中,需要配置一个 execution:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
        <!-- 这个 execution 会写入 build-info.properties-->
        <execution>
            <id>build-info</id>
            <phase>compile</phase>
            <goals>
                <goal>build-info</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <executable>true</executable>
    </configuration>
</plugin>

也可以将配置写到application.yml或者自己实现InfoContributor.

更多详情请参考官方文档.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment