在使用Spring Boot應用過程中,為了對系統(tǒng)的狀態(tài)進行持續(xù)地觀測,您可以將Spring Boot應用接入Prometheus監(jiān)控。本文介紹如何將Spring Boot應用快速接入Prometheus監(jiān)控。
背景信息
對于開發(fā)者而言,大部分傳統(tǒng)SSM結構的MVC應用背后的糟糕體驗都是來自于搭建項目時的大量配置,稍有不慎就可能導致配置出錯。為了解決這個問題,Spring Boot應運而生。Spring Boot的核心價值就是自動配置,只要存在相應Jar包,Spring Boot可以自動配置,如果默認配置不能滿足需求,您還可以替換掉自動配置類,使用自定義配置快速構建企業(yè)級應用程序。
構建Spring Boot應用以及該應用上線之后,您需要對該應用進行監(jiān)測。一般來說,搭建一套完整易用的監(jiān)測系統(tǒng)主要包含以下幾個關鍵部分。
收集監(jiān)測數(shù)據(jù)
目前,行業(yè)常見的收集監(jiān)測數(shù)據(jù)方式主要分為推送(Push)和抓取(Pull)兩個模式。以越來越廣泛應用的Prometheus監(jiān)測體系舉例,可觀測監(jiān)控 Prometheus 版就是以抓取(Pull)模式運行的典型系統(tǒng)。應用及基礎設施的監(jiān)測數(shù)據(jù)以OpenMetrics標準接口的形式暴露給可觀測監(jiān)控 Prometheus 版,然后由可觀測監(jiān)控 Prometheus 版進行定期抓取并長期存儲。
OpenMetrics,是云原生、高度可擴展的指標協(xié)議。 OpenMetrics定義了大規(guī)模上報云原生指標的事實標準,并支持文本表示協(xié)議和Protocol Buffers協(xié)議,文本表示協(xié)議在其中更為常見,也是在可觀測監(jiān)控 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值為GET的一次采樣點數(shù)據(jù)。采樣點內包含一個Float64值和一個毫秒級的UNIX時間戳。隨著時間推移,這些收集起來的采樣點數(shù)據(jù)將在圖表上實時繪制動態(tài)變化的線條。
目前,對于云原生體系下的絕大多數(shù)基礎組件能夠支持OpenMetrics的文本協(xié)議格式暴露指標,對于暫不能支持自身暴露指標的組件, Prometheus社區(qū)也存在極其豐富的Prometheus Exporter供開發(fā)及運維人員使用。這些組件(或Exporter)通過響應來自可觀測監(jiān)控 Prometheus 版的定期抓取請求來及時地將自身的運行狀況記錄到可觀測監(jiān)控 Prometheus 版以便后續(xù)的處理及分析。對于應用開發(fā)者,您還可以通過可觀測監(jiān)控 Prometheus 版的多語言SDK,進行代碼埋點,將自身的業(yè)務指標也接入到上述的Prometheus生態(tài)當中。
數(shù)據(jù)可視化及分析
在獲取應用或基礎設施運行狀態(tài)、資源使用情況,以及服務運行狀態(tài)等直觀信息后,通過查詢和分析多類型、多維度信息能夠方便地對節(jié)點進行跟蹤和比較。同時,通過標準易用的可視化大盤去獲知當前系統(tǒng)的運行狀態(tài)。比較常見的解決方案就是Grafana,作為開源社區(qū)中目前熱度很高的數(shù)據(jù)可視化解決方案,Grafana提供了豐富的圖表形式與模板。在可觀測監(jiān)控 Prometheus 版中,也為您提供了基于Grafana全托管版的監(jiān)測數(shù)據(jù)查詢、分析及可視化。
及時的告警和應急管理
當業(yè)務即將出現(xiàn)故障時,監(jiān)測系統(tǒng)需要迅速反應并通知管理員,從而能夠對問題進行快速的處理或者提前預防問題的發(fā)生,避免出現(xiàn)對業(yè)務的影響。當問題發(fā)生后,管理員需要對問題進行認領和處理。通過對不同監(jiān)測指標以及歷史數(shù)據(jù)的分析,能夠找到并解決根源問題。
接入流程概述
針對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,應用則能夠對接各種監(jiān)測系統(tǒng)。例如,AppOptics、Datadog、Elastic、InfluxDB以及可觀測監(jiān)控 Prometheus 版等。
Micrometer在將可觀測監(jiān)控 Prometheus 版指標對接到Java應用的指標時,支持應用開發(fā)者用三個類型的語義來映射:
Micrometer指標類型 | 可觀測監(jiān)控 Prometheus 版監(jiān)控的指標類型 | 典型用途 |
Counter | Counter | 計數(shù)器,單調遞增場景。例如,統(tǒng)計PV和UV,接口調用次數(shù)等。 |
Gauge | Gauge | 持續(xù)波動的變量。例如,資源使用率、系統(tǒng)負載、請求隊列長度等。 |
Timer | Histogram | 統(tǒng)計數(shù)據(jù)分布。例如,統(tǒng)計某接口調用延時的P50、P90、P99等。 |
DistributionSummary | Summary | 統(tǒng)計數(shù)據(jù)分布,與Histogram用途類似。 |
Micrometer中的Counter指標類型對應于可觀測監(jiān)控 Prometheus 版中的Counter指標類型,用來描述一個單調遞增的變量。如某個接口的訪問次數(shù)、緩存命中或者訪問總次數(shù)等。Timer在邏輯上蘊含了Counter,即如果使用Timer采集每個接口的響應時間,必然也會采集訪問次數(shù)。因此無需為某個接口同時指定Timer與Counter兩個指標。
MicroMeter中的Gauge指標類型對應于可觀測監(jiān)控 Prometheus 版中的Gauge指標類型,用來描述在一個范圍內持續(xù)波動的變量。如CPU使用率、線程池任務隊列數(shù)等。
MicroMeter中的Timer指標類型對應于可觀測監(jiān)控 Prometheus 版中的Histogram,用來描述與時間相關的數(shù)據(jù)。如某個接口RT時間分布等。
Micrometer中的DistributionSummary指標類型對應可觀測監(jiān)控 Prometheus 版中的Summary指標類型 ,與Histogram類似,Summary也是用于統(tǒng)計數(shù)據(jù)分布的,但由于數(shù)據(jù)的分布情況是在客戶端計算完成后再傳入可觀測監(jiān)控 Prometheus 版進行存儲,因此Summary的結果無法在多個機器之間進行數(shù)據(jù)聚合,無法統(tǒng)計全局視圖的數(shù)據(jù)分布,使用起來有一定局限性。
接入流程
當您需要把部署在Kubernetes集群中的Spring Boot應用接入到可觀測監(jiān)控 Prometheus 版時,需要按照代碼埋點>部署應用>服務發(fā)現(xiàn)這個流程來進行。
首先,您需要在代碼中引入Spring Boot Actuator相關Maven依賴,并對您需要監(jiān)測的數(shù)據(jù)進行注冊,或對Controller內的方法打上相應的注解。
其次,您需要將埋點后的應用部署在Kubernetes中,并向可觀測監(jiān)控 Prometheus 版注冊向應用拉取監(jiān)測數(shù)據(jù)的端點(即可觀測監(jiān)控 Prometheus 版的服務發(fā)現(xiàn))。阿里云Prometheus服務提供了使用ServiceMonitor CRD進行服務發(fā)現(xiàn)的方法。
最后,在目標應用的監(jiān)測采集端點被可觀測監(jiān)控 Prometheus 版成功發(fā)現(xiàn)后,您就可以在Grafana上配置數(shù)據(jù)源及相應的大盤。同時您也可以根據(jù)某些關鍵指標進行對應的告警配置。
最終目標
通過將部署在Kubernetes集群中的Spring Boot應用接入到可觀測監(jiān)控 Prometheus 版,希望能夠實現(xiàn)以下幾點目標:
監(jiān)測系統(tǒng)的入口:Frontend服務是一個基于SpringMVC開發(fā)的入口應用,承接外部的客戶流量,這里主要關注的是外部接口的關鍵RED指標。例如,調用率Rate、失敗數(shù)Error、請求耗時Duration。
監(jiān)測系統(tǒng)的關鍵鏈路:對后端服務critical path上的對象進行監(jiān)測。例如,線程池的隊列情況、進程內Guava Cache緩存的命中情況。
實現(xiàn)對業(yè)務強相關的自定義指標進行監(jiān)測。例如,某個接口的UV等。
實現(xiàn)對JVM GC及內存使用情況進行監(jiān)測。
實現(xiàn)對上述指標進行統(tǒng)一匯聚展示,以及配置關鍵指標的告警。
步驟一:引入Spring Boot Actuator依賴,進行初始配置
這里選取一個基于Spring Boot和Spring Cloud Alibaba構建的云原生微服務應用,為您介紹部署在Kubernetes集群上的Spring Boot微服務應用如何進行Prometheus接入的具體接入流程。
執(zhí)行如下代碼段,引入Spring Boot Actuator的相關依賴。
<!-- 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中添加相關配置暴露監(jiān)測數(shù)據(jù)端口。例如,端口為8091。
# application.properties添加以下配置用于暴露指標 spring.application.name=frontend management.server.port=8091 management.endpoints.web.exposure.include=* management.metrics.tags.application=${spring.application.name}
配置成功后,即可訪問該應用的8091端口,然后您可以在該端口的/actuator/prometheus路徑中獲取OpenMetrics標準的監(jiān)測數(shù)據(jù)。
步驟二:代碼埋點及改造
若要獲取某個API接口的RED指標,您需要在對應的接口方法上打@Timed注解。這里以index頁面接口為例打@Timed注解,如下代碼段所示。
@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";
}
其中value即為暴露到/actuator/prometheus中的指標名字,histogram=true表示暴露這個接口請求時長的histogram直方圖類型指標,便于您后續(xù)計算P90、P99等請求時間分布情況。
若您的應用中使用了進程內緩存庫(例如,最常見的Guava Cache庫等)且需要追蹤進程內緩存的運行狀況,您可以按照Micrometer提供的修飾方法,對于待監(jiān)測的關鍵對象進行封裝。
Guava Cache改造
注入MeterRegistry,這里注入的具體實現(xiàn)是PrometheusMeterRegistry,由Spring Boot自行注入即可。
使用工具類API包裝本地緩存,即如下圖中的GuavaCacheMetrics.monitor。
開啟緩存數(shù)據(jù)記錄,即調用.recordStats()方法。
為Cache對象命名,用于生成對應的指標。
線程池改造
注入MeterRegistry,這里注入的具體實現(xiàn)是PrometheusMeterRegistry。
使用工具類API包裝線程池。
為線程池命名,用于生成對應的指標。
在開發(fā)過程中還會涉及許多業(yè)務強相關的自定義指標,為了監(jiān)測這些指標,在往Bean中注入MeterRegistry后,您還需要按照需求和對應場景構造Counter、Gauge或Timer來進行數(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!";
}
}
至此,您對應用的代碼改造工作已全部完成。然后您需要將應用鏡像重新構建并部署到已安裝可觀測監(jiān)控 Prometheus 版的Kubernetes集群中,并在可觀測監(jiān)控 Prometheus 版控制臺中配置ServiceMonitor,進行服務發(fā)現(xiàn)。更多信息,請參見Prometheus實例 for 容器服務和管理Kubernetes集群服務發(fā)現(xiàn)。
ServiceMonitor配置完成后,您可以在Targets列表中查看到剛注冊的Service應用。
步驟三:看板配置
應用的監(jiān)測數(shù)據(jù)已成功收集并存儲到可觀測監(jiān)控 Prometheus 版,因此您可以配置相應的大盤及告警來查看監(jiān)控到的數(shù)據(jù)。這里,為您提供以下兩個Grafana社區(qū)中的開源大盤模板來構建您自己的業(yè)務監(jiān)測模板。
借助以上模板以及可觀測監(jiān)控 Prometheus 版內置的Grafana服務,您可以根據(jù)自己的需求,將日常開發(fā)和運維過程中需要重點關注的指標展示在同一個Grafana Dashboard頁面上,創(chuàng)建屬于您的個性化大盤,便于日常監(jiān)測。例如,這里基于上述模板和自身業(yè)務構建了一個真實的大盤,包含總覽、組件運行時間,內存使用率、堆內堆外內存、分代GC情況等。