Zabbix如何實現對大流量監控數據的高效處理?
本文整理自鮑光亞在2021 zabbix深圳大會的演講。聯系文末小Z獲取ppt.
大家好,我是鮑光亞,我分享的主題是zabbix對大流量監控數據的高效處理。首先總結Zabbix監控數據的兩個特點,再分析Zabbix如何利用監控數據的特點實現大流量監控數據的高效處理。
01
監控數據的獨立性—邏輯視角
監控數據的第一個特點是具有相互獨立性。在不同的數據處理階段,這種獨立性會體現在不同的層面,在數據采集階段會體現在value層面,如果不考慮日志監控的話,同一監控項的多次數據采集之間不會互相影響,相當于是無狀態的。在數據傳輸階段,也就是從agent發送數據到server接收數據的階段,獨立性體現在host層面,不同的host使用不同的地址和接口進行數據傳輸,互不影響,而在同一個host內部,每次傳輸的數據往往包含多個監控項的值。
在隨后的數據預處理階段,獨立性主要體現在監控項層面,每個監控值的預處理過程不會依賴于其他監控項,而在同一監控項內部則可能會依賴于前一個值以計算變化率。在最后的數據存儲和觸發器運算階段,獨立性主要體現在host層面,雖然觸發器表達式允許跨host使用監控項,但是在實際應用中,使用最多的還是在同一個host內部的監控項之間構造表達式,所以觸發器表達式的計算只需要使用同一host內部的監控數據。
上述的獨立性是邏輯意義上的獨立,而在數據處理的次序方面還存在一種限制性約束,即同一監控項的多次采集值構成一個時間序列,意味著這些值在時間維度上具有先后關系,那么Zabbix在預處理階段和觸發器表達式運算階段至少需要保證同一監控項的值嚴格按照時間的先后順序進行處理。
除了監控數據本身,Zabbix中的元數據(或者叫主數據)也體現出獨立性,元數據主要包含host、item、trigger等信息,其獨立性主要體現在host層面,因為item屬性與host屬性是關聯的,而trigger又是與item關聯的。所以每個host元數據相互關聯,構成整體。然而,某個host屬性的修改不會影響到其他host。
在Zabbix系統中所反映出的監控數據以及元數據之間的獨立性,為并行和可擴展性提供了基礎,可以說Zabbix監控系統非常適合基于數據分組的并行化和微服務化。
02
監控數據的熱值以及熱數據的規模
監控數據的另一個特點體現在監控數據的熱值以及熱數據的規模方面。如果將數據的每分鐘訪問次數定義為數據的熱值,那么監控數據的熱值與數據的存活時間(也就是年齡)直接相關。
在監控數據寫入數據庫之前,需要完成數據采集、數據傳輸和預處理,在這個時間段,Zabbix需要在最短的時間內快速處理完數據,因此其熱值很高,但是這時的熱數據范圍很小,主要是每個監控項的當前值。而在觸發器表達式計算階段,當前值的處理會引起對該監控項下的多個歷史值的訪問,此時熱數據的范圍大大增加。如果某個觸發器表達式需要使用最近60分鐘的數據,那么熱數據的范圍就擴增到60分鐘。
對于大部分監控項而言,隨著時間流逝,監控數據會快速地脫離Zabbix server的使用范圍,進入冷數據區。雖然冷數據脫離了Zabbix server的使用范圍,但是Zabbix仍然不能對冷數據進行離線化,因為前端UI和網絡API需要訪問這些冷數據,這些訪問一般僅限于少量監控項的讀取。從Zabbix server的角度來說,對于任一特定監控項,數據的熱區和冷區分界線是固定的,并且熱區的數據量相對于冷數據要小得多。
如果使用mysql來存儲監控數據,由于索引的存在,數據的寫入性能會隨著存儲規模的增加而降低,查詢性能也是一樣。因此,控制數據規模成為解決數據庫訪問性能的關鍵。如果將熱數據和冷數據分開存儲,并且在需要時讓數據在兩者之間進行流動,則對于Zabbix server而言,可以大大降低數據規模。如果進一步考慮如何實現熱數據表的最小化,就需要建立一種動態機制,每次修改觸發器表達式后按照觸發器的數據需求量在冷熱數據之間進行雙向調整。
以上的熱值分析是針對監控數據,那么對于元數據來說,其總體訪問頻率主要取決于nvps值和元數據同步的頻率,那么數據采集頻率比較高的監控項,相關的元數據熱值也更高。
Zabbix具體如何實現監控數據的高效處理?
03
Zabbixserver的數據IO
Zabbix對數據的處理能力集中體現在Zabbix server端。總體上,Zabbix server采用流水線式的多進程架構來處理監控數據,其中比較關鍵的有3類進程,每一類又可以啟動多個進程。這3類進程分別是:
trapper/poller進程,負責接收監控數據;
預處理進程,負責對接收的監控數據進行預處理;
history syncer進程負責將監控數據寫入數據庫以及計算觸發器表達式并生成event。這3類進程之間可以通過共享內存和Unix域套接字實現進程間通信。這里沒有展開講lld進程,是因為lld進程處理的是底層自動發現的數據,并不是嚴格意義上的監控值。
既然進程之間是流水線式的協作,我們看一下監控數據在三類進程之間如何進行輸入和輸出。首先, Trapper和poller進程接收到的數據按照來源分為兩種,一種是來自proxy端,一種是來自agent端。由于來自proxy端的數據已經由proxy完成了預處理,所以,這部分數據會直接輸出到共享內存,供history syncer進程使用。
對于來自agent端的數據,無論其監控項是否設置了預處理步驟,都會通過unix域套接字傳遞給預處理進程。預處理進程接收到數據以后,如果發現該數據并沒有設置預處理步驟,則直接寫入共享內存,供history syncer進程使用;如果發現需要預處理,則在預處理完畢以后再寫入共享內存,供history syncer進程使用。對于history syncer進程來說,其輸入數據來自共享內存,它會批量地從共享內存讀取數據進行處理,具體處理過程是先寫入數據庫,然后計算觸發器表達式生成event。
以上是不同種類進程之間的數據IO,那么同一類進程內部的多個進程之間又是如何分配數據的呢?總體而言,Zabbix建立了一種機會均等的機制來保證同類的多個進程之間可以實現數據的均衡分配。比如trapper進程,每一個trapper進程所做的工作就是不斷地重復一個過程,也就是接受連接,然后讀取數據,再處理數據,最后關閉連接。整個過程不需要考慮其他trapper進程的狀態。
從統計意義上說,每次接受連接的時候,對于每個trapper進程來說都有相同的概率獲得連接,最后的結果就是所有連接在所有trapper進程之間均衡分配。如果考慮每個連接中包含的數據量不均衡,那么當某個trapper進程接受的某個連接包含較多的數據時,意味著該進程需要花更多的時間來讀取和處理數據,這就意味著下一次接受連接的時間被推遲。對于poller進程,道理也是一樣,每個poller進程都以相同的概率從Zabbix server端的配置緩存接收到任務,從而實現數據分配均衡。
預處理進程的工作模式與trapper進程不同,預處理進程采用manager-worker模式,即manager進程是唯一的數據入口,負責從trapper和poller接收所有數據,然后通過unix域套接字將數據分配給各個worker進程處理。其分配的規則是,每次每個worker只分配一個數據,只有當worker完成前一個任務之后才會分配下一個任務。
最后,history syncer進程之間的數據均衡也是遵循機會均等的機制。其主要特點是,每個循環最多處理1000個監控值,所以每次寫數據庫的監控值也不會超過1000個。
我們會發現,總體的數據處理過程都基于監控數據之間的獨立性,從而可以靈活地在各個進程之間調度。
04
大流量數據的接收
作為監控系統,Zabbix所面臨的挑戰之一在于需要從大量的監控目標接收數據,這一方面意味著需要連接非常多的監控目標,另一方面意味著監控數據的流量(訪問量)比較大。
影響這種通信效率的一個重要因素是通信協議,考慮到單個消息中包含的數據量不同,在數據接收階段,Zabbix采用了兩種不同的通信協議。Trapper進程要求在每個消息中包含較大量的監控數據,因此Zabbix采用基于TCP協議和JSON格式的自定義協議進行通信。而對于poller進程,當poller進程向agent請求單個監控值時,Zabbix采用簡化的文本協議進行通信,以提高通信效率。
兩種消息格式均為文本格式,相較于使用二進制格式,文本格式使得agent端的接口設計更簡單,從而為自定義agent開發提供了便利,可以吸納更多的監控目標轉向Zabbix。在tcp連接的管理方面,Zabbix的每個連接只處理一個請求,處理完就會關閉,無論在trapper進程還是poller進程中都是這樣。每個tcp連接的建立和關閉都意味著一定的開銷,但是這種模式也有優點,就是靈活性。每次連接只處理一個請求,意味著每個請求都可以在多個進程之間重新調度。從而可以更好地在眾多進程之間實現動態均衡。退一步說,通過增加單個連接的數據量也能夠降低頻繁建立連接的成本。
在擴展性方面,除了可以通過增加進程數量來增加數據吞吐量之外,Zabbix還支持多地址監聽,從而可以突破單套接字的吞吐量限制。
05
數據結構設計—解決處理速度問題
假設有一個監控系統存在100萬個監控項,30萬個觸發器,nvps值為一萬,意味著每秒需要處理1萬個值,而每處理1個值都需要從100萬個監控項中找到所對應的item狀態信息。同樣地,在計算觸發器時也需要從大量觸發器中查找目標。對于這一查找問題,Zabbix通過哈希表結構來解決,也就是,以itemid、hostid、triggerid等作為鍵,構建哈希表來組織這些需要頻繁查找的數據。
哈希表結構存在于配置緩存、歷史緩存、歷史索引緩存、值緩存valuecache和趨勢緩存中,配置信息緩存中的哈希表主要是解決剛才說的頻繁查找大規模元數據的問題。歷史緩存和歷史索引緩存中也使用了哈希表,當有大量的監控數據來不及處理時,可以先放到歷史緩存的哈希表中,等待history syncer進程處理。由于使用了哈希表,即使有大量監控項的數據進入緩存,history syncer進程仍然可以以固定的時間復雜度來查找這些數據。
ValueCache以哈希表形式存儲每個監控項的熱數據,這些數據主要用于觸發器表達式的計算,從而,監控項數量的增長基本不會影響觸發器表達式計算所消耗的時間。趨勢緩存中存儲的是每個監控項最近自然小時內的累計趨勢數據,這些數據的更新和寫庫均需要經歷查找的過程,因為數據的更新和寫庫都是由最新到來的監控數據驅動的,需要根據到來的監控數據查找對應的監控項數據。
除了需要解決快速查找問題,Zabbix還需要解決快速排序問題,這一問題源于history syncer進程處理監控數據時應該按照什么樣的順序進行處理,Zabbix是以監控項為單位對所有監控數據按照時間戳從小到大進行全局性的排序,所使用的排序方法就是堆排序,當需要選擇目標時,只需要訪問根節點即可。在使用堆排序的情形下,每次排序所消耗的時間與堆的規模直接相關。所以我們應該盡可能降低歷史緩存中的監控項的數量,以加快數據處理速度。在壓力較小的Zabbix系統中,歷史緩存中的數據總是接近于0。
上述哈希表結構的設計體現了監控數據的獨立性,正是由于獨立性,每次查找數據只需要訪問單個目標。而堆排序的設計則體現了監控數據在時間維度的先后次序。
06
元數據的訪問與協調
下面看一下元數據對數據處理效率的影響。元數據位于共享內存中,包含監控項、主機、觸發器、接口等所有必要的信息,這些信息分別存儲在很多個哈希表結構中。這些信息供幾乎所有Zabbix進程使用,在Zabbix server端,無論是數據接收階段、預處理階段、數據計算階段都離不開對元數據的訪問。此外,元數據還需要通過configuration syncer進程進行定期數據同步,目的是將數據庫中所作的修改同步到緩存中。當在同步過程中需要修改元數據,configuration syncer進程會對面臨一個較大的挑戰,就是與其他進程的協調。考慮到大部分進程只是讀取元數據,而不會進行寫操作,Zabbix選擇使用讀寫鎖來協調所有進程對元數據的訪問,從而允許多個進程同時讀取元數據。
即使這樣,當configuration syncer進程持有寫鎖時,其他進程將無法訪問元數據。對這一問題的優化,Zabbix采用臨界區最小化以及拆分臨界區的方式,將元數據的同步過程拆分為依次執行的多個同步序列,每個序列結束后都會暫時釋放寫鎖,從而給其他進程運行的機會。這些序列總體上是先同步主機信息,然后同步監控項信息,最后同步觸發器和事件處理相關的信息。在使用讀寫鎖的情形下,單純的讀鎖基本不會影響多進程的執行進度,而一旦寫鎖介入就會對所有其他進程產生排斥效果。
Zabbix通過最大程度地減少寫鎖持有時間,并將持有時間碎片化,從而降低了寫鎖對Zabbix進程并行性能的影響。我們注意到configuration syncer進程是唯一的,并未采用多進程方式,這一方面是因為元數據內部需要維持某些一致性,如果使用多進程方式,無疑會增加維持一致性方面的開銷,另一方面,如果采用多進程,這些進程之間仍然需要解決鎖沖突的問題,最終的結果與單進程并無多大區別。不過,如果能夠基于元數據之間的獨立性,實現基于數據分組的并行化,那就另當別論。
07
大流量數據的存儲
監控數據的存儲是由history syncer進程負責寫入數據庫,history syncer進程應對大流量數據的方式是,一方面通過批量插入來提高寫庫的效率,另一方面通過多進程的方式來擴展數據處理能力。在寫庫過程中,歷史數據寫入history表,即使數據變為冷數據也需要留在history表中供前端UI訪問。趨勢數據寫入trends表,相較于歷史數據,趨勢數據的寫庫負載要低的多,是因為對于每個監控項來說,平均每小時只需要寫庫一次,其他時間只需要更新趨勢緩存,不需要寫庫。
在history syncer進程的觸發器計算階段,主要訪問值緩存,但是如果值緩存不能命中則需要查詢history表,這種情況下就需要使用history表索引了。考慮索引對insert操作的影響,索引在提高查詢速度的同時也降低了寫入性能。
觸發器計算之后生成的event信息也需要寫入數據庫,這些信息存儲在events表、problem、escalation等表中。因此,這些表的數據增長率取決于Zabbix生成的事件的數量,當事件數量陡增時,這些表的寫入壓力也會隨之增加。
在數據存儲方面主要體現了熱數據和冷數據的轉換過程以及數據規模對讀寫性能的影響。
今天我的演講到這里,謝謝大家。
專家推薦《深入理解Zabbix監控系統》
張世宏(當代張思德),Zabbix開源社區專家:
相比于市面上其他Zabbix圖書,本書從底層原理入手,深入剖析了Zabbix監控系統組件的內部運行機制,對于想學習和深入了解Zabbix的人員來說是非常好的選擇。
田川,海爾智家基礎管理:
近幾年開源監控系統蓬勃發展,特別是Prometheus的勢頭正勁,但以前很多介紹Prometheus的文章或教程里,都會把Zabbix作為反面案例,而其中列舉的一些例子其實是對Zabbix不了解或不熟悉而造成的誤讀。不過,現在用戶越來越理性,也越來越專業,會根據不同的業務應用場景,選擇更符合實際需求的推薦方案。作為在工作中同時使用Zabbix和Prometheus的用戶,我認為在基礎設施即服務(infrastructure as a service,IaaS)監控領域里,Zabbix仍是最佳的開源監控解決方案。
經過多年耕耘,Zabbix已經成功在銀行、電信、制造、保險、證券和零售等多個行業中成功應用。本書是從源碼角度對Zabbix開源監控系統進行全面解讀的技術圖書,強烈推薦每一位Zabbix用戶將其作為案頭必備的工具書和參考手冊。
備注“使用Zabbix年限+企業+姓名”
進入交流群,4000+用戶已加入
一個人走得快,一群人走得遠
Zabbix
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。