基于Spring Boot與Micrometer的系統參數監控指南

如何為你的Spring Boot應用裝上一個功能強大的監控儀表盤

在現代微服務架構中,系統監控已成為保障應用穩定性的關鍵環節。通過有效的監控,我們可以實時了解應用的運行狀態,及時發現并解決性能問題。本文將介紹如何使用Micrometer及其注冊表(Registry)在Spring Boot環境中實現全面系統參數監控。

1 Micrometer簡介

Micrometer是一款供應商中立的應用程序指標門面(Facade),類似于SLF4J在日志領域的作用,它為不同監控系統提供了統一的度量采集API。它可以與多種監控系統(如Prometheus、Datadog、New Relic、InfluxDB等)無縫集成,讓你無需修改代碼即可切換監控后端。

Micrometer的架構圍繞三個核心概念構建:

  • Meter:表示具體的度量指標,如計數器(Counter)、計時器(Timer)等

  • MeterRegistry:負責創建和存儲Meter的核心接口

  • Binder:將框架內部指標(如JVM指標)自動綁定到注冊表

2 Spring Boot集成Micrometer

2.1 添加依賴

首先,在您的pom.xml中添加以下依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-core</artifactId>
</dependency>
<!-- 使用Prometheus作為監控系統 -->
<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

如果使用Gradle,可以在build.gradle中添加:

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-core'
implementation 'io.micrometer:micrometer-registry-prometheus'

2.2 配置監控端點

application.ymlapplication.properties中進行配置:

management:endpoints:web:exposure:include: health,info,metrics,prometheusmetrics:tags:application: ${spring.application.name}region: northexport:prometheus:enabled: true

此配置開啟了Actuator的監控端點,并設置了全局標簽(application和region),這些標簽會附加到所有監控指標上

2.3 選擇監控系統

Micrometer支持多種監控系統,以下是常見選擇:

監控系統適用場景特點
Prometheus時間序列監控開源、拉取模式、適合Kubernetes環境
InfluxDB處理大量時間序列數據高性能、支持類SQL查詢
Datadog全棧可觀測性商業化、功能全面、支持多種數據源
StatsD簡單指標收集輕量級、推送模式、易于部署

3 使用MeterRegistry記錄指標

Spring Boot會自動配置一個MeterRegistry實例,可以直接在代碼中使用它來記錄各種指標。

3.1 計數器(Counter)

計數器用于記錄單調遞增的指標,如請求總數、訂單創建數量等。

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class OrderService {private final Counter orderCounter;public OrderService(MeterRegistry meterRegistry) {this.orderCounter = meterRegistry.counter("orders.total", "type", "created");}public void createOrder() {// 業務邏輯orderCounter.increment();}
}

3.2 計量儀(Gauge)

Gauge用于測量瞬時值,如內存使用量、緩存大小等。

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.concurrent.atomic.AtomicInteger;@Component
public class MyGaugeComponent {private AtomicInteger myValue = new AtomicInteger(0);private final MeterRegistry meterRegistry;public MyGaugeComponent(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;}@PostConstructpublic void init() {Gauge.builder("my_custom_gauge", myValue, AtomicInteger::get).description("A custom gauge example").tags("component", "gauge").register(meterRegistry);}public void updateValue(int newValue) {myValue.set(newValue);}@Beanpublic CommandLineRunner bindThreadPoolToMetrics(MeterRegistry registry,@Qualifier("asyncExecutorService") ThreadPoolTaskExecutor executor,SystemStatusService systemStatusService) {Gauge.builder("system.status.code", systemStatusService::getStatusCode).description("當前系統狀態碼").register(registry);return args -> {registry.gauge("asyncExecutorService.threadpool.core.size", executor, ThreadPoolTaskExecutor::getCorePoolSize);registry.gauge("asyncExecutorService.threadpool.max.size", executor, ThreadPoolTaskExecutor::getMaxPoolSize);registry.gauge("asyncExecutorService.threadpool.pool.size", executor, ThreadPoolTaskExecutor::getPoolSize);registry.gauge("asyncExecutorService.threadpool.active.count", executor, ThreadPoolTaskExecutor::getActiveCount);registry.gauge("asyncExecutorService.threadpool.queue.size", executor,new ToDoubleFunction<ThreadPoolTaskExecutor>() {@Overridepublic double applyAsDouble(ThreadPoolTaskExecutor value) {return value.getThreadPoolExecutor().getQueue().size();}});//registry.gauge("system.status.code", systemStatusService, SystemStatusService::getStatusCode);};}@Bean(name = "threadPoolTaskScheduler")public ThreadPoolTaskScheduler threadPoolTaskScheduler() {ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();executor.setPoolSize(2);executor.setThreadNamePrefix("TST-SCHEDULER");executor.setWaitForTasksToCompleteOnShutdown(true);executor.setAwaitTerminationSeconds(10);return executor;}
}

3.3 計時器(Timer)

計時器用于測量短時任務的持續時間,內置百分位計算。

import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class ApiService {private final Timer apiTimer;public ApiService(MeterRegistry meterRegistry) {this.apiTimer = meterRegistry.timer("api.requests", "api_type", "external");}public String callExternalApi() {return apiTimer.record(() -> {// 模擬API調用try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "API response";});}
}

3.4 分布摘要(DistributionSummary)

分布摘要用于記錄值的分布情況,適用于不涉及時間的測量,如響應體大小。

import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class ResponseService {private final DistributionSummary responseSizeSummary;public ResponseService(MeterRegistry meterRegistry) {this.responseSizeSummary = DistributionSummary.builder("response.size").description("Response size distribution").baseUnit("bytes").register(meterRegistry);}public void processResponse(String response) {// 記錄響應大小responseSizeSummary.record(response.getBytes().length);}
}

4 監控HTTP請求

Spring Boot會自動監控HTTP請求,并提供一些默認的Metrics,如請求數量、響應時間等。您可以通過以下配置自定義這些指標:

management:metrics:web:server:request:autotime:enabled: truemetric:name: http.server.requests

還可以通過自定義過濾器來增強HTTP監控:

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class MetricFilter extends OncePerRequestFilter {private final MeterRegistry meterRegistry;public MetricFilter(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String path = request.getRequestURI();String method = request.getMethod();meterRegistry.counter("http.requests.total", "method", method, "path", path).increment();long start = System.currentTimeMillis();try {filterChain.doFilter(request, response);} finally {long duration = System.currentTimeMillis() - start;meterRegistry.timer("http.requests.duration","method", method,"path", path,"status", String.valueOf(response.getStatus())).record(duration, TimeUnit.MILLISECONDS);}}
}

5 自定義MeterFilter

MeterFilter允許您修改或過濾Metrics。例如,可以重命名Metrics,或刪除一些不必要的Metrics。

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.config.MeterFilterReply;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MicrometerConfig {@Beanpublic MeterFilter renameFilter() {return MeterFilter.renameTag("http.server.requests", "method", "http_method");}@Beanpublic MeterFilter ignoreTagFilter() {return MeterFilter.ignoreTag("uri");}@Beanpublic MeterFilter denyFilter() {return MeterFilter.deny(id -> {String meterName = id.getName();// 拒絕以"temp"開頭的指標return meterName != null && meterName.startsWith("temp");});}
}

6 查看監控數據

啟動Spring Boot應用后,您可以訪問/actuator/prometheus端點查看Prometheus格式的監控數據。

示例輸出

# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{application="my-app",area="heap",id="Eden Space",} 1.2632928E7

7 常見問題與解決方案

  1. Metric名稱沖突
    如果應用中使用了多個庫,它們都使用了相同的Metric名稱,可能會導致沖突。解決這個問題的方法是使用不同的標簽來區分這些Metrics。

  2. 性能問題
    如果應用需要記錄大量的Metrics,可能會導致性能問題。解決這個問題的方法是減少Metrics的數量,或者使用更高效的監控系統。

  3. 數據丟失
    如果監控系統出現故障,可能會導致數據丟失。解決這個問題的方法是使用高可用的監控系統,并定期備份數據。

  4. 指標基數爆炸
    避免使用高基數的標簽(如用戶ID),這會導致指標數量急劇增加,影響監控系統性能。

8 最佳實踐

  1. 標簽設計:使用有限且一致的標簽值集合,避免高基數標簽。

  2. 命名規范:使用"."分隔小寫單詞字符,Micrometer會自動轉換為各監控系統適應的格式。

  3. 監控策略:只監控關鍵指標,避免過度監控導致系統負載過重。

  4. 異常處理:確保指標記錄不會影響主要業務邏輯,妥善處理異常。

  5. 文檔化:為自定義指標提供清晰的文檔說明,包括指標名稱、標簽含義和預期值范圍。

9 總結

通過Spring Boot集成Micrometer,我們可以為應用快速添加一個功能強大的"監控儀表盤",實時了解應用的各項指標,如CPU使用率、內存占用、請求響應時間等。Micrometer作為監控門面,讓我們能夠靈活選擇監控后端,而無需修改代碼。

關鍵要點

  • Micrometer提供與供應商無關的監控指標接口

  • Spring Boot自動配置簡化了集成過程

  • 合理使用標簽和命名規范避免常見問題

  • 結合Grafana等可視化工具可以更好地展示監控數據

通過本文介紹的方法,我們可以快速為Spring Boot應用添加監控功能,及時發現并解決性能問題,確保應用的穩定性和可靠性。

彩蛋

監控參數使用prometheus+grafana展示出來,如下圖所示:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/923652.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/923652.shtml
英文地址,請注明出處:http://en.pswp.cn/news/923652.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【運維】-- 前端會話回放與產品分析平臺之 openreplay

目錄 OpenReplay 項目分析 1、項目概覽 2、關鍵特性 3、代碼結構&#xff08;Monorepo&#xff09; 4、技術棧與語言占比 5、部署與交付 6、社區與支持 7、版本與活躍度&#xff08;截至倉庫頁面所示&#xff09; 8、適用場景 9、優勢與注意事項 10、落地建議&#…

NineData社區版 V4.5.0 正式發布!運維中心新增細粒度任務權限管理,新增MySQL至Greenplum全鏈路復制對比

NineData 社區版 V4.5.0 正式發布&#xff01;在數據復制方面&#xff0c;新增 MySQL 至 Greenplum 全鏈路復制對比&#xff0c;并優化全局 DDL 管控、MySQL/PostgreSQL/MongoDB 同構性能。在數據庫 DevOps 方面&#xff0c;新增支持 AWS RDS 全系列及阿里云 PolarDB&#xff0…

discuz所有下載版本和升級工具

下載版本: Discuz! 每日構建版下載 - DiscuzX 3.x Daily Build Download Site SC是簡體中文 TC是繁體中文 可能你需要其他版本: Discuz!官方網站 - 開放、連接、共贏 下載簡體中文就好。 升級工具: 升級程序下載地址 https://gitee.com/oldhuhu/DiscuzX34235.git(…

【開題答辯全過程】以 “紅色棗莊”旅游網站為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

【LeetCode】2785. 將字符串中的元音字母排序

題目描述 題目鏈接 問題分析 這道體的思路非常簡單和好理解&#xff0c;找出字符串中的元音字符&#xff0c;然后按照ASSIC值進行排序&#xff0c;然后插入回對應的位置&#xff0c;解題步驟為&#xff1a; 使用一個set&#xff08;可以快速查找的容器&#xff09;&#x…

3 步發 10 億郵件,這個 GitHub 開源項目牛逼。

你是否要經常批量發郵件&#xff1f;無論是向客戶推送最新資訊、產品營銷&#xff0c;還是發送日常常規通知類郵件。使用第三方郵件服務平臺不僅成本高昂&#xff0c;功能限制多&#xff0c;而且可能無法保證隱私和安全。現在&#xff0c;有一個完全開源、能自己部署的解決方案…

【計算機網絡】DNS 解析 DNS 污染

1. DNS 解析&#xff08;工作流程、參與方與緩存&#xff09; DNS 的目標&#xff1a;把人類可讀的域名&#xff08;如 www.example.com&#xff09;映射為 IP 地址&#xff08;如 93.184.216.34&#xff09;。 典型解析流程&#xff08;遞歸解析器 迭代查詢&#xff09;&…

用住宿樓模型徹底理解Kubernetes架構(運行原理視角)

導讀&#xff1a;從樓宇建設到租客入住的全流程想象我們正在建設一棟巨型智能住宿樓&#xff0c;從基礎設施搭建到租客入住管理&#xff0c;每個環節都對應Kubernetes的組件和概念。本文將按運行原理的先后順序&#xff0c;系統解析Kubernetes的23個核心組件與基本概念。把 Kub…

嘉銀科技基于阿里云 Kafka Serverless 提升業務彈性能力,節省成本超過 20%

作者&#xff1a;四牛 前言 云消息隊列 Kafka 版 Serverless 系列憑借其秒級彈性擴展、按需付費、輕運維的優勢&#xff0c;助力嘉銀科技業務系統實現靈活擴縮容&#xff0c;在業務效率和成本優化上持續取得突破&#xff0c;保證服務的敏捷性和穩定性&#xff0c;并節省超過 20…

RTOS 任務狀態與調度機制詳解

一、任務狀態概述在實時操作系統&#xff08;RTOS&#xff09;中&#xff0c;任務通常具有以下幾種基本狀態&#xff1a;Running&#xff08;運行態&#xff09;&#xff1a;任務正在 CPU 上實際執行。單核系統中同一時刻最多只有一個任務處于運行態。Ready&#xff08;就緒態&…

TDengine 特殊選擇函數 UNIQUE 用戶手冊

UNIQUE 函數用戶手冊 函數定義 UNIQUE(expr)功能說明 UNIQUE() 函數返回指定列去重后的值&#xff0c;功能類似于 SQL 中的 DISTINCT 關鍵字。對于相同的數據值&#xff0c;UNIQUE 函數會返回時間戳最小的那一條記錄。該函數會跳過 NULL 值。 版本要求 最低版本: v3.0.0.0…

新零售第一階段傳統零售商的困境突破與二次增長路徑:基于定制開發開源AI智能名片S2B2C商城小程序的實踐探索

摘要&#xff1a;新零售第一階段&#xff0c;傳統零售商面臨同質化競爭、用戶消費意愿低迷、線上電商分流等核心困境。本文以定制開發開源AI智能名片S2B2C商城小程序為切入點&#xff0c;結合阿里巴巴、某知名連鎖零售企業等實踐案例&#xff0c;分析其通過“AI智能推薦供應鏈協…

Spark SQL 之 Join Reorder

參考鏈接 https://www.cnblogs.com/fxjwind/p/14768975.html join Reorder src/main/scala/org/apache/spark/sql/catalyst/optimizer/CostBasedJoinReorder.scala private def reorder(plan: LogicalPlan, output: Seq[Attribute]): LogicalPlan = {<

牛客周賽 Round 109

比賽鏈接&#xff1a;牛客競賽_ACM/NOI/CSP/CCPC/ICPC算法編程高難度練習賽_牛客競賽OJ A-小紅的直角三角形_牛客周賽 Round 109 簽到題&#xff1a;用勾股定理即可通過此題&#xff08;需要注意對共線情況的判斷&#xff09; 代碼&#xff1a; // Problem: 小紅的直角三角…

[deepseek]LNK2001錯誤即單獨編譯匯編并鏈接

方案一&#xff1a;使用預編譯的 .obj 文件&#xff08;最簡單&#xff09; 如果匯編代碼不常改動&#xff0c;這是最省事的方法。手動編譯一次&#xff1a; 打開命令行&#xff0c;切換到 spoof.asm 所在目錄。使用你已有的匯編器&#xff08;或者下載一個單獨的 MASM 版本&am…

php學習 (第六天)

虛擬主機 一.什么是虛擬主機&#xff1f; 1.1 概念虛擬主機&#xff08;Web Hosting&#xff09;英文&#xff1a;Web Hosting / Shared Hosting核心概念&#xff1a; 一臺服務器被切分給多個用戶&#xff0c;每個人只使用服務器的一部分資源&#xff08;CPU、內存、帶寬、存儲…

AcousticsML聲學機器學習翻譯教程二(特征提取Feature Etraction)

源自&#xff1a;https://github.com/RAMshades/AcousticsM 特征提取 特征是可測量的屬性&#xff0c;作為系統的輸入。這些輸入與特定數據樣本相關&#xff0c;機器學習模型可通過解讀這些特征來提供預測。特征通常具有獨立性&#xff0c;并能提供樣本的具體細節。音頻特征示例…

【論文閱讀】Beyond Text: Frozen Large Language Models in Visual Signal Comprehension

本論文研究了能否利用一個“凍結”的LLM&#xff0c;直接理解視覺信號&#xff08;即圖片&#xff09;&#xff0c;而不用在多模態數據集上進行微調。核心思想是把圖片看作一種“語言實體”&#xff0c;把圖片轉換成一組離散詞匯&#xff0c;這些詞匯來自LLM自己的詞表。為此&a…

The Oxford-IIIT寵物圖像識別數據集(753M)

0、引言博主研究生期間做的是人工智能領域相關的深度學習模型研究&#xff0c;早期還沒定題的時候調研了大量方向。眾所周知&#xff0c;模型性能的好壞很大程度上依賴于數據集&#xff0c;因此我當時也接觸了大量數據集&#xff0c;這陣子將這些數據集匯總整理了一下&#xff…

jdbc DAO封裝及BaseDAO工具類

DAO概念 DAO&#xff1a;Data Access Object&#xff0c;數據訪問對象。 Java是面向對象語言&#xff0c;數據在Java中通常以對象的形式存在。一張表對應一個實體類&#xff0c;一張表的操作對應一個DAO對象&#xff01; 在Java操作數據庫時&#xff0c;我們會將對同一張表的增…