更新時間:2020-10-30 來源:黑馬程序員 瀏覽量:
隨著分布式系統規(guī)模的日益擴大,集群中的機器規(guī)模也隨之變大,那如何更好地進行集群管理也顯得越來越重要了。所謂集群管理,包括集群監(jiān)控與集群控制兩大塊,前者側重對集群運行時狀態(tài)的收集,后者則是對集群進行操作與控制。
在日常開發(fā)和運維過程中,我們經常會有類似于如下的需求:
·如何快速的統計出當前生產環(huán)境下一共有多少臺機器
·如何快速的獲取到機器上下線的情況
·如何實時監(jiān)控集群中每臺主機的運行時狀態(tài)
在傳統的基于Agent的分布式集群管理體系中,都是通過在集群中的每臺機器上部署一個 Agent,由這個 Agent
負責主動向指定的一個監(jiān)控中心系統(監(jiān)控中心系統負責將所有數據進行集中處理,形成一系列報表,并負責實時報警,以下簡稱“監(jiān)控中心”)匯報自己所在機器的狀態(tài)。在集群規(guī)模適中的場景下,這確實是一種在生產實踐中廣泛使用的解決方案,能夠快速有效地實現分布式環(huán)境集群監(jiān)控,但是一旦系統的業(yè)務場景增多,集群規(guī)模變大之后,該解決方案的弊端也就顯現出來了。
大規(guī)模升級困難
以客戶端形式存在的 Agent,在大規(guī)模使用后,一旦遇上需要大規(guī)模升級的情況,就非常麻煩,在升級成本和升級進度的控制上面臨巨大的挑戰(zhàn)。
統一的Agent無法滿足多樣的需求
對于機器的CPU使用率、負載(Load)、內存使用率、網絡吞吐以及磁盤容量等機器基本的物理狀態(tài),使用統一的Agent來進行監(jiān)控或許都可以滿足。但是,如果需要深入應用內部,對一些業(yè)務狀態(tài)進行監(jiān)控,例如,在一個分布式消息中間件中,希望監(jiān)控到每個消費者對消息的消費狀態(tài);或者在一個分布式任務調度系統中,需要對每個機器上任務的執(zhí)行情況進行監(jiān)控。很顯然,對于這些業(yè)務耦合緊密的監(jiān)控需求,不適合由一個統一的Agent來提供。
編程語言多樣性
隨著越來越多編程語言的出現,各種異構系統層出不窮。如果使用傳統的Agent方式,那么需要提供各種語言的 Agent
客戶端。另一方面,“監(jiān)控中心”在對異構系統的數據進行整合上面臨巨大挑戰(zhàn)。
Zookeeper的兩大特性:
1.客戶端如果對Zookeeper的數據節(jié)點注冊Watcher監(jiān)聽,那么當該數據節(jié)點的內容或是其子節(jié)點列表發(fā)生變更時,Zookeeper服務器就會向訂閱的客戶端發(fā)送變更通知。
2.對在Zookeeper上創(chuàng)建的臨時節(jié)點,一旦客戶端與服務器之間的會話失效,那么臨時節(jié)點也會被自動刪除
利用其兩大特性,可以實現集群機器存活監(jiān)控系統,若監(jiān)控系統在/clusterServers節(jié)點上注冊一個Watcher監(jiān)聽,那么但凡進行動態(tài)添加機器的操作,就會在/clusterServers節(jié)點下創(chuàng)建一個臨時節(jié)點:/clusterServers/[Hostname],這樣,監(jiān)控系統就能夠實時監(jiān)測機器的變動情況。
下面通過分布式日志收集系統這個典型應用來學習Zookeeper如何實現集群管理。
分布式日志收集系統:
分布式日志收集系統的核心工作就是收集分布在不同機器上的系統日志,在這里我們重點來看分布式日志系統(以下簡稱“日志系統”)的收集器模塊。
在一個典型的日志系統的架構設計中,整個日志系統會把所有需要收集的日志機器(我們以“日志源機器”代表此類機器)分為多個組別,每個組別對應一個收集器,這個收集器其實就是一個后臺機器(我們以“收集器機器”代表此類機器),用于收集日志
· 變化的日志源機器
在生產環(huán)境中,伴隨著機器的變動,每個應用的機器幾乎每天都是在變化的(機器硬件問題、擴容、機房遷移或是網絡問題等都會導致一個應用的機器變化),也就是說每個組別中的日志源機器通常是在不斷變化的。
· 變化的收集器機器
日志收集系統自身也會有機器的變更或擴容,于是會出現新的收集器機器加入或是老的收集器機器退出的情況。
無論是日志源機器還是收集器機器的變更,最終都可以歸結為如何快速、合理、動態(tài)地為每個收集器分配對應的日志源機器。這也成為了整個日志系統正確穩(wěn)定運轉的前提,也是日志收集過程中最大的技術挑戰(zhàn)之一,在這種情況下,我們就可以引入zookeeper了,下面我們就來看ZooKeeper在這個場景中的使用。
使用Zookeeper的場景步驟如下
① 注冊收集器機器
使用ZooKeeper來進行日志系統收集器的注冊,典型做法是在ZooKeeper上創(chuàng)建一個節(jié)點作為收集器的根節(jié)點,例如/logs/collector(下文我們以“收集器節(jié)點”代表該數據節(jié)點),每個收集器機器在啟動的時候,都會在收集器節(jié)點下創(chuàng)建自己的節(jié)點,例如/logs/collector/[Hostname]
② 任務分發(fā)
待所有收集器機器都創(chuàng)建好自己對應的節(jié)點后,系統根據收集器節(jié)點下子節(jié)點的個數,將所有日志源機器分成對應的若干組,然后將分組后的機器列表分別寫到這些收集器機器創(chuàng)建的子節(jié)點(例如/logs/collector/host1)上去。這樣一來,每個收集器機器都能夠從自己對應的收集器節(jié)點上獲取日志源機器列表,進而開始進行日志收集工作。
③ 狀態(tài)匯報
完成收集器機器的注冊以及任務分發(fā)后,我們還要考慮到這些機器隨時都有掛掉的可能。因此,針對這個問題,我們需要有一個收集器的狀態(tài)匯報機制:每個收集器機器在創(chuàng)建完自己的專屬節(jié)點后,還需要在對應的子節(jié)點上創(chuàng)建一個狀態(tài)子節(jié)點,例如/logs/collector/host1/status,每個收集器機器都需要定期向該節(jié)點寫入自己的狀態(tài)信息。我們可以把這種策略看作是一種心跳檢測機制,通常收集器機器都會在這個節(jié)點中寫入日志收集進度信息。日志系統根據該狀態(tài)子節(jié)點的最后更新時間來判斷對應的收集器機器是否存活。
④ 動態(tài)分配
如果收集器機器掛掉或是擴容了,就需要動態(tài)地進行收集任務的分配。在運行過程中,日志系統始終關注著/logs/collector這個節(jié)點下所有子節(jié)點的變更,一旦檢測到有收集器機器停止匯報或是有新的收集器機器加入,就要開始進行任務的重新分配。無論是針對收集器機器停止匯報還是新機器加入的情況,日志系統都需要將之前分配給該收集器的所有任務進行轉移。為了解決這個問題,通常有兩種做法:
· 全局動態(tài)分配
這是一種簡單粗暴的做法,在出現收集器機器掛掉或是新機器加入的時候,日志系統需要根據新的收集器機器列表,立即對所有的日志源機器重新進行一次分組,然后將其分配給剩下的收集器機器。
· 局部動態(tài)分配
全局動態(tài)分配方式雖然策略簡單,但是存在一個問題:一個或部分收集器機器的變更,就會導致全局動態(tài)任務的分配,影響面比較大,因此風險也就比較大。所謂局部動態(tài)分配,顧名思義就是在小范圍內進行任務的動態(tài)分配。在這種策略中,每個收集器機器在匯報自己日志收集狀態(tài)的同時,也會把自己的負載匯報上去。請注意,這里提到的負載并不僅僅只是簡單地指機器CPU負載(Load),而是一個對當前收集器任務執(zhí)行的綜合評估,這個評估算法和ZooKeeper本身并沒有太大的關系,這里不再贅述。
在這種策略中,如果一個收集器機器掛了,那么日志系統就會把之前分配給這個機器的任務重新分配到那些負載較低的機器上去。同樣,如果有新的收集器機器加入,會從那些負載高的機器上轉移部分任務給這個新加入的機器。
上述步驟已經完整的說明了整個日志收集系統的工作流程,其中有兩點注意事項:
①節(jié)點類型
在/logs/collector節(jié)點下創(chuàng)建臨時節(jié)點可以很好的判斷機器是否存活,但是,若機器掛了,其節(jié)點會被刪除,記錄在節(jié)點上的日志源機器列表也被清除,所以需要選擇持久節(jié)點來標識每一臺機器,同時在節(jié)點下分別創(chuàng)建/logs/collector/[Hostname]/status節(jié)點來表征每一個收集器機器的狀態(tài),這樣,既能實現對所有機器的監(jiān)控,同時機器掛掉后,依然能夠將分配任務還原。
② 日志系統節(jié)點監(jiān)聽
若采用Watcher機制,那么通知的消息量的網絡開銷非常大,需要采用日志系統主動輪詢收集器節(jié)點的策略,這樣可以節(jié)省網絡流量,但是存在一定的延時。
猜你喜歡