简介
Micrometer为当前比较流行的监控系统的客户端,提供了一个简单的门面,可以很方便的用它来监控你的基于JVM的应用。它的作用类似于日志系统中SLF4J!Micrometer记录的应用程序指标可以用于观察,警报和响应环境的当前/最近运行状态。
官网:https://micrometer.io/ springboot 2.0 的Spring Boot Actuator 监控应用使用的就是Micrometer
快速入门
1. maven依赖
这里我们使用prometheus作为监控系统
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.0.6</version>
</dependency>
2. MeterRegistry
在Micrometer中,MeterRegistry主要是用来注册meters。我们可以通过迭代MeterRegistry来拓展每个meter的度量值。最后后端会使用指标及其维度值组合,生成一个时间序列的数据。针对不同的监控系统,MeterRegistry有不同的实现类。prometheus有一个MeterRegistry的实现类prometheusRegistry。我们可以使用prometheusRegistry来将我们的应用指标暴露给Prometheus。
PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
3. Tags
一个meter有name和tag组成。为了兼容不同的监控系统,建议命名的时候,使用小数点作为分隔符。例如
Counter counter = registry.counter("page.visitors", "age", "20s");
Tags可以是用来描述度量值的一些额外的额属性,以便我们做一些特殊的处理。在上面的代码中,page.visitors 是这个meter的名称,age=20s是它的tag。我们可以通过tag统计age在20和30之间的值。
在一些系统中,我们可以添加公共标签,例如我们的应用都有应用名称,就可以通过公共标签,给每一个metrix添加一个tag
registry.config().commonTags("application", "your applciation name");
这样我们在监控的时候就可以通过application 这个tag去监控不同的应用。
4. Counter
Counter可以用来计数。Counter接口允许您增加固定数量,但必须是正数。即Counter存的值只能一直增加。Counter可以用来记录http请求数。
Counter counter=meterRegistry.counter("page.visitors", "age", "20s");
counter.increment();
或者
Counter counter = Counter.builder("page.visitors")
.tag("age", "20s")
.register(meterRegistry);
counter.increment();
在prometheus中会存一条数据
page_visitors_total{age="20s",application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 1
5. Timer
Timer 可以用来测量系统中的时间的耗时和频率。Timer会记录时间发生的次数和处理的耗时。我们可以通过Timer来监控http请求耗时。
Timer timer = meterRegistry.timer("app.event");
timer.record(() -> {
try {
TimeUnit.MILLISECONDS.sleep(1500);
} catch (InterruptedException ignored) {
}
});
timer.record(3000, TimeUnit.MILLISECONDS);
在prometheus中会存两条数据,次数和耗时总数
app_event_seconds_count{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 2
app_event_seconds_sum{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 4.499942169
6. Gauge
Gauge可以用来获取当前的值,一个典型的例子是,Guage可以用来获取集合、map的长度或者在与运行状态的线程的数量
List<String> list = new ArrayList<>(4);
Gauge gauge = Gauge
.builder("cache.size", list, List::size)
.register(registry);
在prometheus中会存一条数据
cache_size{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 0
7. Distribution summaries
Distribution summaries用来记录事件的分布。类似于Timer,但不同的是它记录的值不是时间。例如,Distribution summaries可以用来度量请求到达服务器的负载
DistributionSummary distributionSummary = DistributionSummary
.builder("request.size")
.baseUnit("bytes")
.register(meterRegistry);
distributionSummary.record(3);
distributionSummary.record(4);
distributionSummary.record(5);
在prometheus中会存三条数据
request_size_bytes_count{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 3
request_size_bytes_max{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 0
request_size_bytes_sum{application="prometheus_demo",instance="192.168.0.106:8080",job="prometheus"} 12
8. 抓取数据
可以调用prometheusRegistry.scrape()来抓取监控到的数据。这里我们创建一个http 服务器提供一个用来抓取数据的http请求。
try {
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/prometheus", httpExchange -> {
prometheusRegistry.counter("http.request", Tags.of("url", "/prometheus")).increment();
String response = prometheusRegistry.scrape();
httpExchange.sendResponseHeaders(200, response.getBytes().length);
try (OutputStream os = httpExchange.getResponseBody()) {
os.write(response.getBytes());
}
});
new Thread(server::start).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
Prometheus 配置
为了将监控数据存储到prometheus,需要在Prometheus配置一下
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
metrics_path: /prometheus #这个是你暴露的http请求的url
static_configs:
- targets: ['192.168.0.106:8080'] #http服务器的ip和端口
配好之后,就可以在prometheus查询监控数据,也可以直接访问http://ip:port/prometheus.