之前介紹了Sentinel相關的文章,小夥伴在生產實踐中不知道有沒有這個疑問?我們的Sentinel控制檯監控的資料只能看最近5分鐘的,如圖
那麼就導致歷史資料是檢視不了的,那肯定是不行的,在生產環境中我們最起碼能夠看到最近幾天甚至幾個月的監控資料,方便我們排查出哪些時間段/哪些天,哪些介面會到達什麼樣的QPS;方便我們對整體系統的QPS、以及異常情況有基本的瞭解。
如果要做到這些,就需要做到對這些資料進行持久化,而不能只儲存在記憶體中。那我們今天就來介紹一下怎麼改造Sentinel控制檯,可以達到持久化的目的。同時用XMind畫了一張導圖記錄Spring Cloud Alibaba的學習筆記(原始檔對部分節點有詳細備註和參考資料,由於太大就沒展示全部,歡迎關注我的公眾號:阿風的架構筆記 後臺傳送【導圖】拿下載連結, 已經完善更新):
分析
Sentinel客戶端會記錄資源訪問的秒級資料(若沒有訪問則不進行記錄)並儲存在本地日誌中。Sentinel 控制檯可以通過 Sentinel 客戶端預留的 HTTP API 從秒級監控日誌中拉取監控資料,並進行聚合。
目前Sentinel控制檯中監控資料聚合後直接存在記憶體中,未進行持久化,且僅保留最近 5 分鐘的監控資料。核心思想就是實現MetricsRepository介面實現,原始碼如下
MetricsRepository定義了以下介面:
save 與 saveAll:儲存對應的監控資料
queryByAppAndResourceBetween:查詢某段時間內的某個應用的某個資源的監控資料
listResourcesOfApp:查詢某個應用下的所有資源
現在Sentinel控制檯只實現了記憶體InMemoryMetricsRepository,介面可傳入自定義範型
上面預設的監控資料型別為MetricEntity,包含應用名稱、時間戳、資源名稱、異常數、請求通過數、請求拒絕數、平均響應時間等資訊。
對於監控資料的儲存,使用者需要根據自己的儲存精度,來考慮如何儲存這些監控資料。部署多個控制檯例項時,通常需要仔細設計下監控拉取和寫入策略。
我們知道了Sentinel的實現,那我們持久化監控的方案是什麼呢?
方案
我們把監控資料持久化到哪裡呢?能想到的就是資料庫,但不要選擇mysql資料庫,而是選擇帶時序功能的資料庫方案,可採用主流的InfluxDB時序資料庫
具體InfluxDB和mysql有什麼區別,可網上檢視
持久化是第一步,我們下一步還需要用圖表的方式展現出來,我們第一個能夠想到的方案就是Grafana。
小夥伴如果不瞭解,自行網補
這樣我們具體的方案就有了,如圖
程式碼
現在Sentinel控制檯專案pom.xml中引入influxdb包
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
<version>2.21</version>
</dependency>
封裝一個influxdb工具類
- url、username、password用於儲存InfluxDB的連線、使用者名稱、密碼資訊,定義為static屬性,因此在set方法上使用@Value註解從配置檔案讀取屬性值;
- resultMapper用於查詢結果到實體類的對映;
- init方法用於初始化url、username、password;
- process為通用的處理方法,負責開啟關閉連線,並且呼叫InfluxDBCallback回撥方法;
- insert為插入資料方法,配合InfluxDBInsertCallback回撥使用;
- query為通用的查詢方法,配合InfluxDBQueryCallback回撥方法使用,返回QueryResult物件;
- queryList為查詢列表方法,呼叫query得到QueryResult,再通過resultMapper轉換為List<實體類>;
**在resources目錄下的application.properties檔案中,增加InfluxDB的配置: **
influxdb.url=http://127.0.0.1:8086
influxdb.username=admin
influxdb.password=admin
在datasource.entity包下,新建influxdb包,下面新建sentinel_metric資料表(measurement)對應的實體類MetricPO:
該類參考MetricEntity建立,加上influxdb-java包提供的註解
通過@Measurement(name = "sentinel_metric")指定資料表(measurement)名稱
time作為時序資料庫的時間列;
app、resource設定為tag列,通過註解標識為tag=true;
其它欄位為filed列;
接著在InMemoryMetricsRepository所在的repository.metric包下新建InfluxDBMetricsRepository類,實現MetricsRepository
其中:
- save、saveAll方法通過呼叫InfluxDBUtils.insert和InfluxDBInsertCallback回撥方法,往sentinel_db庫的sentinel_metric資料表寫資料;
- saveAll方法不是迴圈呼叫save方法,而是在回撥內部迴圈Iterable
metrics處理,這樣InfluxDBFactory.connect連線只開啟關閉一次; - doSave方法中,.time(DateUtils.addHours(metric.getTimestamp(), 8).getTime(), TimeUnit.MILLISECONDS)
- queryByAppAndResourceBetween、listResourcesOfApp裡面的查詢方法,使用InfluxDB提供的類sql語法,編寫查詢語句即可。
最後一步,在MetricController、MetricFetcher兩個類,找到metricStore屬性,
在@Autowired註解上面加上@Qualifier("influxDBMetricsRepository")註解:
到此持久化就完成了,可以啟動測試一下,就可以發現influxdb進入了監控資料
監控
部署安裝Grafana這裡就不介紹了,自行網補;Grafana有模板的概念,只要配置了模板,然後動態傳入引數即可快速生成多個使用相同模板的不同指標資料的圖表。
新增模板
然後配置SQL執行查詢,即時可看到效果
配置好以後使用模板功能檢視多個介面的流控指標監控
具體Grafana配置,小夥伴們可以自行網補
方案優化
上面我們已經實現了監控資料持久化到influxDB中了,但是我們會發現一寫問題
1、sentinel-dashboard目前是每隔一秒從所有的客戶端同步一次資料, 叢集龐大的情況下,控制檯需要拉取很多客戶端的資料,效率很低且不穩定,看原始碼
2、sentinel-dashboard收集到資料以後直接插入資料庫沒有緩衝,吞吐量低,效能低
基於上面的問題我們可以優化一下方案
優化方案
優化點
-
增加一個服務Sentinel Server,用來就是收集監控資料
-
Sentinel客戶端主動推送給Sentinel Server,不需要去拉;這樣就解決了叢集大的情況
-
增加kafka訊息中介軟體,做了資料的緩衝,效能以及吞吐量會大大提升
-
Sentinel Server釋出以及訂閱監控資料訊息
這個優化方案就要把Sentinel控制檯中的監控業務移除掉
總結
這篇文章最主要解決了監控資料持久化監控的問題,涉及到最終的優化方案有時間後續文章介紹,希望這篇文章能夠幫助小夥伴們,謝謝!!!
看完三件事❤️
如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
- 關注公眾號 『 阿風的架構筆記 』,不定期分享原創知識。
- 同時可以期待後續文章ing?
- 關注後回覆【666】掃碼即可獲取架構進階學習資料包