Spring Boot整合 Prometheus
Micrometer簡介
Micrometer 為 Java 平臺(tái)上的性能數(shù)據(jù)收集提供了一個(gè)通用的 API,應(yīng)用程序只需要使用 Micrometer 的通用 API 來收集性能指標(biāo)即可。Micrometer 會(huì)負(fù)責(zé)完成與不同監(jiān)控系統(tǒng)的適配工作。這就使得切換監(jiān)控系統(tǒng)變得很容易。Micrometer 還支持推送數(shù)據(jù)到多個(gè)不同的監(jiān)控系統(tǒng)。Micrometer類似日志系統(tǒng)中SLF4J。
Micrometer中有兩個(gè)最核心的概念,分別是是計(jì)量器(Meter)和計(jì)量器注冊(cè)表(MeterRegistry),下面來分別看下這兩個(gè)概念。
計(jì)量器(Meter)
Meter用來收集性能指標(biāo)數(shù)據(jù)(Metris),總共有四種類型的Meter,分別是Counter,Gauge,Timer,Summary。
每個(gè)Meter都有自己的名稱,同時(shí)Meter可以指定一系列的tag。tag是以key-value的形式出現(xiàn),這樣我們就可以根據(jù)tag對(duì)指標(biāo)進(jìn)行過濾。除了每個(gè)Meter獨(dú)有的標(biāo)簽外,也可以通過MeterRegistry添加通用的tag。
MeterRegistry.Config config = simpleMeterRegistry.config();
config.commonTags("tag1","value1","tag2","value2");
Counter
Counter只允許增加值,Counter所表示的計(jì)數(shù)值是double類型,默認(rèn)情況下增加的值是1.0
@Autowired
private SimpleMeterRegistry simpleMeterRegistry;
@Bean
public Counter counter1(){
return Counter.builder("test.count1").register(simpleMeterRegistry);
}
@Bean
public Counter counter2(){
return simpleMeterRegistry.counter("test.count2");
}
@Test
public void test(){
counter1.increment();
}
Gauge
Cauge是表示單個(gè)的變化的值,例如溫度,氣壓。與Counter的區(qū)別在于,Gauge的值不總是增加的
public void guage(){
Gauge.builder("guaua1", this::getValue).register(simpleMeterRegistry);
}
public double getValue(){
return ThreadLocalRandom.current().nextDouble();
}
Gauge對(duì)象一旦被創(chuàng)建,就不能手動(dòng)對(duì)其中的值進(jìn)行修改。在每次取樣時(shí),Gauge 會(huì)返回當(dāng)前值
Timer
Timer通常用來記錄事件的持續(xù)時(shí)間。Timer會(huì)記錄兩類的數(shù)據(jù),事件的數(shù)量和總的持續(xù)時(shí)間。Timer提供了不同方式來記錄持續(xù)時(shí)間。第一種方式是使用record()方法來記錄Runnable和Callable對(duì)象的運(yùn)行時(shí)間,第二種方式是使用Timer.Sample來保存計(jì)時(shí)狀態(tài)
public void record(){
Timer timer = simpleMeterRegistry.timer("record");
timer.record(() -> {
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
});
}
public void sample(){
Timer.Sample sample = Timer.start();
new Thread(()->{
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
sample.stop(simpleMeterRegistry.timer("sample"));
});
}
summary
summary用來記錄指標(biāo)的分布,summary根據(jù)每個(gè)指標(biāo)的值,把值分配到對(duì)應(yīng)的bucket中。Micrometer默認(rèn)的bucket的值從1到Long.MAX_VALUE,可以通過minimumExpectedValue和maximumExpectedValue來控制bucket的范圍,如果指標(biāo)的值較小,還可以通過scale來設(shè)置一個(gè)值對(duì)數(shù)值進(jìn)行放大
public void summary(){
DistributionSummary summary = DistributionSummary.builder("summary")
.maximumExpectedValue(10L)
.minimumExpectedValue(1L)
.publishPercentiles(0.5, 0.75, 0.9)
.register(simpleMeterRegistry);
summary.record(1.0);
summary.record(5.0);
summary.record(4.5);
summary.record(3.0);
System.out.println(summary.takeSnapshot());
}
計(jì)量器注冊(cè)表(MeterRegistry)
MeterRegistry負(fù)責(zé)創(chuàng)建和維護(hù)Meter。每一個(gè)監(jiān)控系統(tǒng)有自己獨(dú)有的registry

其中SimpleMeterRegistry是一個(gè)基于內(nèi)存的注冊(cè)表,它不支持導(dǎo)出數(shù)據(jù)到監(jiān)控系統(tǒng),主要用來進(jìn)行本地開發(fā)和測(cè)試。
Micrometer支持多個(gè)不同的監(jiān)控系統(tǒng),通過CompositeMeterRegistry可以把多個(gè)計(jì)量器注冊(cè)表組合起來,從而允許同時(shí)發(fā)布數(shù)據(jù)到多個(gè)監(jiān)控系統(tǒng)中。
public void compositeRegistry(){
CompositeMeterRegistry compositeMeterRegistry = new CompositeMeterRegistry();
compositeMeterRegistry.add(new SimpleMeterRegistry());
compositeMeterRegistry.add(new SimpleMeterRegistry(new SimpleConfig() {
@Override
public String get(String s) {
return null;
}
//增加前綴
@Override
public String prefix() {
return "simple";
}
},Clock.SYSTEM));
Counter counter = compositeMeterRegistry.counter("test");
counter.increment();
}
Micrometer本身提供了一個(gè)靜態(tài)的全局注冊(cè)表Metrics.golbalRegistry。這個(gè)注冊(cè)表一個(gè)組合注冊(cè)表,使用Metrics類中的靜態(tài)方法創(chuàng)建的計(jì)量器,都會(huì)被添加到這個(gè)全局注冊(cè)表中
public void globalRegistry(){
Metrics.addRegistry(simpleMeterRegistry);
Counter global = Metrics.counter("global");
global.increment();
}
SpringBoot Actuator
上述介紹了Micrometer的一些簡單使用,從Spring Boot2.0開始,Micrometer就是Spring Boot默認(rèn)提供的性能指標(biāo)收集庫。SpringBoot Actuator提供了對(duì)Micrometer的自動(dòng)配置。在項(xiàng)目中引入SpringBoot Actuator,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
并在配置文件中,增加如下配置
Actuator可對(duì)外默認(rèn)的服務(wù),*表示顯示所有
management.endpoints.web.exposure.include=*
啟動(dòng)項(xiàng)目,訪問http://8080/actuator,就可以看到Actuator提供的所有監(jiān)控
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"auditevents": {
"href": "http://localhost:8080/actuator/auditevents",
"templated": false
},
"beans": {
"href": "http://localhost:8080/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8080/actuator/caches/{cache}",
"templated": true
},
"caches": {
"href": "http://localhost:8080/actuator/caches",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-component": {
"href": "http://localhost:8080/actuator/health/{component}",
"templated": true
},
"health-component-instance": {
"href": "http://localhost:8080/actuator/health/{component}/{instance}",
"templated": true
},
"conditions": {
"href": "http://localhost:8080/actuator/conditions",
"templated": false
},
"configprops": {
"href": "http://localhost:8080/actuator/configprops",
"templated": false
},
"env": {
"href": "http://localhost:8080/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8080/actuator/env/{toMatch}",
"templated": true
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
},
"loggers": {
"href": "http://localhost:8080/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8080/actuator/loggers/{name}",
"templated": true
},
"heapdump": {
"href": "http://localhost:8080/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8080/actuator/threaddump",
"templated": false
},
"prometheus": {
"href": "http://localhost:8080/actuator/prometheus",
"templated": false
},
"metrics": {
"href": "http://localhost:8080/actuator/metrics",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8080/actuator/metrics/{requiredMetricName}",
"templated": true
},
"scheduledtasks": {
"href": "http://localhost:8080/actuator/scheduledtasks",
"templated": false
},
"httptrace": {
"href": "http://localhost:8080/actuator/httptrace",
"templated": false
},
"mappings": {
"href": "http://localhost:8080/actuator/mappings",
"templated": false
}
}
}
訪問http://localhost:8080/actuator/metrics,可以看到Actuator默認(rèn)收集的監(jiān)控指標(biāo),包括JVM相關(guān)指標(biāo)(內(nèi)存使用,垃圾收集),tomcat相關(guān)指標(biāo),數(shù)據(jù)庫連接池還是系統(tǒng)相關(guān)指標(biāo)
{
"names": [
"jvm.memory.max",
"jvm.threads.states",
"process.files.max",
"jvm.gc.memory.promoted",
"system.load.average.1m",
"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",
"http.server.requests",
"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.threads.current",
"process.files.open",
"jvm.buffer.count",
"jvm.buffer.total.capacity",
"tomcat.sessions.active.max",
"tomcat.threads.busy",
"process.start.time"
]
}
我們可以通過以下鏈接來查看具體某個(gè)指標(biāo)
http://localhost:8080/actuator/metrics/metricName
其中metricName為需要查看指標(biāo)的名稱,例如查看jvm內(nèi)存
http://localhost:8080/actuator/metrics/jvm.memory.used
從上圖中我們可以看到j(luò)vm.memory.used有兩個(gè)tag,area和id,area指定內(nèi)存位置(堆內(nèi)存和非堆內(nèi)存),id指定內(nèi)存分類,我們可以指定tag來查看更細(xì)致的指標(biāo)
http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:heap
http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:heap&tag=id:PS%20Eden%20Space
Prometheus
Micrometer支持Prometheus,Micrometer提供PrometheusMeterRegistry注冊(cè)表,用于將指標(biāo)轉(zhuǎn)為Prometheus格式的指標(biāo)。首先需要在pom文件引入依賴
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
其次在配置文件中,配置暴露Prometheus,并允許將指標(biāo)導(dǎo)入到Prometheus中
management.endpoint.prometheus.enabled=true
management.metrics.export.prometheus.enabled=true
項(xiàng)目啟動(dòng)后,我們?cè)L問http://localhost:8080/actuator/prometheus,可以看到指標(biāo)以變成Prometheus格式的指標(biāo)
可以安裝Prometheus來采集這些指標(biāo)
docker run -d -p 9090:9090 -v ~/Documents/config/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
其中prometheus.yml配置了采集地址及路徑
scrape_configs:
- job_name: prometheus-test
metrics_path: /actuator/prometheus
static_configs:
- targets: ['172.16.22.50:8080']
172.16.22.50是我本機(jī)的地址,你們可以修改為自己的ip地址即可,訪問http://localhost:9090/targets可以看到Prometheus采集配置
自定義Metric
我們可以利用Prometheus client自定義metric
package com.wbl.spingbootdemo.prometheus;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Counter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* @author wbl
* @date 2019-09-29
*/
@Service
public class PrometheusMeter {
@Autowired
private CollectorRegistry collectorRegistry;
// 定義name為prometheus_counter的counter
public Counter prometheusCounter(){
return Counter.build().name("prometheus_counter").help("prometheus counter test")
.register(collectorRegistry);
}
@PostConstruct
public void init(){
Counter counter = prometheusCounter();
new Thread(()-> {
while (true){
counter.inc();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
啟動(dòng)項(xiàng)目之后,可以在Prometheus查詢頁面看到剛剛定義的指標(biāo)prometheus_counter
總結(jié)
Micrometer整合了多個(gè)監(jiān)控系統(tǒng),包括Prometheus。Micrometer利用Meter收集數(shù)據(jù),利用不同的MeterRegistry與不同的監(jiān)控系統(tǒng)整合
SpringBoot Actuator集成了Micrometer,定義了許多默認(rèn)的metric,可以在http://localhost:8080/actuator/metrics查看
SpringBoot Actuator可以通過Micrometer將采集的指標(biāo)導(dǎo)入到Prometheus中
參考文獻(xiàn)
Micrometer
Quick Guide to Micrometer
Instrumenting And Monitoring Spring Boot 2 Applications
自定義Metrics:讓Prometheus監(jiān)控你的應(yīng)用程序
使用 Micrometer 記錄 Java 應(yīng)用性能指標(biāo)

喜歡,在看
