Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)

本文原創(chuàng)作者鮑光亞,京東商城基礎(chǔ)平臺(tái)部軟件開發(fā)工程師,經(jīng)作者同意發(fā)表于本人博客,如需轉(zhuǎn)載需經(jīng)本人同意。

目前累計(jì)服務(wù)客戶1000多家,積累了豐富的產(chǎn)品開發(fā)及服務(wù)經(jīng)驗(yàn)。以網(wǎng)站設(shè)計(jì)水平和技術(shù)實(shí)力,樹立企業(yè)形象,為客戶提供成都網(wǎng)站制作、網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)頁設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷、VI設(shè)計(jì)、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。創(chuàng)新互聯(lián)始終以務(wù)實(shí)、誠(chéng)信為根本,不斷創(chuàng)新和提高建站品質(zhì),通過對(duì)領(lǐng)先技術(shù)的掌握、對(duì)創(chuàng)意設(shè)計(jì)的研究、對(duì)客戶形象的視覺傳遞、對(duì)應(yīng)用系統(tǒng)的結(jié)合,為客戶提供更好的一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進(jìn)步。

一、前言

我部門對(duì)數(shù)據(jù)庫的監(jiān)控使用的是開源的Zabbix系統(tǒng),目前監(jiān)控了上萬臺(tái)主機(jī)。本文旨在通過分析Zabbix系統(tǒng)server端的數(shù)據(jù)結(jié)構(gòu)和并行計(jì)算的實(shí)現(xiàn)方法,嘗試探尋Zabbix系統(tǒng)server端的潛在擴(kuò)展能力,同時(shí)希望有助于在實(shí)際應(yīng)用過程中進(jìn)一步優(yōu)化運(yùn)行效率和穩(wěn)定性。

Zabbix系統(tǒng)采用server-proxy-agent架構(gòu),其server端的主要功能是收集監(jiān)控?cái)?shù)據(jù)并基于所收集的數(shù)據(jù)觸發(fā)報(bào)警動(dòng)作。在實(shí)際應(yīng)用中,zabbix有可能會(huì)監(jiān)控10000臺(tái)主機(jī)(host,由hostid唯一標(biāo)識(shí)),如果每臺(tái)主機(jī)設(shè)置50個(gè)監(jiān)控指標(biāo)(item,由itemid唯一標(biāo)識(shí)),并且每分鐘收集一次數(shù)據(jù),則一共有50萬個(gè)item,每秒鐘需要接收并處理8333項(xiàng)數(shù)據(jù)(value),即vps(values per second)為8333。如果有三分之一的item設(shè)置了報(bào)警觸發(fā)器(trigger,由triggerid唯一標(biāo)識(shí)),則共有17萬個(gè)trigger。

在以上情境中,為了保證監(jiān)控的有效性和及時(shí)性,zabbix接收到每個(gè)value后需要立即在50萬個(gè)item中找到正確的item,并獲取該item的前一個(gè)值(previous value,last(),以便計(jì)算增量),或者計(jì)算前5分鐘內(nèi)的平均值(avg(5m)),以便根據(jù)觸發(fā)器表達(dá)式(trigger expression,由functionid唯一標(biāo)識(shí))判斷是否應(yīng)該觸發(fā)報(bào)警事件(event,由eventid唯一標(biāo)識(shí))。同時(shí)如果item返回值類型為數(shù)字型,還需要計(jì)算該item在一個(gè)小時(shí)內(nèi)的平均值(value_avg)、最大值(value_max)、最小值(value_min)。按照上面的vps數(shù)據(jù),zabbix至少需要每秒鐘搜索8333*500000次。此外,item和trigger并不是靜態(tài)數(shù)據(jù),用戶隨時(shí)可能會(huì)增加、修改、刪除、禁用(disable)、啟用(enable)某些item和trigger,zabbix需要在處理value時(shí)查詢?cè)搃tem和trigger最新的狀態(tài)。如何在一秒時(shí)間內(nèi)完成如此大量的操作,zabbix給出的方案是: 哈希表。

在并行計(jì)算的軟件方面,由于Zabbix系統(tǒng)監(jiān)控的各個(gè)主機(jī)之間是相對(duì)獨(dú)立的,無論在任務(wù)還是在數(shù)據(jù)方面都非常便于計(jì)算的并行化。服務(wù)器硬件方面,我們實(shí)際使用的服務(wù)器結(jié)構(gòu)是2*8處理器+三級(jí)緩存+16G*8內(nèi)存+SSD硬盤+10Gbps網(wǎng)卡(數(shù)據(jù)庫、zabbix server和web服務(wù)共用)。Zabbix的并行計(jì)算主要采用的是共享內(nèi)存模式。

二、Zabbix中的哈希表種類

Zabbix使用的哈希表是鏈?zhǔn)焦1?,主要有以下五類(都是在共享?nèi)存中分配空間):

1.Valuecache

Valuecache中包含兩個(gè)哈希表vc_cache->items(itemid作為鍵值進(jìn)行哈希)和vc_cache->strpool(字符串作為鍵值),用于存儲(chǔ)收集到的values(包括數(shù)字型和字符串型),每個(gè)item占用一個(gè)slot,每個(gè)槽位都是一個(gè)鏈表,鏈表節(jié)點(diǎn)存儲(chǔ)實(shí)際需要的信息。

Valuecache的哈希表在服務(wù)啟動(dòng)時(shí)創(chuàng)建,服務(wù)退出時(shí)銷毀,初始槽數(shù)為1009(1000之后的第一個(gè)素?cái)?shù)),隨著表中元素?cái)?shù)量的增加,槽數(shù)也會(huì)按照一定的規(guī)則增多。Valuecache可使用的最大空間由配置文件中的ValueCacheSize參數(shù)控制,允許的范圍是128K-64G。

2.Dbcache

Dbcache中的cache->trends哈希表,用于緩存trends表(每個(gè)item的小時(shí)平均值、最大值、最小值)的數(shù)據(jù)。Zabbix server的history_syncer進(jìn)程會(huì)持續(xù)接收來自agent或者proxy的數(shù)據(jù)后會(huì)將其加載到緩存中,同時(shí)更新cache->trends哈希表。該哈希表中的元素是ZBX_DC_TREND結(jié)構(gòu)體。

Cache->trends表中的數(shù)據(jù)時(shí)間超過整點(diǎn)時(shí)會(huì)被flush到數(shù)據(jù)庫中,例如10點(diǎn)之后會(huì)將9-10點(diǎn)之間的數(shù)據(jù)flush到數(shù)據(jù)庫中。

Cache->trends哈希表在服務(wù)啟動(dòng)時(shí)創(chuàng)建,初始槽數(shù)與vc_cache->items相同,為1009(1000之后的第一個(gè)素?cái)?shù))。Cache->trends哈希表的最大可用空間由配置文件中的TrendCacheSize參數(shù)控制,允許的范圍是128K-2G。

3.Dbconfig

Dbconfig緩存中存儲(chǔ)了多個(gè)與監(jiān)控有關(guān)的配置信息的哈希表,包括config->hosts、config->items、config->functions、config->triggers等等。配置信息哈希表的鍵值包括hostid、itemid、functionid、triggerid、triggerdepid、expressionid、globalmacroid、hostmacroid、hosttemplateid、interfaceid、host_inventory等,其中數(shù)量最多的往往是itemid、functionid和triggerid,會(huì)在數(shù)十萬級(jí)別(以10000個(gè)host計(jì))。

以config->items為例,該哈希表的元素是ZBX_DC_ITEM結(jié)構(gòu)體。Config->items中的數(shù)據(jù)是從數(shù)據(jù)庫中查詢獲得的,zabbix server的configuration syncer進(jìn)程會(huì)周期性地從數(shù)據(jù)庫同步數(shù)據(jù)到緩存中。

Dbconfig緩存中的其他哈希表與config->items表類似,都是從數(shù)據(jù)庫同步數(shù)據(jù),都是在服務(wù)啟動(dòng)時(shí)創(chuàng)建,初始槽數(shù)都是1009,并隨著數(shù)據(jù)量的增加動(dòng)態(tài)擴(kuò)展。整個(gè)dbconfig緩存可用空間大小由CacheSize參數(shù)決定,取值范圍為128K-8G。

4.Strpool

此處的strpool與vc_cache->strpool是相互獨(dú)立的兩個(gè)哈希表。此Strpool緩存用于存儲(chǔ)配置信息相關(guān)的字符串值,它與dbconfig共同分享CacheSize的空間(strpool占15%)。Strpool存儲(chǔ)的字符串包括host name、item key、item delay_flex、snmp community、snmp securityname、snmp passphrase、logitem format等數(shù)據(jù)。Zabbix需要使用host name等字符串時(shí),會(huì)首先在strpool中查找。

Strpool的哈希表初始槽數(shù)為1009。鍵值是字符串本身,哈希值是對(duì)字符串調(diào)用哈希函數(shù)的返回值。

5.其他

除了以上哈希表,還有snmpidx、vmware service等哈希表。

三、哈希表的實(shí)現(xiàn)

下面以config->items哈希表為例,說明zabbix中哈希表的實(shí)現(xiàn)方法。

1.數(shù)據(jù)結(jié)構(gòu)定義

Zabbix采用的是鏈?zhǔn)焦1?,哈希表中的每個(gè)slot都是一個(gè)鏈表。具體的數(shù)據(jù)結(jié)構(gòu)定義如下:

2.Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)    
槽數(shù)取值及負(fù)載因子

Zabbix的哈希過程是先調(diào)用哈希函數(shù)計(jì)算鍵值對(duì)應(yīng)的哈希值,然后用取余法確定槽位號(hào)。因此,取余計(jì)算時(shí)的除數(shù)就是槽位數(shù),該數(shù)值取素?cái)?shù)(因?yàn)樗財(cái)?shù)可以做到最大程度上均勻散列)。在config->items哈希表中,槽位數(shù)的初始值是1009,隨著數(shù)據(jù)量的增加,當(dāng)負(fù)載因子(元素?cái)?shù)/槽數(shù))達(dá)到0.8時(shí),會(huì)擴(kuò)充槽數(shù)量(擴(kuò)充為當(dāng)前數(shù)量的1.5倍以上,并取素?cái)?shù))。因此,負(fù)載因子總是保持在0.8和0.533之間。

按照以上規(guī)則,每次擴(kuò)展哈希表,其槽數(shù)如下表示。當(dāng)item數(shù)量為50萬時(shí),槽數(shù)應(yīng)為670849。

序號(hào)

理論值

素?cái)?shù)(槽數(shù))

允許的元素?cái)?shù)

0

1000

1009

806

1

1513

1523

1217

2

2284

2287

1828

3

3430

3433

2745

4

5149

5153

4121

5

7729

7741

6191

6

11611

11617

9292

7

17425

17431

13943

8

26146

26153

20921

9

39229

39229

31382

10

58843

58889

47110

11

88333

88337

70668

12

132505

132511

106007

13

198766

198769

159014

14

298153

298153

238521

15

447229

447233

357785

16

670849

670849

536678

17

1006273

1006279

805022

18

1509418

1509427

1207540

19

2264140

2264149

1811318

3.哈希函數(shù)

Zabbix使用的哈希函數(shù)是在fnv-1a函數(shù)(http://www.isthe.com/chongo/tech/comp/fnv/index.html)的基礎(chǔ)上稍微進(jìn)行了改進(jìn)。該函數(shù)采用乘積和位操作達(dá)到快速哈希的目的。具體實(shí)現(xiàn)如下:

Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)

按照以上函數(shù),模擬620000個(gè)itemid的哈希過程(槽數(shù)取1006279),哈希效率如下:

總桶數(shù)

1006279

空桶數(shù)量

543405

深度大于1的桶數(shù)

127940

載荷因子

0.616131311

最大桶深

7

深桶占有值桶比例

0.276403514

深桶占總桶數(shù)比例

0.127141677

空桶占總數(shù)比例

0.540014251

四、任務(wù)和數(shù)據(jù)的并行化

1.任務(wù)的并行

Zabbix系統(tǒng)的任務(wù)基本上都是基于所監(jiān)控的host和item,各個(gè)host和item之間有較強(qiáng)的獨(dú)立性。為了并行化,Zabbix將任務(wù)拆分為相對(duì)獨(dú)立的子任務(wù),各個(gè)子任務(wù)由一個(gè)或者多個(gè)進(jìn)程來執(zhí)行。Zabbix server端的進(jìn)程劃分如下表所示:

啟動(dòng)

順序

process title

允許

進(jìn)程數(shù)

默認(rèn)值

任務(wù)

1

configuration syncer

1-1

1

從數(shù)據(jù)庫同步數(shù)據(jù)到Dbconfig緩存

2

db watchdog

1-1

1

周期性地檢查server端數(shù)據(jù)庫是否可用,如果不可用則發(fā)送報(bào)警信息

3

poller #n

0-1000

5

根據(jù)dbconfig中的數(shù)據(jù),從passive agent和snmp設(shè)備采集數(shù)據(jù),并flush到共享內(nèi)存cache->history中

4

unreachable poller #n

0-1000

1

當(dāng)設(shè)備處于unreachable狀態(tài)時(shí),周期性地polling設(shè)備

5

trapper #n

0-1000

5

從socket接收并處理active agent和active proxy發(fā)來的數(shù)據(jù)(json格式,zabbix通訊協(xié)議),并flush到共享內(nèi)存cache->history中

6

icmp pinger #n

0-1000

1

根據(jù)dbconfig中的數(shù)據(jù),批量采集icmpping相關(guān)的item數(shù)據(jù),并flush到共享內(nèi)存cache->history中

7

alerter

1-1

1

發(fā)送各種報(bào)警通知

8

housekeeper

1-1

1

周期性地刪除過期的歷史數(shù)據(jù)

9

timer #n

1-1000

1

計(jì)算與時(shí)間相關(guān)的trigger表達(dá)式等

10

node watcher

1-1

1

處理與node之間的交互

11

http poller #n

0-1000

1

收集web監(jiān)控相關(guān)的數(shù)據(jù),并flush到共享內(nèi)存cache->history中

12

discoverer #n

0-250

1

按照指定規(guī)則掃描網(wǎng)絡(luò),自動(dòng)發(fā)現(xiàn)host、interface等

13

history syncer #n

1-100

4

將共享內(nèi)存cache->history中的數(shù)據(jù)批量更新到數(shù)據(jù)庫中,并flush到共享內(nèi)存vc_cache、cache->trends、config->items等中

14

escalator

1-1

1

當(dāng)報(bào)警操作需要分步連續(xù)執(zhí)行時(shí),控制各步驟之間的escalations

15

ipmi poller #n

0-1000

0

與poller進(jìn)程類似,處理ipmi items

16

java poller #n

0-1000

0

與poller進(jìn)程類似,處理JMX items

17

snmp trapper #n

0-1

0

與trapper進(jìn)程類似,處理snmp items

18

proxy poller #n

0-250

1

與passive proxy交互,以設(shè)定的頻率獲取所需要的json格式數(shù)據(jù)并將數(shù)據(jù)flush到共享內(nèi)存cache->history中

19

self-monitoring

1-1

1

處理與zabbix自身運(yùn)行狀態(tài)相關(guān)的item信息,訪問共享內(nèi)存中的collector變量

20

vmware collector #n

0-250

0

采集vmware虛擬機(jī)相關(guān)的數(shù)據(jù),并flush到共享內(nèi)存中

所有進(jìn)程中比較關(guān)鍵的進(jìn)程有兩類:poller/trapper類進(jìn)程,用于采集數(shù)據(jù)并加載到共享內(nèi)存中;history syncer進(jìn)程,用于更新數(shù)據(jù)庫及觸發(fā)events和報(bào)警。邏輯上這兩類任務(wù)是先后執(zhí)行的,首先要采集到數(shù)據(jù)然后才能觸發(fā)報(bào)警。而每類任務(wù)的各個(gè)進(jìn)程之間是獨(dú)立的,多個(gè)poller/trapper進(jìn)程可以同時(shí)執(zhí)行,多個(gè)history syncer進(jìn)程也可以同時(shí)執(zhí)行。

2.Socket multiplexing對(duì)多進(jìn)程的支持

Zabbix監(jiān)控系統(tǒng)的數(shù)據(jù)最終來源是被監(jiān)控的主機(jī),數(shù)據(jù)通過socket監(jiān)聽端口接收(監(jiān)聽端口允許的最大連接數(shù)由操作系統(tǒng)決定)。Zabbix通過fork多個(gè)子進(jìn)程來共享同一個(gè)socket,在讀socket時(shí)則通過基于select()函數(shù)的multiplexing實(shí)現(xiàn)多進(jìn)程同時(shí)讀取。

按照10000個(gè)host,每分鐘采集一次數(shù)據(jù)(假設(shè)每個(gè)host上的所有item同時(shí)采集數(shù)據(jù),事實(shí)可能并非如此),平均每秒鐘有167個(gè)連接請(qǐng)求。

3.MySQL數(shù)據(jù)庫的讀寫

Zabbix支持多種數(shù)據(jù)庫,包括Mysql、Oracle、IBM DB2、PostgreSQL、SQLite,我們實(shí)際使用的是Mysql。為了保證數(shù)據(jù)的持續(xù)性,zabbix在觸發(fā)報(bào)警前會(huì)先將數(shù)據(jù)插入到數(shù)據(jù)庫中。History syncer進(jìn)程數(shù)允許最多100個(gè),每個(gè)進(jìn)程可以與數(shù)據(jù)庫建立獨(dú)立的連接,進(jìn)行數(shù)據(jù)更新。

五、共享內(nèi)存與進(jìn)程間通信

1.共享內(nèi)存的創(chuàng)建

共享內(nèi)存是進(jìn)程間通信中最簡(jiǎn)單并且速度最快的一種機(jī)制。Zabbix的進(jìn)程間通信主要采用共享內(nèi)存的方式,主進(jìn)程在fork出所有子進(jìn)程之前調(diào)用shmget創(chuàng)建共享內(nèi)存,并attach到地址空間中。

Zabbix調(diào)用shmget創(chuàng)建的共享內(nèi)存segment共有8個(gè),為config_mem、trend_mem、history_mem、history_text_mem、vc_mem、vmware_mem、strpool.mem_info、collector,分別用于dbconfig緩存、cache->trends數(shù)據(jù)、cache->history(數(shù)字和string)、vc_cache、vmware數(shù)據(jù)、strpool、監(jiān)控zabbix自身狀態(tài)的collector結(jié)構(gòu)。如果實(shí)際應(yīng)用中沒有啟用vmware,則只有7個(gè)共享內(nèi)存被attach到各子進(jìn)程的地址空間中,如下圖所示,這些共享內(nèi)存段將一直保持attach狀態(tài),直到服務(wù)停止。

Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)

從上圖可以看出,每個(gè)共享內(nèi)存段都attach到了553個(gè)進(jìn)程中,即zabbix server的每個(gè)進(jìn)程都可以訪問所有七個(gè)共享內(nèi)存。

2.信號(hào)量機(jī)制

Zabbix使用二進(jìn)制信號(hào)量機(jī)制來協(xié)調(diào)多個(gè)進(jìn)程對(duì)共享內(nèi)存的同時(shí)訪問,避免資源爭(zhēng)用。系統(tǒng)在創(chuàng)建共享內(nèi)存之前會(huì)調(diào)用semget函數(shù),創(chuàng)建一個(gè)包含13個(gè)信號(hào)量的信號(hào)量集,并將每個(gè)信號(hào)量的值初始化為1。各個(gè)信號(hào)量用于對(duì)不同的共享內(nèi)存進(jìn)行訪問控制,具體如下所示:

# define ZBX_MUTEX_LOG 0

# define ZBX_MUTEX_NODE_SYNC 1

# define ZBX_MUTEX_CACHE 2

# define ZBX_MUTEX_TRENDS 3

# define ZBX_MUTEX_CACHE_IDS 4

# define ZBX_MUTEX_CONFIG 5

# define ZBX_MUTEX_SELFMON 6

# define ZBX_MUTEX_CPUSTATS 7

# define ZBX_MUTEX_DISKSTATS 8

# define ZBX_MUTEX_ITSERVICES 9

# define ZBX_MUTEX_VALUECACHE 10

# define ZBX_MUTEX_VMWARE 11

# define ZBX_MUTEX_SQLITE3 12

當(dāng)進(jìn)程需要對(duì)某個(gè)共享內(nèi)存進(jìn)行寫操作時(shí),會(huì)首先lock(調(diào)用semop函數(shù)將信號(hào)量-1),執(zhí)行寫操作完畢后將再unlock(將信號(hào)量+1)。如果執(zhí)行l(wèi)ock時(shí)信號(hào)量為0,則等待,直到信號(hào)量非0。Zabbix的信號(hào)量在釋放共享內(nèi)存時(shí)銷毀。

六、聲明與結(jié)論

本文創(chuàng)作基于zabbix 2.2.10版本的源碼分析,歡迎批評(píng)指正。

Zabbix所采用的哈希函數(shù)效果比較理想。但在實(shí)際應(yīng)用中,仍然可以根據(jù)需要和資源情況對(duì)負(fù)載因子、槽數(shù)擴(kuò)展速度、槽數(shù)初值、哈希函數(shù)定義進(jìn)行改進(jìn)。

在Zabbix的并行計(jì)算方面,由于監(jiān)控系統(tǒng)的特點(diǎn),數(shù)據(jù)和任務(wù)之間有較強(qiáng)的獨(dú)立性,非常便于并行化。Zabbix通過多進(jìn)程+共享內(nèi)存實(shí)現(xiàn)并行,資源爭(zhēng)用問題通過信號(hào)量進(jìn)行控制。從實(shí)際應(yīng)用效果來看,并行的性能非常理想。

Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)

本文名稱:Zabbix數(shù)據(jù)結(jié)構(gòu)及并行計(jì)算實(shí)現(xiàn)
本文路徑:http://muchs.cn/article30/gdicpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、微信公眾號(hào)、網(wǎng)站內(nèi)鏈、虛擬主機(jī)品牌網(wǎng)站建設(shè)軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司