Logstash實踐: 分散式系統的日誌監控

發表於2015-12-28

1. 前言

服務端日誌你有多重視?

  1. 我們沒有日誌
  2. 有日誌,但基本不去控制需要輸出的內容
  3. 經常微調日誌,只輸出我們想看和有用的
  4. 經常監控日誌,一方面幫助日誌微調,一方面及早發現程式的問題

只做到第1點的,你可以洗洗去睡了。很多公司都有做到第2點和第3點,這些公司的服務端程式基本已經跑了很長時間了,已比較穩定,確實無需花太多時間去關注。如果一個新產品,在上線初期,我覺得就有必要做到第4點。

日誌怎麼看?

  1. 都說了,我們沒有日誌
  2. 線上日誌逐個tail+grep
  3. 編寫指令碼,下載某個時間範圍內的全部日誌到本地再搜尋

tail+grep或者把日誌下載下來再搜尋,可以應付不多的主機和應用不多的部署場景。但對於多機多應用部署就不合適了。這裡的多機多應用指的是同一種應用被部署到幾臺伺服器上,每臺伺服器上又部署著不同的多個應用。可以想象,這種場景下,為了監控或者搜尋某段日誌,需要登陸多臺伺服器,執行多個tail -Fgrep命令。一方面這很被動。另一方面,效率非常低,數次操作下來,程式設計師的心情也會變糟(我還要去維護宇宙和平的好嘛)。

這篇文章講的就是如何解決分散式系統的日誌管理問題。先給大家看看最終的效果:

日誌實時監控效果圖

單個螢幕上所有伺服器的日誌實時滾動著顯示。每條日誌開頭還標明日誌的來源(下圖)。

每行日誌標有來源資訊

實現這種效果的原理是後臺跑著一個程式,這個程式負責彙總所有日誌到一個本地檔案中。只要執行tail -f這個檔案就可以做到監控日誌了。因為所有日誌都彙總在一個檔案裡了,所以做日誌搜尋的時候只要針對這一個檔案搜尋就可以了。

能夠彙總日誌檔案的工具名字叫Logstash,即本文的介紹重點。它使用JRuby編寫,開源,主流,免費,使用簡單(宇宙和平使者必備單品)。

2. Logstash部署架構

Logstash的理念很簡單,它只做3件事情:

  1. Collect:資料輸入
  2. Enrich:資料加工,如過濾,改寫等
  3. Transport:資料輸出

別看它只做3件事,但通過組合輸入和輸出,可以變幻出多種架構實現多種需求。這裡只丟擲用以解決日誌彙總需求的部署架構圖:

Logstash部署架構

解釋術語:

  • Shipper:日誌收集者。負責監控本地日誌檔案的變化,及時把日誌檔案的最新內容收集起來,輸出到Redis暫存。
  • Indexer:日誌儲存者。負責從Redis接收日誌,寫入到本地檔案。
  • Broker:日誌Hub,用來連線多個Shipper和多個Indexer。

無論是Shipper還是Indexer,Logstash始終只做前面提到的3件事:

  • Shipper從日誌檔案讀取最新的行文字,經過處理(這裡我們會改寫部分後設資料),輸出到Redis,
  • Indexer從Redis讀取文字,經過處理(這裡我們會format文字),輸出到檔案。

一個Logstash程式可以有多個輸入源,所以一個Logstash程式可以同時讀取一臺伺服器上的多個日誌檔案。Redis是Logstash官方推薦的Broker角色“人選”,支援訂閱釋出和佇列兩種資料傳輸模式,推薦使用。輸入輸出支援過濾,改寫。Logstash支援多種輸出源,可以配置多個輸出實現資料的多份複製,也可以輸出到Email,File,Tcp,或者作為其它程式的輸入,又或者安裝外掛實現和其他系統的對接,比如搜尋引擎Elasticsearch。

總結:Logstash概念簡單,通過組合可以滿足多種需求。

3. Logstash的安裝,搭建和配置

3.1. 安裝Java

下載JDK壓縮包。
一般解壓到/user/local/下,形成/usr/local/jdk1.7.0_79/bin這種目錄結構。
配置JAVA_HOME環境變數:echo 'export JAVA_HOME=/usr/local/jdk1.7.0_79' >> ~/.bashrc

3.2 安裝Logstash

官網下載Logstash的壓縮包。
一般也解壓到/usr/local/下,形成/usr/local/logstash-1.4.3/bin這種目錄結構。

Logstash的執行方式為主程式+配置檔案。Collect,Enrich和Transport的行為在配置檔案中定義。配置檔案的格式有點像json,又有點像php。

3.3. 編寫Shipper角色的配置檔案:shipper.conf

如上,input描述的就是資料如何輸入。這裡填寫你需要收集的本機日誌檔案路徑。

如上,output描述的就是資料如何輸出。這裡描述的是輸出到Redis

data_type的可選值有channellist兩種。用過Redis的人知道,channel是Redis的釋出/訂閱通訊模式,而list是Redis的佇列資料結構。兩者都可以用來實現系統間有序的訊息非同步通訊。channel相比list的好處是,解除了釋出者和訂閱者之間的耦合。舉個例子,一個Indexer在持續讀取Redis中的記錄,現在想加入第二個Indexer,如果使用list,就會出現上一條記錄被第一個Indexer取走,而下一條記錄被第二個Indexer取走的情況,兩個Indexer之間產生了競爭,導致任何一方都沒有讀到完整的日誌。channel就可以避免這種情況。這裡Shipper角色的配置檔案和下面將要提到的Indexer角色的配置檔案中都使用了channel

如上,filter描述的是如何過濾資料。mutate是一個自帶的過濾外掛,它支援replace操作,可以改寫資料。這裡改寫了後設資料中的host欄位,替換成了我們自己定義的文字。

Logstash傳遞的每條資料都帶有後設資料,如@version,@timestamp,host等等。有些可以修改,有些不允許修改。host記錄的是當前主機的資訊。Logstash可能不會去獲取主機的資訊或者獲取的不準確,這裡建議替換成自己定義的主機標示,以保證最終的日誌輸出可以有完美的格式和良好的可讀性。

3.4 編寫Indexer角色的配置檔案:indexer.conf

如上,input部分設定為從redis接收資料

如上,output部分設定為寫入本地檔案

官方文件裡flush_interval為緩衝時間(單位秒)。我實踐下來不是秒而是數量,Logstash會等待緩衝區寫滿一定數量後才輸出。這對線上除錯是不能接受的,建議上線初期設為0。程式穩定後,隨著日誌量的增大,可以增大flush_interval的值以提高檔案寫入效能。

Indexer的配置檔案中,我明確指定了message_format的格式,其中%{host}對應的就是之前手動設定的host後設資料。

3.5. 啟動Logstash

我們來測試一下,切到Shipper主機上,模擬日誌產生:

再切換到Indexer主機上,如果出現:10.140.46.134 B[1] Hello World,說明Logstash部署成功。

3.6. 日誌著色指令碼

tail -f的時候,如果使用awk配合echo,可以匹配你想要高亮的文字,改變他們的前景色和背景色。就像效果圖裡的那樣(這是宇宙和平使者必備單品的重要屬性好嘛)。這裡附上我寫的指令碼,把指令碼中的關鍵資訊替換成你想要匹配的文字即可:

So easy,媽媽再也不用擔心我的日誌。。。

4. 還有什麼

有些公司需要挖掘日誌的價值,那僅僅收集和實時顯示是不夠的,需要把逼格上升到日誌分析技術層面。

一個完整的日誌分析技術棧需要實時收集,實時索引和展示三部分組成,Logstash只是這其中的第一個環節。Logstash所屬的Elastic公司,已經開發了完整的日誌分析技術棧,它們是Elasticsearch,Logstash,和Kibana,簡稱ELK。Elasticsearch是搜尋引擎,而Kibana是Web展示介面。

日誌分析技術棧

如果你搭建了完整的技術棧,你的老闆就可以在圖形化介面上按不同的維度去搜尋日誌了。

Kibana介面

還可以做一些高大上的統計和計算。

Kibana介面

當然,我認為90%的公司是沒有必要這麼做的(畢竟他們的程式設計師還要去維護宇宙的和平),能做到在控制檯裡監控和搜尋就能滿足需要了。但我們也可以看看剩下的那10%的公司是怎麼做的,比如這篇文章:新浪是如何分析處理32億條實時日誌的?


參考文獻:

相關文章