測(cè)試環(huán)境中出現(xiàn)了一個(gè)異常的告警現(xiàn)象:一條告警通過(guò) Thanos Ruler 的 HTTP 接口觀察到持續(xù)處于 active 狀態(tài),但是從 AlertManager 這邊看這條告警為已解決狀態(tài)。按照 DMP 平臺(tái)的設(shè)計(jì),告警已解決指的是告警上設(shè)置的結(jié)束時(shí)間已經(jīng)過(guò)了當(dāng)前時(shí)間。一條發(fā)送至 AlertManager 的告警為已解決狀態(tài)有三種可能:1. 手動(dòng)解決了告警2. 告警只產(chǎn)生了一次,第二次計(jì)算告警規(guī)則時(shí)會(huì)發(fā)送一個(gè)已解決的告警3. AlertManager 接收到的告警會(huì)帶著一個(gè)自動(dòng)解決時(shí)間,如果還沒(méi)到達(dá)自動(dòng)解決時(shí)間,則將該時(shí)間重置為 24h 后首先,因?yàn)榱私獾綔y(cè)試環(huán)境沒(méi)有手動(dòng)解決過(guò)異常告警,排除第一條;其次,由于該告警持續(xù)處于 active 狀態(tài),所以不會(huì)是因?yàn)楦婢划a(chǎn)生了一次而接收到已解決狀態(tài)的告警,排除第二條;最后,告警的告警的產(chǎn)生時(shí)間與自動(dòng)解決時(shí)間相差不是 24h,排除第三條。那問(wèn)題出在什么地方呢?
創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)提供樺南企業(yè)網(wǎng)站建設(shè),專(zhuān)注與做網(wǎng)站、網(wǎng)站設(shè)計(jì)、成都h5網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為樺南眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專(zhuān)業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。
分析
下面我們開(kāi)始分析這個(gè)問(wèn)題。綜合第一節(jié)的描述,初步的猜想是告警在到達(dá) AlertManager 前的某些階段的處理過(guò)程太長(zhǎng),導(dǎo)致告警到達(dá) AlertManager 后就已經(jīng)過(guò)了自動(dòng)解決時(shí)間。我們從分析平臺(tái)里一條告警的流轉(zhuǎn)過(guò)程入手,找出告警在哪個(gè)處理階段耗時(shí)過(guò)長(zhǎng)。首先,一條告警的產(chǎn)生需要兩方面的配合:
metric 數(shù)據(jù)
告警規(guī)則
將 metric 數(shù)據(jù)輸入到告警規(guī)則進(jìn)行計(jì)算,如果符合條件則產(chǎn)生告警。DMP 平臺(tái)集成了 Thanos 的相關(guān)組件,數(shù)據(jù)的提供和計(jì)算則會(huì)分開(kāi),數(shù)據(jù)還是由 Prometheus Server 提供,而告警規(guī)則的計(jì)算則交由 Thanos Rule(下文簡(jiǎn)稱(chēng) Ruler)處理。下圖是 Ruler 組件在集群中所處的位置:
看來(lái),想要弄清楚現(xiàn)告警的產(chǎn)生到 AlertManager 之間的過(guò)程,需要先弄清除 Ruler 的大致機(jī)制。官方文檔對(duì) Ruler 的介紹是:You can think of Rule as a simplified Prometheus that does not require a sidecar and does not scrape and do PromQL evaluation (no QueryAPI)。
不難推測(cè),Ruler 應(yīng)該是在 Prometheus 上封裝了一層,并提供一些額外的功能。通過(guò)翻閱資料大致了解,Ruler 使用 Prometheus 提供的庫(kù)計(jì)算告警規(guī)則,并提供一些額外的功能。下面是 Ruler 中告警流轉(zhuǎn)過(guò)程:
請(qǐng)點(diǎn)擊輸入圖片描述
請(qǐng)點(diǎn)擊輸入圖片描述
首先,圖中每個(gè)告警規(guī)則 Rule 都有一個(gè) active queue(下面簡(jiǎn)稱(chēng)本地隊(duì)列),用來(lái)保存一個(gè)告警規(guī)則下的活躍告警。
其次,從本地隊(duì)列中取出告警,發(fā)送至 AlertManager 前,會(huì)被放入 Thanos Rule Queue(下面簡(jiǎn)稱(chēng)緩沖隊(duì)列),該緩沖隊(duì)列有兩個(gè)屬性:
capacity(默認(rèn)值為 10000):控制緩沖隊(duì)列的大小,
maxBatchSize(默認(rèn)值為 100):控制單次發(fā)送到 AlertManager 的最大告警數(shù)
了解了上述過(guò)程,再通過(guò)翻閱 Ruler 源碼發(fā)現(xiàn),一條告警在放入緩沖隊(duì)列前,會(huì)為其設(shè)置一個(gè)默認(rèn)的自動(dòng)解決時(shí)間(當(dāng)前時(shí)間 + 3m),這里是影響告警自動(dòng)解決的開(kāi)始時(shí)間,在這以后,有兩個(gè)階段可能影響告警的處理:1.?緩沖隊(duì)列階段2.?出緩沖隊(duì)列到 AlertManager 階段(網(wǎng)絡(luò)延遲影響)由于測(cè)試環(huán)境是局域網(wǎng)環(huán)境,并且也沒(méi)在環(huán)境上發(fā)現(xiàn)網(wǎng)絡(luò)相關(guān)的問(wèn)題,我們初步排除第二個(gè)階段的影響,下面我們將注意力放在緩沖隊(duì)列上。通過(guò)相關(guān)源碼發(fā)現(xiàn),告警在緩沖隊(duì)列中的處理過(guò)程大致如下:如果本地隊(duì)列中存在一條告警,其上次發(fā)送之間距離現(xiàn)在超過(guò)了 1m(默認(rèn)值,可修改),則將該告警放入緩沖隊(duì)列,并從緩沖隊(duì)列中推送最多 maxBatchSize 個(gè)告警發(fā)送至 AlertManager。反之,如果所有本地隊(duì)列中的告警,在最近 1m 內(nèi)都有發(fā)送過(guò),那么就不會(huì)推送緩沖隊(duì)列中的告警。也就是說(shuō),如果在一段時(shí)間內(nèi),產(chǎn)生了大量重復(fù)的告警,緩沖隊(duì)列的推送頻率會(huì)下降。隊(duì)列的生產(chǎn)方太多,消費(fèi)方太少,該隊(duì)列中的告警就會(huì)產(chǎn)生堆積的現(xiàn)象。因此我們不難猜測(cè),問(wèn)題原因很可能是是緩沖隊(duì)列推送頻率變低的情況下,單次推送的告警數(shù)量太少,導(dǎo)致緩沖隊(duì)列堆積。下面我們通過(guò)兩個(gè)方面驗(yàn)證上述猜想:首先通過(guò)日志可以得到隊(duì)列在大約 20000s 內(nèi)推送了大約 2000 次,即平均 10s 推送一次。結(jié)合緩沖隊(duì)列的具體屬性,一條存在于隊(duì)列中的告警大約需要 (capacity/maxBatchSize)*10s = 16m,AlertManager 在接收到告警后早已超過(guò)了默認(rèn)的自動(dòng)解決時(shí)間(3m)。其次,Ruler 提供了 3 個(gè) metric 的值來(lái)監(jiān)控緩沖隊(duì)列的運(yùn)行情況:
thanos_alert_queue_alerts_dropped_total
thanos_alert_queue_alerts_pushed_total
thanos_alert_queue_alerts_popped_total
通過(guò)觀察 thanos_alert_queue_alerts_dropped_total 的值,看到存在告警丟失的總數(shù),也能佐證了緩沖隊(duì)列在某些時(shí)刻存在已滿(mǎn)的情況。
解決通過(guò)以上的分析,我們基本確定了問(wèn)題的根源:Ruler 組件內(nèi)置的緩沖隊(duì)列堆積造成了告警發(fā)送的延遲。針對(duì)這個(gè)問(wèn)題,我們選擇調(diào)整隊(duì)列的 maxBatchSize 值。下面介紹一下這個(gè)值如何設(shè)置的思路。由于每計(jì)算一次告警規(guī)則就會(huì)嘗試推送一次緩沖隊(duì)列,我們通過(guò)估計(jì)一個(gè)告警數(shù)量的最大值,得到 maxBatchSize 可以設(shè)置的最小值。假設(shè)你的業(yè)務(wù)系統(tǒng)需要監(jiān)控的實(shí)體數(shù)量分別為 x1、x2、x3、...、xn,實(shí)體上的告警規(guī)則數(shù)量分別有 y1、y2、y3、...、yn,那么一次能產(chǎn)生的告警數(shù)量最多是(x1 * y2 + x2 * y2 + x3 * y3 + ... + xn * yn),最多推送(y1 + y2 + y3 + ... + yn)次,所以要使緩沖隊(duì)列不堆積,maxBatchSize 應(yīng)該滿(mǎn)足:maxBatchSize = (x1 * y2 + x2 * y2 + x3 * y3 + ... + xn * yn) / (y1 + y2 + y3 + ... + yn),假設(shè) x = max(x1,x2, ...,xn), 將不等式右邊適當(dāng)放大后為 x,即 maxBatchSize 的最小值為 x。也就是說(shuō),可以將 maxBatchSize 設(shè)置為系統(tǒng)中數(shù)量最大的那一類(lèi)監(jiān)控實(shí)體,對(duì)于 DMP 平臺(tái),一般來(lái)說(shuō)是 MySQL 實(shí)例。
注意事項(xiàng)
上面的計(jì)算過(guò)程只是提供一個(gè)參考思路,如果最終計(jì)算出該值過(guò)大,很有可能對(duì) AlertManager 造成壓力,因而失去緩沖隊(duì)列的作用,所以還是需要結(jié)合實(shí)際情況,具體分析。因?yàn)?DMP 將 Ruler 集成到了自己的組件中,所以可以比較方便地對(duì)這個(gè)值進(jìn)行修改。如果是依照官方文檔的介紹使用的 Ruler 組件,那么需要對(duì)源碼文件進(jìn)行定制化修改。
方法如下:
第一步:
第二步:
第三步:
點(diǎn)擊查看sql后 會(huì)有這張表的創(chuàng)建語(yǔ)句,改下他說(shuō)屬的數(shù)據(jù)庫(kù),然后將這些代碼貼到你要?jiǎng)?chuàng)建這張表的數(shù)據(jù)庫(kù)里 執(zhí)行就行了。
導(dǎo)入數(shù)據(jù),請(qǐng)看截圖:
當(dāng)點(diǎn)擊圖中按鈕后,會(huì)出現(xiàn)四個(gè)選項(xiàng),選擇sql文件就行了,這樣在copy and exec,就可以了。
用sys賬號(hào)或者擁有DBA權(quán)限的賬號(hào)登錄系統(tǒng),通過(guò)表DBA_TABLESPACES查詢(xún)表空間的信息,通過(guò)表DBA_ALL_TABLES查詢(xún)表的信息,要知道一個(gè)空間下有那些表,通過(guò)TABLESPACE_NAME字段進(jìn)行限制。
或者也可以像樓一說(shuō)的通過(guò)PL/SQL?Developer的圖形界面來(lái)查看。