春节前的两个星期,本人写了两篇Spring Boot 应用集成Prometheus + Grafana实现监控告警功能的文章。java
凭借着 Spring Boot Actuator 模块 + micrometer-registry-prometheus
模块,Spring Boot 应用和 Prometheus 集成变得很是的简单。git
可是一些老项目多是非 Spring Boot 的 Spring MVC 项目。这一次就是来说一讲传统 Spring MVC 如何集成 Prometheus。也算是把这个系列完整一下。github
相关的理论部分,实际上在往期两篇文章中都有说明,这里就不赘述了,直接进入实操部分。spring
这里实际上就是引入 Prometheus 最基础的 Java 客户端依赖。安全
<properties>
...
<io.prometheus.version>0.8.0</io.prometheus.version>
</properties>
<!-- The client -->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>${io.prometheus.version}</version>
</dependency>
<!-- Hotspot JVM metrics-->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_hotspot</artifactId>
<version>${io.prometheus.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.prometheus/simpleclient_servlet -->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_servlet</artifactId>
<version>${io.prometheus.version}</version>
</dependency>
复制代码
像
simpleclient_hotspot
这种就是帮忙作了Hotspot JVM metrics 的收集,还有些其余的依赖能够参照官方github自行研究选择bash
<servlet>
<servlet-name>metrics</servlet-name>
<servlet-class>io.prometheus.client.exporter.MetricsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>metrics</servlet-name>
<url-pattern>/metrics</url-pattern>
</servlet-mapping>
复制代码
若是有集成
shiro
、spring security
的话,记得配置一下对应的路径app
在启动类中增长以下代码,jvm
@PostConstruct
public void init() {
//输出JVM信息
DefaultExports.initialize();
}
复制代码
如今启动项目,访问http://ip:port/metrics
,能够看到相关的指标数据:ide
# HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool.
# TYPE jvm_buffer_pool_used_bytes gauge
jvm_buffer_pool_used_bytes{pool="direct",} 1791403.0
jvm_buffer_pool_used_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool.
# TYPE jvm_buffer_pool_capacity_bytes gauge
jvm_buffer_pool_capacity_bytes{pool="direct",} 1791403.0
jvm_buffer_pool_capacity_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool.
# TYPE jvm_buffer_pool_used_buffers gauge
jvm_buffer_pool_used_buffers{pool="direct",} 44.0
jvm_buffer_pool_used_buffers{pool="mapped",} 0.0
# HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously.
# TYPE jvm_memory_pool_allocated_bytes_total counter
jvm_memory_pool_allocated_bytes_total{pool="Code Cache",} 2.4131136E7
jvm_memory_pool_allocated_bytes_total{pool="PS Eden Space",} 1.157973728E9
jvm_memory_pool_allocated_bytes_total{pool="PS Old Gen",} 4.2983992E7
jvm_memory_pool_allocated_bytes_total{pool="PS Survivor Space",} 2.3271936E7
jvm_memory_pool_allocated_bytes_total{pool="Compressed Class Space",} 6964912.0
jvm_memory_pool_allocated_bytes_total{pool="Metaspace",} 5.9245208E7
# HELP jvm_classes_loaded The number of classes that are currently loaded in the JVM
# TYPE jvm_classes_loaded gauge
......
复制代码
有了数据以后,后面的步骤(Prometheus 采集指标,可视化)在SpringBoot 微服务应用集成Prometheus + Grafana 实现监控告警有详细的说明。微服务
Prometheus提供了4中不一样的Metrics类型:Counter, Gauge, Histogram, Summary。
至于怎么使用,官方doc中详细的说明,这里简单举两个例子:
你能够先声明一个专门的拦截器,来处理统计Metrics的操做:
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
复制代码
计数器能够用于记录只会增长不会减小的指标类型,好比记录应用请求的总量(http_requests_total)。
对于Counter类型的指标,只包含一个inc()方法,用于计数器+1
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
// 用请求路径和http method 当作标签
private Counter requestCounter = Counter.build()
.name("io_namespace_http_requests_total")
.labelNames("path", "method")
.help("Total requests.")
.register();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 调用inc() 技术+1
requestCounter.labels(request.getRequestURI(), request.getMethod()).inc();
super.afterCompletion(request, response, handler, ex);
}
}
复制代码
一些对应的经常使用的聚合操做的PromQL:
# 经常使用PromQL
## 查询应用的请求总量
sum(io_namespace_http_requests_total)
## 查询每秒Http请求量
sum(rate(io_wise2c_gateway_requests_total[5m]))
## 查询当前应用请求量Top N的URI
topk(10, sum(io_namespace_http_requests_total) by (path))
复制代码
主要用于在指定分布范围内(Buckets)记录大小(如http request bytes)或者事件发生的次数。
以请求响应时间requests_latency_seconds为例,假如咱们须要记录http请求响应时间符合在分布范围{.005, .01, .025, .05, .075, .1, .25, .5, .75, 1, 2.5, 5, 7.5, 10}中的次数时。
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
private Histogram requestLatencyHistogram = Histogram.build()
.labelNames("path", "method", "code")
.name("io_namespace_http_requests_latency_seconds_histogram")
.help("Request latency in seconds.")
.register();
// spring interceptor 单例,线程不安全,因此使用threadlocal
private ThreadLocal<Histogram.Timer> timerThreadLocal = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Histogram.Timer histogramRequestTimer = requestLatencyHistogram.labels(request.getRequestURI(), request.getMethod()).startTimer();
timerThreadLocal.set(histogramRequestTimer);
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
Histogram.Timer histogramRequestTimer = timerThreadLocal.get();
histogramRequestTimer.observeDuration();
timerThreadLocal.remove();
super.afterCompletion(request, response, handler, ex);
}
}
复制代码
最后访问前面配置的 /metrics
端点,查看对应埋点数据。
到这里传统Spring MVC如何集成 Prometheus 也就算讲述完毕了,能够结合前两篇文章一块儿食用。
但愿能给你带来一些收获。
若是本文有帮助到你,但愿能点个赞,这是对个人最大动力🤝🤝🤗🤗。