javascript
最佳实践|Spring Boot 应用如何快速接入 Prometheus 监控
簡介:SpringBoot 微服務的開發(fā)、發(fā)布與部署只占其生命周期的一小部分,應用和系統(tǒng)運維才是重中之重。而運維過程中,監(jiān)控工作更是占據(jù)重要位置。那么,為了對系統(tǒng)的狀態(tài)進行持續(xù)地觀測,面向Spring Boot應用我們該如何快速實現(xiàn)Prometheus監(jiān)控接入。本文為大家詳細講解完整接入流程與接入事項!
作者:凡星
對于開發(fā)者而言,大部分傳統(tǒng) SSM 結(jié)構(gòu)的 MVC 應用背后的糟糕體驗都是來自于搭建項目時的大量配置,稍有不慎就可能踩坑。為了解決上述問題,Spring Boot 應運而生。正如其名,Spring Boot 的核心價值就是自動配置,只要存在相應 jar 包,Spring 可以自動配置。如果默認配置不能滿足需求,還可以替換掉自動配置類,使用自定義配置,快速構(gòu)建企業(yè)級應用程序。
但構(gòu)建 Spring Boot 應用只是第一步,隨著應用上線之后,我們又該如何進行監(jiān)測?
基礎知識及概念
首先,在正式講解前,先向大家講解本次分享所需要的基本知識和概念。一般來說,搭建一套完整易用的監(jiān)測系統(tǒng)主要包含以下幾個關(guān)鍵部分。
收集監(jiān)測數(shù)據(jù)
目前,行業(yè)常見的收集監(jiān)測數(shù)據(jù)方式主要分為推送(Push)和抓取(Pull)兩個模式。以越來越廣泛應用的 Prometheus 監(jiān)測體系舉例,Prometheus 就是以抓取(Pull)模式運行的典型系統(tǒng)。應用及基礎設施的監(jiān)測數(shù)據(jù)以 OpenMetrics 標準接口的形式暴露給 Prometheus,由 Prometheus 進行定期抓取并長期存儲。
這里簡單介紹一下 OpenMetrics。作為云原生、高度可擴展的指標協(xié)議, OpenMetrics 定義了大規(guī)模上報云原生指標的事實標準,并支持文本表示協(xié)議和 Protocol Buffers 協(xié)議,文本表示協(xié)議在其中更為常見,也是在 Prometheus 進行數(shù)據(jù)抓取時默認采用的協(xié)議。下圖是一個基于 OpenMetrics 格式的指標表示格式樣例。
指標的數(shù)據(jù)模型由指標(Metric)名,以及一組 key/value 標簽(Label)定義的,具有相同的度量名稱以及標簽屬于相同時序集合。例如 ?acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 可以表示指標名為 acme_http_router_request_seconds_sum,標簽 method 值為 POST 的一次采樣點數(shù)據(jù)。采樣點內(nèi)包含一個 float64 值和一個毫秒級的 UNIX 時間戳。隨著時間推移,這些收集起來的采樣點數(shù)據(jù)將在圖表上實時繪制動態(tài)變化的線條。
目前,對于云原生體系下的絕大多數(shù)基礎組件,大多能夠支持以上面提到的 OpenMetrics 的文本協(xié)議格式暴露指標,對于尚未能夠支持自身暴露指標的組件, Prometheus 社區(qū)也存在極其豐富的 Prometheus Exporter 供開發(fā)及運維人員使用。這些組件(或 Exporter)通過響應來自 Prometheus 的定期抓取請求來及時地將自身的運行狀況記錄到 Prometheus 以便后續(xù)的處理及分析。對于應用開發(fā)者,還可以通過 Prometheus 多語言 SDK,進行代碼埋點,將自身的業(yè)務指標也接入到上述的 Prometheus 生態(tài)當中。
數(shù)據(jù)可視化及分析
在獲取應用或基礎設施運行狀態(tài)、資源使用情況,以及服務運行狀態(tài)等直觀信息后,通過查詢和分析多類型、多維度信息能夠方便的對節(jié)點進行跟蹤和比較。同時,通過標準易用的可視化大盤去獲知當前系統(tǒng)的運行狀態(tài)。比較常見的解決方案就是 Grafana,作為開源社區(qū)中目前熱度很高的數(shù)據(jù)可視化解決方案,Grafana 提供了豐富的圖表形式與模板。在阿里云 ARMS Prometheus 監(jiān)控服務中,也基于 Grafana 向用戶提供了全托管版的監(jiān)測數(shù)據(jù)查詢、分析及可視化。
及時的告警和應急管理
當業(yè)務即將出現(xiàn)故障時,監(jiān)測系統(tǒng)需要迅速反應并通知管理員,從而能夠?qū)栴}進行快速的處理或者提前預防問題的發(fā)生,避免出現(xiàn)對業(yè)務的影響。當問題發(fā)生后,管理員需要對問題進行認領(lǐng)和處理。通過對不同監(jiān)測指標以及歷史數(shù)據(jù)的分析,能夠找到并解決根源問題。
接入流程概覽
接下來,我們講講面向部署在 Kubernetes 集群上的 Spring Boot 微服務應用如何進行 Prometheus 接入。針對 Spring Boot 應用,社區(qū)提供了開箱即用的 Spring Boot Actuator 框架,方便 Java 開發(fā)者進行代碼埋點和監(jiān)測數(shù)據(jù)收集、輸出。從 Spring Boot 2.0 開始,Actuator 將底層改為 Micrometer,提供了更強、更靈活的監(jiān)測能力。Micrometer 是一個監(jiān)測門面,可以類比成監(jiān)測界的 Slf4j 。借助 Micrometer,應用能夠?qū)痈鞣N監(jiān)測系統(tǒng),例如:AppOptics,Datadog,Elastic,InfluxDB 等,當然,也包括我們今天所介紹的 Prometheus。
Micrometer 在將 Prometheus 指標對接到 Java 應用的指標時,支持應用開發(fā)者用三個類型的語義來映射:
- MicroMeter 中的 Counter 對應于 Prometheus 中的 Counter,用來描述一個單調(diào)遞增的變量,如某個接口的訪問次數(shù),緩存命中/訪問總次數(shù)等。Timer 在邏輯上蘊含了 Counter,即如果使用 Timer 采集每個接口的響應時間,必然也會采集訪問次數(shù)。故無需為某個接口同時指定 Timer 與 Counter 兩個指標
- MicroMeter 中的 Gauge 對應于 Prometheus 中的 Gauge,用來描述在一個范圍內(nèi)持續(xù)波動的變量,如 CPU 使用率,線程池任務隊列數(shù)等。
- MicroMeter 中的 Timer 對應于 Prometheus 中的 Histogram,用來描述與時間相關(guān)的數(shù)據(jù),如某個接口 RT 時間分布等等。
- Micrometer 中的 DistributionSummary 對應 Prometheus 中的 Summary ,與 ?Histogram 類似,Summary 也是用于統(tǒng)計數(shù)據(jù)分布的,但由于數(shù)據(jù)的分布情況是在客戶端計算完成后再傳入 Prometheus 進行存儲,因此 Summary 的結(jié)果無法在多個機器之間進行數(shù)據(jù)聚合,無法統(tǒng)計全局視圖的數(shù)據(jù)分布,使用起來有一定局限性。
當我們需要把部署在 Kubernetes 集群中的 Spring Boot 應用接入到 Prometheus 時,需要按照代碼埋點->部署應用->服務發(fā)現(xiàn)這個流程來進行。
首先,我們需要在代碼中引入 Spring Boot Actuator 相關(guān) maven 依賴,并對我們需要監(jiān)測的數(shù)據(jù)進行注冊,或?qū)?Controller 內(nèi)的方法打上響應的注解。
其次,我們將埋點后的應用部署在 Kubernetes 中,并向 Prometheus 注冊向應用拉取監(jiān)測數(shù)據(jù)的端點(也就是 Prometheus 服務發(fā)現(xiàn))。阿里云 Prometheus 服務提供了使用 ServiceMonitor CRD 進行服務發(fā)現(xiàn)的方法。
最后在目標應用的監(jiān)測采集端點被 Prometheus 成功發(fā)現(xiàn)后,我們就可以開始在 Grafana 上面配置數(shù)據(jù)源及相應的大盤了。當然,我們同時也需要根據(jù)某些關(guān)鍵指標進行對應的告警配置。這些需求在阿里云 Prometheus 監(jiān)控服務都能很方便地滿足。
接入流程詳解
接下來,我們進入實戰(zhàn)演練環(huán)節(jié),這里選取一個基于 Spring Boot & Spring Cloud Alibaba 構(gòu)建的云原生微服務應用(https://github.com/aliyun/alibabacloud-microservice-demo)作為我們改造的基線。
我們最終目標是:
1、監(jiān)測系統(tǒng)的入口:Frontend 服務是一個基于 SpringMVC 開發(fā)的入口應用,承接外部的客戶流量,我們主要關(guān)注的是外部接口的關(guān)鍵 RED 指標(調(diào)用率 Rate,失敗數(shù) Error,請求耗時 Duration);
2、監(jiān)測系統(tǒng)的關(guān)鍵鏈路:對后端服務 critical path 上的對象進行監(jiān)測,如線程池的隊列情況、進程內(nèi) Guava Cache 緩存的命中情況;
3、對業(yè)務強相關(guān)的自定義指標(比如某個接口的 UV 等等);
4、對 JVM GC 及內(nèi)存使用情況進行監(jiān)測;
5、對上述指標進行統(tǒng)一匯聚展示、以及配置關(guān)鍵指標的告警。
第一步,引入 Spring Boot Actuator 依賴,進行初始配置
首先,我們需要引入 Spring Boot Actuator 的相關(guān)依賴,在 application.properties 配置中暴露監(jiān)測數(shù)據(jù)端口(這里定義為 8091)。成功后,我們即可訪問應用的 8091 端口的/actuator/prometheus 路徑拿到 OpenMetrics 標準的監(jiān)測數(shù)據(jù)。
<!-- spring-boot-actuator依賴 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- prometheus依賴 --> <dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId> </dependency> # application.properties添加以下配置用于暴露指標 spring.application.name=frontendmanagement.server.port=8091 management.endpoints.web.exposure.include=* management.metrics.tags.application=${spring.application.name}第二步,代碼埋點及改造
為了獲取某個 Api 接口的 RED 指標,我們需要在對應的接口方法上打下面的 @Timed 注解。我們以演示項目中的 index 頁面接口為例。注意這里,@Timed 注解中的 value 即為暴露到/actuator/prometheus 中的指標名字,histogram=true 表示我們暴露這個接口請求時長的 histogram 直方圖類型指標,便于我們后續(xù)計算 P99,P90 等請求時間分布情況。
@Timed(value = "main_page_request_duration", description = "Time taken to return main page", histogram = true) @ApiOperation(value = "首頁", tags = {"首頁操作頁面"}) @GetMapping("/") public String index(Model model) {model.addAttribute("products", productDAO.getProductList());model.addAttribute("FRONTEND_APP_NAME", Application.APP_NAME);model.addAttribute("FRONTEND_SERVICE_TAG", Application.SERVICE_TAG);model.addAttribute("FRONTEND_IP", registration.getHost());model.addAttribute("PRODUCT_APP_NAME", PRODUCT_APP_NAME);model.addAttribute("PRODUCT_SERVICE_TAG", PRODUCT_SERVICE_TAG);model.addAttribute("PRODUCT_IP", PRODUCT_IP);model.addAttribute("new_version", StringUtils.isBlank(env));return "index.html"; }如果我們的應用中使用了進程內(nèi)緩存庫,比如最為常見的 Guava Cache 庫等等。如果我們想追蹤進程內(nèi)緩存的運行狀況,我們需要按照 Micrometer 提供的修飾方法,對待監(jiān)測的關(guān)鍵對象進行封裝。
- Guava Cache 改造主要是四步驟,代碼改動比較小,很容易就可以接入:
1、注入 MeterRegistry,這里注入的具體實現(xiàn)是 PrometheusMeterRegistry,由 Spring Boot 自行注入即可
2、使用工具類 api,即圖中展示的 GuavaCacheMetrics.monitor 包裝一下本地緩存
3、開啟緩存數(shù)據(jù)記錄,即調(diào)用一下.recordStats()方法
4、增加一個名稱,用于生成對應的指標。
- 線程池改造主要是三步驟,也并不是很復雜:
1、注入 MeterRegistry,這里注入的具體實現(xiàn)是 PrometheusMeterRegistry;
2、使用工具類 api 包裝一下線程池;
3、增加一個名稱,用于生成對應的指標。
當然,我們在開發(fā)過程中一定還有許多業(yè)務強相關(guān)的自定義指標,為了監(jiān)測這些指標,我們在向 Bean 中注入 MeterRegistry 后,需要按照我們的需求和對應場景構(gòu)造 Counter,Gauge 或 Timer(這些類型的區(qū)別和使用場景上文有提到)來進行數(shù)據(jù)統(tǒng)計,并將其注冊到 MeterRegistry 進行指標暴露,下面是一個簡單的例子。
@Service public class DemoService {Counter visitCounter;public DemoService(MeterRegistry registry) {visitCounter = Counter.builder("visit_counter").description("Number of visits to the site").register(registry);}public String visit() {visitCounter.increment();return "Hello World!";} }至此,我們的應用代碼改造工作到這里就全部完成了,下一步工作就是將應用鏡像重新構(gòu)建并重新部署到已安裝 ARMS Prometheus 的 Kubernetes 集群中。之后,我們 ARMS Prometheus 控制臺中配置 ServiceMonitor,進行服務發(fā)現(xiàn)。
添加好 ServiceMonitor 后,我們可以在 Targets 列表中看到剛注冊的應用 Service。
第三步,看板配置
應用的監(jiān)測數(shù)據(jù)已成功收集并存儲到 ARMS Prometheus。接下來,也是最關(guān)鍵的一步,就是根據(jù)這些數(shù)據(jù),配置相應的大盤及告警。這里,我們借助 Grafana 社區(qū)中開源大盤模板來構(gòu)建我們自己的業(yè)務監(jiān)測模板。主要基于以下兩個模板:
- Spring Boot 2.1 Statistics:
Spring Boot 2.1 Statistics dashboard for Grafana | Grafana Labs
- JVM (Micrometer):
JVM (Micrometer) dashboard for Grafana | Grafana Labs
借助這些模板以及 ARMS Prometheus 內(nèi)置的 Grafana 服務,我們可以很方便地將日常開發(fā)和運維過程中非常關(guān)心的指標組織在一張的 Grafana Dashboard 上。這里給大家拋磚引玉一下,放一張我們內(nèi)部基于上述模板和自身業(yè)務構(gòu)建的一個真實的大盤。這里面包含了一些總覽,比如組件運行時間,內(nèi)存使用率等等,也有一些細節(jié)指標,如堆內(nèi)堆外內(nèi)存,分代 GC 情況等等,還有像接口請求的 RED 等等,這里就不過多贅述了,大家可以充分發(fā)揮自己的想象力來創(chuàng)造獨一無二的酷炫大盤~
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的最佳实践|Spring Boot 应用如何快速接入 Prometheus 监控的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里巴巴超大规模 Kubernetes
- 下一篇: gradle idea java ssm