日常巡檢的檢查順序)
微服務(wù)日常巡檢的檢查順序微服務(wù)巡檢不是每天把所有指標(biāo)看一遍。更有效的做法是先確認(rèn)用戶路徑是否異常再沿入口、依賴、線程與連接池、JVM 和基礎(chǔ)設(shè)施逐層縮小范圍。順序清楚值班人員才能知道下一步該看什么也能避免一看到 CPU 抖動(dòng)就重啟服務(wù)。巡檢項(xiàng)要跟隨系統(tǒng)風(fēng)險(xiǎn)和依賴變化維護(hù)。新接入消息隊(duì)列、修改線程池、升級(jí) JDK 或調(diào)整注冊(cè)中心后對(duì)應(yīng)檢查也要更新一份多年不變的靜態(tài)清單很快會(huì)與真實(shí)架構(gòu)脫節(jié)。第一層先看用戶請(qǐng)求和近期變更從關(guān)鍵入口的成功率、目標(biāo)延遲和任務(wù)完成情況開(kāi)始并按路由或業(yè)務(wù)類型分組。整體平均值正??赡苋杂幸粋€(gè)高價(jià)值接口持續(xù)失敗。流量接近零時(shí)成功率也可能失真應(yīng)同時(shí)看請(qǐng)求量和絕對(duì)錯(cuò)誤數(shù)。把當(dāng)前異常與最近發(fā)布、配置變更、依賴升級(jí)和流量變化放在同一時(shí)間軸。時(shí)間接近不等于根因已經(jīng)確認(rèn)但它能幫助確定優(yōu)先排查范圍。沒(méi)有異常時(shí)日常報(bào)告也應(yīng)標(biāo)明當(dāng)前版本和上次變更方便后來(lái)對(duì)比。健康檢查只是一條信號(hào)。Liveness 回答進(jìn)程是否需要重啟Readiness 決定實(shí)例能否接流業(yè)務(wù)路徑則驗(yàn)證關(guān)鍵功能。端口可訪問(wèn)不能證明線程池、數(shù)據(jù)庫(kù)和注冊(cè)狀態(tài)正常反過(guò)來(lái)下游短時(shí)波動(dòng)也不應(yīng)觸發(fā)所有實(shí)例的 Liveness 失敗并反復(fù)重啟。第二層檢查依賴和流量放大查看上游到本服務(wù)、再到數(shù)據(jù)庫(kù)、緩存、消息隊(duì)列和其他 RPC 的調(diào)用關(guān)系。重點(diǎn)是超時(shí)、重試、連接等待和拒絕。入口流量沒(méi)有變化、內(nèi)部調(diào)用卻明顯增加可能出現(xiàn)重試放大或重復(fù)消費(fèi)。依賴異常時(shí)先確認(rèn)是所有實(shí)例都失敗還是某個(gè)可用區(qū)、連接池或目標(biāo)版本集中出錯(cuò)。DNS、證書(shū)和權(quán)限錯(cuò)誤通常不會(huì)通過(guò)原樣重試恢復(fù)連接中斷或明確的臨時(shí)錯(cuò)誤才可能在預(yù)算內(nèi)有限重試。巡檢報(bào)告需要保留錯(cuò)誤分類而不是統(tǒng)一寫(xiě)成“下游不穩(wěn)定”。服務(wù)發(fā)現(xiàn)要同時(shí)看控制面與調(diào)用端實(shí)際視圖。注冊(cè)中心有實(shí)例不代表客戶端緩存已經(jīng)更新實(shí)例心跳正常也不代表業(yè)務(wù)處理能力正常??梢猿椴樽?cè)版本、實(shí)例狀態(tài)和一次真實(shí)路由結(jié)果但不要讓巡檢繞過(guò)正常負(fù)載均衡直接修改注冊(cè)信息。第三層看線程池、連接池和隊(duì)列Java 服務(wù)常見(jiàn)的“CPU 不高卻很慢”往往與等待有關(guān)。檢查業(yè)務(wù)線程池的 active、pool size、queue size 和 reject數(shù)據(jù)庫(kù)連接池的 active、idle 與等待時(shí)間以及 HTTP 客戶端的連接獲取與進(jìn)行中請(qǐng)求。每個(gè)指標(biāo)都要帶池名稱不能把某個(gè)自定義executor.queued當(dāng)成整個(gè) Tomcat 或 WebFlux 的狀態(tài)。隊(duì)列長(zhǎng)度必須結(jié)合處理速率。短時(shí)出現(xiàn)幾個(gè)等待任務(wù)未必有問(wèn)題持續(xù)增長(zhǎng)且完成速率跟不上入口才說(shuō)明無(wú)法收斂。無(wú)界隊(duì)列不會(huì)顯示“滿”卻會(huì)讓內(nèi)存和等待時(shí)間不斷增長(zhǎng)因此配置巡檢還要確認(rèn)隊(duì)列類型與容量。連接池達(dá)到上限時(shí)不要立刻調(diào)大。先看連接為何長(zhǎng)期占用、超時(shí)是否生效、下游是否變慢。擴(kuò)大每個(gè)實(shí)例的池后再乘以副本數(shù)可能超過(guò)數(shù)據(jù)庫(kù)或服務(wù)端能承受的總連接。第四層再進(jìn)入 JVMJVM 巡檢關(guān)注堆、非堆、GC 暫停、分配速率、線程和類加載但沒(méi)有一條固定閾值適合所有服務(wù)。先建立當(dāng)前 JDK、GC 和負(fù)載下的基線再看趨勢(shì)與用戶延遲是否同時(shí)變化。Metaspace 的max可能沒(méi)有配置成有限值此時(shí)簡(jiǎn)單計(jì)算使用比例沒(méi)有意義。更值得觀察的是類加載數(shù)量、使用量是否在穩(wěn)定流量下持續(xù)增長(zhǎng)以及 Full GC 后能否回落。動(dòng)態(tài)代理、腳本和頻繁創(chuàng)建類加載器只是可能原因需要結(jié)合 Heap Dump、類加載統(tǒng)計(jì)和版本變更驗(yàn)證。GC 暫停也不能孤立解讀。記錄暫停分布、發(fā)生原因、堆占用和分配速率再與請(qǐng)求長(zhǎng)尾對(duì)齊。偶發(fā)暫停不一定影響用戶持續(xù)高分配導(dǎo)致頻繁回收才需要繼續(xù)定位。Heap Dump 與線程 Dump 可能包含業(yè)務(wù)數(shù)據(jù)應(yīng)限制觸發(fā)、訪問(wèn)和保留時(shí)間。Actuator 數(shù)據(jù)先由監(jiān)控系統(tǒng)統(tǒng)一采集Spring Boot Actuator 與 Micrometer 可以暴露運(yùn)行指標(biāo)但具體名稱、標(biāo)簽和可用性取決于版本與已注冊(cè)組件。建立 Prometheus 等采集系統(tǒng)后日常巡檢優(yōu)先查詢統(tǒng)一時(shí)序數(shù)據(jù)而不是額外腳本并發(fā)輪詢每個(gè) Pod。后者會(huì)制造新負(fù)載也難以保留趨勢(shì)。小型環(huán)境確實(shí)需要只讀腳本時(shí)要把“指標(biāo)缺失”與“指標(biāo)為零”分開(kāi)并保護(hù) Actuator 入口。下面的示例只檢查健康狀態(tài)不打印響應(yīng)正文服務(wù)地址來(lái)自受控配置超時(shí)和并發(fā)都有限。它不能替代認(rèn)證、TLS 和集中監(jiān)控。from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass from typing import Literal import requests dataclass(frozenTrue) class Service: name: str base_url: str dataclass(frozenTrue) class Result: service: str status: Literal[UP, DOWN, UNKNOWN] reason: str def inspect(service: Service) - Result: try: response requests.get( f{service.base_url}/actuator/health/readiness, timeout(1, 2), ) if response.status_code ! 200: return Result(service.name, DOWN, fhttp_{response.status_code}) payload response.json() status payload.get(status) if status UP: return Result(service.name, UP, readiness_up) return Result(service.name, DOWN, readiness_not_up) except (requests.RequestException, ValueError) as exc: return Result(service.name, UNKNOWN, type(exc).__name__) def inspect_all(services: list[Service]) - list[Result]: with ThreadPoolExecutor(max_workersmin(4, len(services))) as executor: futures [executor.submit(inspect, service) for service in services] return [future.result() for future in as_completed(futures)]UNKNOWN不能顯示成綠色健康。網(wǎng)絡(luò)、認(rèn)證或響應(yīng)格式問(wèn)題都需要單獨(dú)處理。腳本也不應(yīng)自動(dòng)重啟實(shí)例先保留證據(jù)再由有權(quán)限和審計(jì)的處置流程決定動(dòng)作。告警與日?qǐng)?bào)處理不同時(shí)間尺度需要立即通知的是正在影響用戶并且有人可以處理的狀態(tài)例如關(guān)鍵路徑持續(xù)失敗、隊(duì)列無(wú)法收斂或全部實(shí)例不可用。容量趨勢(shì)、Metaspace 增長(zhǎng)和依賴版本偏差更適合進(jìn)入日?qǐng)?bào)或工單。把所有異常都發(fā)成電話告警只會(huì)消耗值班注意力。去重不應(yīng)僅按Service Metric。同一根因可能讓幾十個(gè)服務(wù)同時(shí)報(bào)警應(yīng)按依賴或調(diào)用拓?fù)渚酆贤恢笜?biāo)在不同集群又可能是兩起事件需要保留環(huán)境標(biāo)簽。靜默規(guī)則設(shè)置開(kāi)始、結(jié)束與負(fù)責(zé)人避免維護(hù)窗口結(jié)束后告警仍被永久壓制。每條告警附上當(dāng)前值、基線、持續(xù)時(shí)間、受影響路徑和一條只讀排查入口。若接收人無(wú)法根據(jù)內(nèi)容決定繼續(xù)觀察、限流或升級(jí)就應(yīng)重新設(shè)計(jì)這條告警。巡檢本身也需要預(yù)算高頻、昂貴的管理查詢會(huì)影響被觀察系統(tǒng)。健康接口保持輕量指標(biāo)由拉取系統(tǒng)按容量采集日志查詢限制時(shí)間和結(jié)果量。不要在業(yè)務(wù)高峰自動(dòng)觸發(fā) Heap Dump也不要讓巡檢賬號(hào)擁有修改配置或重啟服務(wù)的權(quán)限。定期演練指標(biāo)缺失、注冊(cè)異常、線程池拒絕和下游超時(shí)確認(rèn)告警能觸發(fā)、說(shuō)明足夠、恢復(fù)條件明確。規(guī)則修改后先回放歷史數(shù)據(jù)檢查是否把已知波動(dòng)重新變成噪聲。一套可用的巡檢順序應(yīng)該讓值班人員從用戶影響走到具體資源再回到變更和依賴證據(jù)。它不追求指標(biāo)最多而是盡快回答現(xiàn)在是否影響用戶問(wèn)題在哪一層誰(shuí)需要采取什么動(dòng)作。