1. 程式人生 > >日誌系統之基於Zookeeper的分布式協同設計

日誌系統之基於Zookeeper的分布式協同設計

服務配置 設計 onf 進程 最新 secret 要求 日誌搜索 必須

近期這段時間在設計和實現日誌系統。在整個日誌系統系統中Zookeeper的作用非常重要——它用於協調各個分布式組件並提供必要的配置信息和元數據。這篇文章主要分享一下Zookeeper的使用場景。

這裏主要涉及到Zookeeper在日誌系統中的使用,但事實上它在我們的消息總線和搜索模塊中也相同非常重要。

日誌元數據

日誌的類型和日誌的字段這裏我們統稱為日誌的元數據。我們構建日誌系統的目的終於主要是為了:日誌搜索,日誌分析。這兩大塊我們非常大程度上依賴於——ElasticSearch(關於什麽是ElasticSearch,這裏就不多做介紹了)。

關於日誌字段

日誌的字段定義,在ElasticSearch中是一個索引中某個mapping的Schema。ElasticSearch是一個號稱Schema Free的分布式全文檢索系統。這裏須要正確地理解Schema Free,它並非不須要Schema。也不是強制要求你必須有明白的Schema,有沒有都能夠做全文檢索。可是像聚合、分析等非常多高級功能都建立在明白的Schema的基礎上。因此。從分析統計的角度看,我們對日誌進行明白的字段定義是非常有必要的。

日誌與搜索模塊的協同

日誌元數據是日誌系統的基礎信息。我們在web管控臺管理它並同步至Zookeeper供其它模塊使用。比方搜索模塊。由於上文提到日誌的類型、字段事實上跟ElasticSearch的Mapping Type

是對等的映射關系。所以搜索模塊會重度依賴日誌元數據。

另外。為了保證新的日誌元數據(一般是一個新的日誌類型被創建)盡快同步至ElasticSearch。我們利用了Zookeeper的事件Push機制(或者叫Pub/Sub機制)來實時獲知日誌元數據的變化。一旦有新的日誌元數據產生。我們的搜索模塊會馬上得到事件通知,它會獲取最新的日誌元數據。然後為其在ElasticSearch的indices中新建一個mapping。為這樣的日誌類型的日誌存入ElasticSearch做好準備。

這樣的方式帶來了哪些優點。眼下來看至少有三點:

  • 實時性:搜索模塊能第一時間感知到新的日誌類型的創建
  • 低耦合性:管控臺上日誌模塊跟搜索模塊,沒有由於信息的依賴而產生較強的耦合性;它們通過Zookeeper進行了解耦
  • Mapping Type的可控性:ElasticSearch有個非常好的特性,就是當你將一個文檔存入某個mapping type,假設該文檔中存在mapping未曾定義的字段,ElasticSearch將會為你自己主動加入該字段的定義。我們覺得這樣的機制將會使日誌字段變得不可控。因此我們通過統一日誌元數據再加上後面基於相同的解析行為來保證Schema的可控性。

日誌採集

從之前的文章中,你應該能夠找到日誌採集器的選型,出於多種原因(跟消息總線的集成、可定制性、支持從zookeeper獲取配置等),我們選擇了Flume-ng。它在最新的穩定版(1.6.0)提供了從zookeeper獲取採集配置的功能。

於是,日誌採集花費在運維上的成本就大大減少了。由於有了配置之後,運維人員就不須要手動在目標server上改動配置文件,完畢各種配置,僅僅須要固定鍵入例如以下的啟動命令就可以:

sudo bin/flume-ng agent --conf conf -z 127.0.0.1:2181 -p /component/log/mysqlSlowquery/flume -name mysql-slowquery-30 -Dflume.root.logger=DEBUG,console

而上面這個命令中,唯一須要變動的僅僅有以下幾個部分:

  • zookeeper的server(集群)信息
  • 即將收集的日誌的類型的flume路徑
  • 即將收集的日誌的flume配置的znode名稱,如上例是mysql-slowquery-30

事實上原先須要手動改動配置文件的部分參數項將在提供的管控臺中進行配置,但基於web的表單填寫顯然要比在server上以命令行的方式來得easy得多。

這裏我們的做法是拆解了flume的配置文件,將其固定不變的部分做成模板,將其可變部分做成表單。在提交之前,通過模板引擎將模板跟配置信息進行合並為完整的配置並推送到Zookeeper中去。

當中須要配置的部分參數有:

  • 日誌文件所在目標server的路徑位置
  • 日誌文件名的格式
  • 日誌是單行模式還是多行模式
  • 消息源的secret(消息總線部分)
  • 消息槽的名稱(消息總線部分)
  • 消息流的token(消息總線部分)
  • ….

日誌解析

相同在之前的文章中我也提及我們在日誌解析上的選擇是morphline。

morphline是個在Hadoop生態系統中的ETL Framework。morphline也有一個配置文件用於定義一系列的Commands。而它也有固定部分和可變部分,由於解析主要應用了morphline的Grok命令,所以針對這個命令,可變部分主要是:

  • 解析字典
  • 解析的正則表達式

我們的做法相同相似於日誌採集模塊。將morphline的配置文件的固定部分做成固定模板。然後將可變部分在管控臺上進行配置。終於合並提交到Zookeeper中。

日誌解析服務(歸屬於以下的後臺服務)。在啟動時會依據自己的日誌類型,從Zookeeper的特定節點下找到該日誌類型的morphline的配置,將其獲取下來並保存在本地文件系統中,然後構建Mrophline對象(由於morphline眼下僅僅提供基於File對象的構造方式。所以多了一個先保存至本地文件再基於文件構造Morphline對象的步驟)進行解析。

後臺服務

日誌解析這邊僅僅是給解析任務提供了 元數據 。真正的解析由後臺的解析任務來完畢,我們將相似的這些同意在後臺的全部任務籠統得歸結為 後臺服務

後臺服務遵循:任務組->任務->工作線程的層次性的組織方式。依照服務的業務類型(說白了就是同一套處理邏輯)。將其劃分為不同的任務組(比方:ETL組、日誌索引組等)。不同的任務組下會有 至少 一個任務。比方ETL任務組下就會有非常多個任務(比方:nginx訪問日誌解析任務、mysql慢查詢日誌解析任務等)。而某一個任務下又存在至少一個工作線程。

任務元數據

在管控臺有一個後臺服務模塊。專門用於管理任務對象以及它們的元數據。

運行任務的工作者線程本身是無狀態的。它們在啟動的時候會去Zookeeper上下載它們運行任務所須要的元數據。

熱備機制

通常,為了服務的可用性我們會為每一個任務配備不少於一個工作者線程。

當然,這裏的 不少於一個 並不僅僅是基於一個運行後臺服務的JVM進程或一個主機節點來計數的,而是針對由多個節點組成的集群而言。

這通過一個配置來實現:

worker.minimumNumPerTask=2

它的意義是:對每一個task而言,啟動的最少的worker線程數。假設一個主機節點上啟動兩個後臺服務的JVM進程,那麽這個task就會相應4個工作者線程。

正常情況下,每一個任務在同一時刻僅僅有一個處於active狀態的工作者線程,而其它搶占失敗的都會將自己切換為standby模式。作為備援隨時待命。

這個機制是怎樣實現的?這得益於Zookeeper提供的 暫時順序 節點。

當多個工作者線程去競爭一個任務的時候,它們首先去該任務的path下創建一個子path,並註冊自己的主機等信息。

註意這裏創建的子path的類型不同於其它Zookeeper使用場景的path類型(其它path通常都是持久型的),它是暫時順序的。這兩個屬性非常重要:

  • 暫時: 當一個工作者線程掛掉之後。它本地的Zookeeper會話也會隨之失效。在其會話失效之後。暫時節點將會消失。

  • 順序:它能仲裁出創建path的client的先後順序,並在新建的path中追加標識

各個工作者線程創建暫時順序的path後,由於具有 順序 性。Zookeeper會依照它們創建的順序在path後追加帶有從1開始遞增的編號。各個工作者創建完畢後會得到各自的編號,然後它們作一個順序推斷,誰是最小的誰就會獲得任務的運行機會並成為active工作者,而其它搶占失敗的將默認切換到standby模式,這些搶占失敗的工作者線程會註冊成為它們搶占task的 子節點變更 watcher。這時 暫時 屬性就派上用場了,當處於active模式的工作者線程丟失會話之後,這些standby將會收到通知,而這時它們會再次去推斷自己的編號是不是最小的。假設是那麽就能夠接替之前的工作者線程成為active的了。這時假設有新加入的工作者線程也會觸發變更通知,但這並不會影響正常的邏輯。

當然這裏還存在一些問題有待完好:

  • active線程由於網絡延遲出現短時會話丟失的問題,可能會導致Zookeeper錯誤的推斷
  • 子節點頻繁變更可能會產生廣播風暴

動態運行新任務

每一個任務組都會有一個watcher來監控是否有新的任務被創建(比方一種新的日誌類型被提交)。假設有新任務則會在其所屬的線程池中新建新的工作者來運行新任務。

眼下暫時這個watcher默認僅僅關註新增任務,而針對任務被移除或者任務的元數據變更,watcher暫時還沒有相應的響應機制。這也是興許須要考慮和完好的部分。

後臺服務配置模板化

這樣的機制之前已經分別應用於日誌採集日誌解析模塊了,在這裏也是為了簡化後臺服務啟動時配置的問題。

總結

綜上,整個設計的Zookeeper 拓撲圖大致例如以下:

技術分享圖片

從上面的分析能夠看到。我們最大程度地將各種可變的參數配置到Zookeeper中。使其成為串聯起整個分布式系統的配置中心,而我們的管控臺某種意義上退化成了“配置系統”——將配置界面化、持久化。

同一時候。我們也利用了Zookeeper的實時事件Push機制,來進行分布式協調。

日誌系統之基於Zookeeper的分布式協同設計