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

2021-07-09 04:32:04 字數 3231 閱讀 8410

最近這段時間在設計和實現日誌系統,在整個日誌系統系統中zookeeper的作用非常重要——它用於協調各個分布式元件並提供必要的配置資訊和元資料。這篇文章主要分享一下zookeeper的使用場景。這裡主要涉及到zookeeper在日誌系統中的使用,但其實它在我們的訊息匯流排和搜尋模組中也同樣非常重要。

日誌的型別和日誌的字段這裡我們統稱為日誌的元資料。我們構建日誌系統的目的最終主要是為了:日誌搜尋,日誌分析。這兩大塊我們很大程度上依賴於——elasticsearch(關於什麼是elasticsearch,這裡就不多做介紹了)。

這種方式帶來了哪些好處,目前來看至少有三點:

從之前的文章中,你應該可以找到日誌採集器的選型,出於多種原因(跟訊息匯流排的整合、可定製性、支援從zookeeper獲取配置等),我們選擇了flume-ng。它在最新的穩定版(1.6.0)提供了從zookeeper獲取採集配置的功能。於是,日誌採集花費在運維上的成本就大大降低了。因為有了配置之後,運維人員就不需要手動在目標伺服器上修改配置檔案,完成各種配置,只需要固定鍵入如下的啟動命令即可:

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

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

其實原先需要手動修改配置檔案的部分引數項將在提供的管控臺中進行配置,但基於web的表單填寫顯然要比在伺服器上以命令列的方式來得容易得多。

這裡我們的做法是拆解了flume的配置檔案,將其固定不變的部分做成模板,將其可變部分做成表單。在提交之前,通過模板引擎將模板跟配置資訊進行合併為完整的配置並推送到zookeeper中去。

其中需要配置的部分引數有:

同樣在之前的文章中我也提及我們在日誌解析上的選擇是morphline。morphline是個在hadoop生態系統中的etl framework。morphline也有乙個配置檔案用於定義一系列的commands。而它也有固定部分和可變部分,因為解析主要應用了morphline的grok命令,所以針對這個命令,可變部分主要是:

我們的做法同樣類似於日誌採集模組,將morphline的配置檔案的固定部分做成固定模板,然後將可變部分在管控台上進行配置,最終合併提交到zookeeper中。

日誌解析服務(歸屬於下面的後台服務),在啟動時會根據自己的日誌型別,從zookeeper的特定節點下找到該日誌型別的morphline的配置,將其獲取下來並儲存在本地檔案系統中,然後構建mrophline物件(因為morphline目前只提供基於file物件的構造方式,所以多了乙個先儲存至本地檔案再基於檔案構造morphline物件的步驟)進行解析。

日誌解析這邊只是給解析任務提供了元資料,真正的解析由後台的解析任務來完成,我們將類似的這些允許在後台的所有任務籠統得歸結為後台服務

後台服務遵循:任務組->任務->工作執行緒的層次性的組織方式。按照服務的業務型別(說白了就是同一套處理邏輯),將其劃分為不同的任務組(比如:etl組、日誌索引組等),不同的任務組下會有至少乙個任務,比如etl任務組下就會有很多個任務(比如:nginx訪問日誌解析任務、mysql慢查詢日誌解析任務等),而某乙個任務下又存在至少乙個工作執行緒。

在管控台有乙個後台服務模組,專門用於管理任務物件以及它們的元資料。

通常,為了服務的可用性我們會為每個任務配備不少於乙個工作者執行緒。當然,這裡的不少於乙個並不只是基於乙個執行後台服務的jvm程序或乙個主機節點來計數的,而是針對由多個節點組成的集群而言。

這通過乙個配置來實現:

worker.minimumnumpertask=2
它的意義是:對每個task而言,啟動的最少的worker執行緒數。如果乙個主機節點上啟動兩個後台服務的jvm程序,那麼這個task就會對應4個工作者執行緒。

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

這個機制是如何實現的?這得益於zookeeper提供的臨時順序節點。

當多個工作者執行緒去競爭乙個任務的時候,它們首先去該任務的path下建立乙個子path,並註冊自己的主機等資訊。注意這裡建立的子path的型別不同於其他zookeeper使用場景的path型別(其他path通常都是持久型的),它是臨時順序的。這兩個屬性非常重要:

各個工作者執行緒建立臨時順序的path後,由於具有順序性,zookeeper會按照它們建立的順序在path後追加帶有從1開始遞增的編號。各個工作者建立完成後會得到各自的編號,然後它們作乙個順序判斷,誰是最小的誰就會獲得任務的執行機會並成為active工作者,而其他搶占失敗的將預設切換到standby模式,這些搶占失敗的工作者執行緒會註冊成為它們搶占task的子節點變更watcher。這時臨時屬性就派上用場了,當處於active模式的工作者執行緒丟失會話之後,這些standby將會收到通知,而這時它們會再次去判斷自己的編號是不是最小的,如果是那麼就可以接替之前的工作者執行緒成為active的了。這時如果有新加入的工作者執行緒也會觸發變更通知,但這並不會影響正常的邏輯。

當然這裡還存在一些問題有待完善:

每個任務組都會有乙個watcher來監控是否有新的任務被建立(比如一種新的日誌型別被提交)。如果有新任務則會在其所屬的執行緒池中新建新的工作者來執行新任務。目前暫時這個watcher預設只關注新增任務,而針對任務被移除或者任務的元資料變更,watcher暫時還沒有相應的響應機制。這也是後續需要考慮和完善的部分。

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

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

從上面的分析可以看到,我們最大程度地將各種可變的引數配置到zookeeper中,使其成為串聯起整個分布式系統的配置中心,而我們的管控臺某種意義上退化成了「配置系統」——將配置介面化、持久化。同時,我們也利用了zookeeper的實時事件push機制,來進行分布式協調。

zookeeper學習之zookeeper集群

匯入zookeeper原始碼包,解壓安裝到你放置的資料夾 命令 tar zxvf 原始碼包名 進入解壓後的資料夾 conf目錄,複製zoo zample.cfg檔案並重命名 命令 cp zoo zample.cfg zoo.cfg 使用vim編輯器修改zoo.cfg檔案 命令 vim zoo.cfg...

Poco 日誌 之 系統日誌

poco 支援windows 事件日誌.僅支援win poco autoptrlog new poco eventlogchannel log open poco message msg msg.setsource 1111 msg.settext 333 msg.setpriority poco ...

基於redis佇列的日誌系統實現

1 log的儲存不應該被當前執行緒的session影響,和log4j一樣,執行到哪一步就記錄哪一步,輸出到資料庫,不能出現錯誤回滾或則儲存失敗。2 log的儲存和插入不能影響當前執行緒,不能因為日誌儲存過多而影響當前程序響應速度,或則占用資料庫資源影響程序的讀寫。先將日誌產生後放入快取佇列中,不影響...