1
通過上期的分享,我們對 Metrics 類庫有了較深入的認識,並對指標監控的幾個度量類型瞭如指掌。
本期,我們將走進當下最火的流式處理框架 flink 的源碼,一同深入並學習一下別人家的代碼。
2
會當凌絕頂,一覽眾山小。先從全局瞭解個梗概,然後再採用剝洋蔥的方式逐層去解密。
我本地的源碼是 flink-1.8.1 版本,打開源碼,進入 flink-metrics 模塊,發現很多以 flink-metrics-開頭的系列模塊。
映入眼簾的 flink-metrics 系列模塊雖然很多,不用發愁。其實主要分為指標監控基礎核心模塊(flink-metrics-core),以及指標數據監控組件集成模塊(flink-metrics-xxx)兩大類。
2.1
flink-metrics-core 模塊剖析。
開篇提到 Metrics 的幾種度量類型,來看看 flink 是咋定義的?
打開指標監控基礎核心模塊 flink-metrics-core 看個梗概。
不出我們所料,flink 定義了 Metrics 監控中常見的幾種度量規範(Meter、Gauge、Counter、Histogram),畫個簡易的類圖再看的明白些。
不過為了便於管理和區分 Metric,於是就有了 MetricGroup 的定義,那麼編碼時可以直接與 MetricGroup 交互就可以啦。
到這,瞭解了全局,不妨採用剝洋蔥的方式,再去看看每個接口定義的都是啥規範?逐一進行解密。
Meter 定義 getRate() 方法,用於統計系統中某一個事件的速率,定義 getCount() 方法,用於系統中事件的計數統計。
Gauge 是最簡單的度量指標,只有一個簡單的返回值,定義 getValue() 方法,用來獲取一些對象或者事物的瞬時值。
Counter 累計型的度量指標,定義 inc() 累加方法,以及 dec() 累減等方法。
Histogram 是一種非常常見的統計圖表,統計數據的分佈情況,其中定義的 getStatistics() 方法,提供了最小值,最大值,中間值等對應的計算支撐。
其中 HistogramStatistics 定義如下。
指標對外披露,flink 是咋定義的?
是否還記得上期的分享中,如何把指標數據披露出去的?沒錯,那就是有一系列的 Reporter 來完成的事情,接下來看看 flink 有沒有類似的規範定義呢?
也是沒出我們所料,flink 定義了專門用於指標報告的規範,畫個簡易的類圖,從全局上稍微看的明白些。
如上圖示意,flink 定義了 MetricReporter 用於規定指標披露規範,其中 AbstractReporter 提供了 MetricReporter 接口的簡單的實現。Scheduled 接口用於定義數據披露方案,提供定期性的披露當前數據的支持。
那麼,不妨採取剝洋蔥的方式,逐個再去看看都是啥,能意會就行啦。
MetricReporter 是 flink 定義的指標披露的接口規範,方法名字其實已經很明確啦,再解說一二。其中 open() 方法主要用於初始化相關操作;close() 主要是關閉 Reporter,用於釋放資源;notifyOfAddedMetric()/notifyOfRemovedMetric() 定義新指標註冊以及指標刪除時通知。
如上圖示意,AbstractReporter 抽象類實現了接口 MetricReporter,並擁有 gauges、counters、histograms、meters 四個度量類型的 Map 容器,並對接口 MetricReporter 中定義的 notifyOfAddedMetric()/notifyOfRemovedMetric() 提供了簡單實現。
Scheduled 接口很簡單,定義了 report() 方法,用於定期披露當前指標數據。
上面對 flink-metrics-core 指標監控核心定義模塊,有了初步的認識,那麼看看這些規範到底是怎麼用的?
2.2
flink-metrics-prometheus 模塊剖析。
從全局上了解個梗概,畫個簡易的類圖,稍微看的更清晰。
很顯然,針對 Prometheus 做了支撐,沒有使用 flink-metrics-core 包中的 AbstractReporter 類,而是對 MetricReporter 進行了單獨實現,不妨我們去看個梗概。
見名知意,AbstractPrometheusReporter 是對 Prometheus 輪子單獨定義的,實現了 MetricReporter 接口定義的方法,肯定少不了去迎合 Prometheus 的代碼,摘取部分核心代碼剖析一下。
如上圖所示,notifyOfAddedMetric() 方法主要按照 Prometheus 的規範進行封裝成 io.prometheus.client.Collector,以及調用 Prometheus 提供的方法對 Metric 進行轉換封裝(說白了,就是按照 Prometheus 的規範進行轉換,不懂也沒關係,因為每個輪子的實現均不同)。
再去看 AbstractPrometheusReporter 實現類 PrometheusPushGatewayReporter 的源碼之前,不妨先扒拉出以往分享 Prometheus 實戰中的一張圖,解說一二。
如圖示意,要完成數據源層的 AppService 的指標監控,需要對應用納入一個 Client lib 來支撐指標產生、輸出,然後通過 push 的形式,主動推送數據到 PushGateway,然後 Prometheus Server 會定期性的從 PushGateway 上拉取指標數據。
知道了流程,我們再去看 flink-metrics-prometheus 的源碼,可能會更清晰。
如源碼所示,PrometheusPushGatewayReporter 類持有 PushGateway 的引用,進而可以使用 Prometheus 提供的 API 進行 push 數據,以及創建連接和釋放資源。
代碼很簡單,open() 方法主要讀取配置文件,進行實例化 PushGateway;report() 方法會調用 PushGateway 提供的 push 方法進行推送數據;close() 方法主要用於釋放資源,從 PushGateway 上把 jobName 對應的 metrics 刪除。
如果你一直追隨一猿小講的腳步的話,那麼會想起之前 flink 監控實踐的一段配置,結合上段代碼,再去看這段配置,就知道這個配置咋回事啦。
搞定了監控數據如何披露出去的,唯獨有一點,還是沒有搞明白?那就是 PrometheusPushGatewayReporter 什麼時候實例化的呢?也就是流程怎麼串起來的呢?
2.3
flink-runtime 模塊中部分代碼剖析。
首先找到flink-runtime 目錄下的 metrics 包中 org.apache.flink.runtime.metrics.MetricRegistryImpl 一探究竟。
截圖為 MetricRegistryImpl 構造方法的部分代碼,其中標註 1 代碼,主要是依據配置內容,構建配置的 Reporter 對象;標註 2 的代碼,調用其 open() 方法,完成初始化動作;標註 3 的代碼,主要是判斷 Reporter 對象有沒有實現 Scheduled 接口,如果實現了,則會通過 executor 進行定期調用 reporter.report() 方法進行報送數據。
瞭解到指標數據如何對外披露,但是 Metric 在哪兒添加的呢?
我們知道 MetricGroup 設計的目的,是為了方便對 Metric 管理,而 AbstractMetricGroup 則對添加 Metric 等相關方法進行了定義實現。
如圖示標註 2 代碼,AbstractMetricGroup 類中會調用 registry.register(metric, name, this) 完成指標的註冊添加,進而會調用 MetricRegistryImpl 的 register 方法。
如圖中標註 2 代碼,會調用對應的 Reporter 的 notifyOfAddedMetric() 方法完成添加指標通知。
此時,代碼懵懵懂,再去看以往實戰的效果圖(Granfna 展示 flink-metrics)的背後,腦海裡應該會清晰不少。
3
flink-metrics 源碼剖析就到這兒,flink 與 prometheus 監控集成剖析也刨到這兒,其實 flink-metrics 與其它輪子集成也是這麼一回事兒,掌握脈略就行了。
另外,flink 作為當下最流行的開源流式處理框架,那麼 flink 定義的指標度量接口規範,勢必會對我們應用監控有建設性的參考意義。
好了,本次分享就到這兒,希望你們能夠喜歡。
閱讀更多 一猿小講 的文章