傳統 Spring MVC 項目 集成 Prometheus

undefined

前言

春節前的兩個星期,本人寫了兩篇Spring Boot 應用集成Prometheus + Grafana實現監控告警功能的文章。java

憑藉着 Spring Boot Actuator 模塊 + micrometer-registry-prometheus 模塊,Spring Boot 應用和 Prometheus 集成變得很是的簡單。git

可是一些老項目多是非 Spring Boot 的 Spring MVC 項目。這一次就是來說一講傳統 Spring MVC 如何集成 Prometheus。也算是把這個系列完整一下。github

相關的理論部分,實際上在往期兩篇文章中都有說明,這裏就不贅述了,直接進入實操部分。spring

實操

1. 引入依賴

這裏實際上就是引入 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

2. 配置新的endpoint

<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>
複製代碼

若是有集成shirospring security的話,記得配置一下對應的路徑app

3. 開啓JVM監控參數

在啓動類中增長以下代碼,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 實現監控告警有詳細的說明。微服務

4. 數據埋點(自定義Metrics指標)

Prometheus提供了4中不一樣的Metrics類型:Counter, Gauge, Histogram, Summary。

  • Counter - 只增不減的計數器
  • Gauge - 可增可減的儀表盤
  • Histogram - 自帶buckets區間用於統計分佈統計圖
  • 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);
    }
}

複製代碼

Counter

計數器能夠用於記錄只會增長不會減小的指標類型,好比記錄應用請求的總量(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))
複製代碼

Histogram

主要用於在指定分佈範圍內(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 也就算講述完畢了,能夠結合前兩篇文章一塊兒食用。

但願能給你帶來一些收穫。

若是本文有幫助到你,但願能點個贊,這是對個人最大動力🤝🤝🤗🤗。

參考

相關文章
相關標籤/搜索