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