Spring Boot 工程集成 Micrometer
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.1.4</version>
</dependency>
application.properties
server.port=8088
spring.application.name=springboot2-prometheus
management.endpoints.web.exposure.include=*
management.metrics.tags.application=${spring.application.name}
启动类
@SpringBootApplication
public class Springboot2PrometheusApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot2PrometheusApplication.class, args);
}
@Bean
MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName){
return registry -> registry.config().commonTags("application", applicationName);
}
}
启动服务,浏览器访问 http://127.0.0.1:8088/actuator/prometheus 就可以看到应用的 一系列不同类型 metrics 信息,例如 http_server_requests_seconds summary、jvm_memory_used_bytes gauge、jvm_gc_memory_promoted_bytes_total counter 等等。
配置 Prometheus 监控应用指标
$ vim prommetheus.yml
......
- job_name: 'application'
scrape_interval: 5s
metrics_path: '/actuator/prometheus'
file_sd_configs:
- files: ['/usr/local/prometheus/groups/applicationgroups/*.json']
$ vim groups/applicationgroups/application.json
[
{
"targets": [
"192.168.1.124:8088"
],
"labels": {
"instance": "springboot2-prometheus",
"service": "springboot2-prometheus-service"
}
}
]
这里 192.168.1.124:8088 就是上边本地启动的服务地址,也就是 Prometheus 要监控的服务地址,同时添加一些与应用相关的标签,方便后期执行 PromSQL 查询语句区分。最后重启 Prometheus 服务,查看 Prometheus UI 界面确认 Target 是否添加成功。
配置 Grafana Dashboard 展示监控项
$ docker run -d -p 3000:3000 --name=grafana grafana/grafana
启动完毕后,浏览器访问 http://192.168.1.121:3000
即可,首次登录使用 admin:admin
默认账户密码登录并修改密码。登录完毕,需要添加数据源,这里我们要添加的就是上边 Prometheus 数据源,配置如下图:
配置完毕,接下来需要导入对应的监控 JVM 的 Dashboard 模板,模板编号为 4701
。
导入完毕后,就可以看到 JVM (Micrometer)
各种类型指标监控图形化以后的页面。
监控某几个 API 请求次数
@RestController
@RequestMapping("/v1")
public class IndexController {
@Autowired
MeterRegistry registry;
private Counter counter_core;
private Counter counter_index;
@PostConstruct
private void init(){
counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
}
@RequestMapping(value = "/index")
public Object index(){
try{
counter_index.increment();
} catch (Exception e) {
return e;
}
return counter_index.count() + " index of springboot2-prometheus.";
}
@RequestMapping(value = "/core")
public Object coreUrl(){
try{
counter_core.increment();
} catch (Exception e) {
return e;
}
return counter_core.count() + " coreUrl Monitor by Prometheus.";
}
}
说明一下,这里是一个简单的 RestController 接口,使用了 Counter 计量器来统计访问 /v1/index 及 /v1/core 接口访问量。因为访问数会持续的增加,所以这里使用 Counter 比较合适。启动服务,我们来分别访问一下这两个接口,为了更好的配合下边演示,可以多访问几次。
服务可以正常访问,并且访问了 6 次 /v1/index
,访问了 10 次 /v1/core
。接下来,我们可以到 Prometheus UI 界面上使用 PromSQL 查询自定义的监控信息了。分别添加 Graph 并执行如下查询语句,查询结果如下:
可以看到正确统计出来这两个接口请求的访问数,这里解释一下查询语句:
app_requests_method_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", method="IndexController.core"}
这里的app_requests_method_count_total
为上边代码中设置的 Counter 名称。
application 为初始化 registry 时设置的通用标签,标注应用名称,这样做好处就是可以根据应用名称区分不同的应用。
instance 为 <local_dir>/groups/applicationgroups/application.json
中配置的 instance 实例名称,用来区分应用实例。
method 为上边代码中设置的 Counter 标签名称,可以用来区分不同的方法,这样就不用为每一个方法设置一个 Counter 了。
接下来,我们在 Grafana Dashboard 上添加一个新的 Panel 并添加 Query 查询,最后图形化展示出来。首先添加一个 Panel 并命名为 自定义监控指标,然后点击 Add Query 增加一个新的 Query 查询,查询语句为上边的 PromSQL 语句,不过这里为了更好的扩展性,我们可以将 application 及 instance 两个参数赋值为变量,而这些变量可以直接从 Prometheus 上传递过来,最终的查询语句为
app_requests_method_count_total{application="$application", instance="$instance", method="IndexController.core"}
最后修改 Title 为 实时访问量 /v1/core
,保存一下,返回首页就可以看到刚添加的 Dashboard 了,是不是很直观。
监控所有 API 请求次数
监控请求次数可以继续使用 Counter 计数器,整个应用所有请求,我们自然而然的想到了 Spring AOP,通过切面注入可以做到统计所有请求记录,添加依赖如下:
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
@Component
@Aspect
public class AspectAop {
@Autowired
MeterRegistry registry;
private Counter counter_total;
ThreadLocal<Long> startTime = new ThreadLocal<>();
@Pointcut("execution(public * com.promethues.demo.controller.*.*(..))")
private void pointCut(){}
@PostConstruct
public void init(){
counter_total = registry.counter("app_requests_count", "v1", "core");
}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint)throws Throwable {
startTime.set(System.currentTimeMillis());
counter_total.increment();
}
@AfterReturning(returning = "returnVal", pointcut = "pointCut()")
public void doAftereReturning(Object returnVal){
System.out.println("请求执行时间:" + (System.currentTimeMillis() - startTime.get()));
}
}
我们创建了一个名称为 app_requests_count 的 Counter,所有请求过来都会执行 counter_total.increment(); 操作,从而实现统计所有请求总数。重启服务,访问多次不同的接口,然后在 Prometheus UI 界面执行 PromSQL 查询,查询语句为
app_requests_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", v1="core"}
查询结果如下:
可以看到,能够正确统计出来所有的请求数量,现在,我们可以在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来了,Query 语句为:
app_requests_count_total{application="$application", instance="$instance",v1="core"}
添加完成后,展示效果如下:
监控实时在线人数
@RestController
@RequestMapping("/v1")
public class IndexController {
@Autowired
MeterRegistry registry;
private Counter counter_core;
private Counter counter_index;
private AtomicInteger app_online_count;
@PostConstruct
private void init(){
counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
app_online_count = registry.gauge("app_online_count", new AtomicInteger(0));
}
@RequestMapping(value = "/index")
public Object index(){
try{
counter_index.increment();
} catch (Exception e) {
return e;
}
return counter_index.count() + " index of springboot2-prometheus.";
}
@RequestMapping(value = "/core")
public Object coreUrl(){
try{
counter_core.increment();
} catch (Exception e) {
return e;
}
return counter_core.count() + " coreUrl Monitor by Prometheus.";
}
@RequestMapping(value = "/online")
public Object onlineCount(){
int people = 0;
try {
people = new Random().nextInt(2000);
app_online_count.set(people);
} catch (Exception e){
return e;
}
return "current online people: " + people;
}
}
重启服务,访问一下 /v1/online
接口,得到一个 2000
以内的随机数作为实时在线人数,浏览器访问一下,得到结果如下:
我们在 Prometheus UI 界面执行一下 PromeSQL 查询语句
app_online_count{application="springboot2-prometheus", instance="springboot2-prometheus"}
同样能够对应获取到实时数据。
继续在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来,Query 语句为: app_online_count{application="$application", instance="$instance"}
, 添加完成后,展示效果如下: