场景
SkyWalking Java Agent 在8.10版本中支持了对线程池的监控,但是仅支持tomcat的线程池以及数据库的连接池,因此希望拓展出自定义想要监控的线程池,在线上运行环境中对系统了解的更加清晰,
SkyWalking我们更偏向于专注于trace追踪的使用,因此在了解了SkyWalking的实现原理后,我们在Prometheus中基于差不多的实现暴露出系统的指标,集成到Prometheus中。
其SkyWalking的原理就是基于相应的点做出拦截,得到线程池对象ThreadPoolExecutor,之后通过 getCorePoolSize
等方法获取线程池的状态然后进行上报,
因此Prometheus中可以基于同样的思想原理实现,在某个契机得到线程池对象,然后将其暴露到指标中。
暴露指标
暴露指标有两种方式,一种是通过引入spring boot actuator的形式,另一种是通过Prometheus Java Client形式暴露,前者其实就是对后者的封装,
前者的好处是使用方便,基本不用做太多的API编写,坏处是安全性问题,可能会暴露出不必要的东西出来,后者与之相反,可根据自己的需求来决定使用哪种方式。
actuator 安全性问题:www.istt.org.cn/NewsDetail/…
spring boot actuator形式
先在maven项目中引用如下几个jar包,得到指标暴露的支持:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>
复制代码
项目的yaml配置如下,主要关心management中的配置,大致的意思就是暴露出Prometheus的相关指标接口:
server:
port: 9091
#Prometheus springboot监控配置
spring:
application:
name: hello-demo
main:
allow-circular-references: true
management:
endpoints:
web:
exposure:
include: '*'
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name} # 暴露的数据中添加application label
复制代码
最后就是代码实现,思路是两步,
- 将所有的ThreadPool托管给Spring,然后加上自定义注解,最后在项目启动后获取带有自定义注解的bean
- 获取到bean后,使用
Metrics.gauge
对指标进行注册
最终访问 http://localhost:9091/actuator/prometheus
可以看到下面的结果,可以看到通过这个地址可以获取到我们的指标了:
Prometheus Java Client形式
因为官方推荐使用jetty作为暴露出去的服务,所以要引入jetty的包,并且引入 simpleclient 来作为类似上面案例中的 Metrics.gauge
效果。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.15.0</version>
</dependency>
<!-- Exposition servlet-->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_servlet</artifactId>
<version>0.15.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.44.v20210927</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.44.v20210927</version>
</dependency>
</dependencies>
复制代码
原生的Client API有些复杂,其需要一个 Collector 接口实现类,在这个实现类中对指标进行添加和进行暴露:
在APP启动类中,对每个扫描到到的线程池构建一个 Collector 实现类,并进行register操作,最终开启jetty server ,并添加一个 MetricsServlet 进去,最后启动。
最后对该servlet进行访问,可以看到我们注册进去的指标。
使用Prometheus收集指标
应用的指标暴露出来,就该使用Prometheus暴露指标了,我们使用docker启动一个Prometheus进行采集:
docker run -p 9090:9090 -v /Users/xxxx/Downloads/prometheus.yml:/etc/prometheus/prometheus.yml -d prom/prometheus
复制代码
prometheus.yml文件里面配置我们需要采集的应用地址:
docker 启动成功后,通过访问 http://localhost:9090/targets ,即可看见如下界面,说明我们已经成功对应用进行采集了。
使用 grafana 显示指标
通过docker启动grafana:
docker run -d --name=grafana -p 3000:3000 grafana/grafana
复制代码
启动完成后,通过 http://localhost:3000/login
访问登录界面,默认登录名和密码都是admin,
进入首页后,第一步是添加datasource,即数据来源,也就是我们的Prometheus
输入Prometheus的地址:
再点击Save&Test,进行保存
保存之后点击返回,然后点击添加Dashboard,
在添加面板中,选择数据源为Prometheus,之后就可以输入我们面板中需要展示的指标数据了:
输入完毕后,点击apply,我们的面板展示则OK展示:
end。