基於ELK Stack和Spark Streaming的日誌處理平臺設計與實現

大數據時代,隨着數據量不斷增長,存儲與計算集羣的規模也逐漸擴大,幾百上千臺的雲計算環境已不鮮見。現在的集羣所需要解決的問題不僅僅是高性能、高可靠性、高可擴展性,還需要面對易維護性以及數據平臺內部的數據共享性等諸多挑戰。優秀的系統運維平臺既能實現數據平臺各組件的集中式管理、方便系統運維人員日常監測、提升運維效率,又能反饋系統運行狀態給系統開發人員。例如採集數據倉庫的日誌可以按照時間序列查看各數據庫實例各種級別的日誌數量與佔比,採集DB2表空間數據分析可得到數據庫集羣健康狀態,分析應用服務器的日誌可以查看出錯最多的模塊、下載最多的文件、使用最多的功能等。大數據時代的業務與運維將緊密的結合在一起。

一、日誌

1.什麼是日誌

日誌是帶時間戳的基於時間序列的機器數據,包括IT系統信息(服務器、網絡設備、操作系統、應用軟件)、物聯網各種傳感器信息。日誌可以反映用戶行爲,是真實數據。

2.日誌處理方案演進

圖 1. 日誌處理方案經歷的版本迭代

   

 

l 日誌處理v1.0:日誌沒有集中式處理;只做事後追查,黑客入侵後刪除日誌無法察覺;使用數據庫存儲日誌,無法勝任複雜事務處理。

l 日誌處理v2.0:使用Hadoop平臺實現日誌離線批處理,缺點是實時性差;使用Storm流處理框架、Spark內存計算框架處理日誌,但Hadoop/Storm/Spark都是編程框架,並不是拿來即用的平臺。

l 日誌處理v3.0:使用日誌實時搜索引擎分析日誌,特點:第一是快,日誌從產生到搜索分析出結果只有數秒延時;第二是大,每天處理TB日誌量;第三是靈活,可搜索分析任何日誌。作爲代表的解決方案有Splunk、ELK、SILK。

圖 2. 深度整合ELK、Spark、Hadoop構建日誌分析系統

 

二、ELK Stack

ELK Stack是開源日誌處理平臺解決方案,背後的商業公司是elastic(https://www.elastic.co/)。它由日誌採集解析工具Logstash、基於Lucene的全文搜索引擎Elasticsearch、分析可視化平臺Kibana組成。目前ELK的用戶有Adobe、Microsoft、Mozilla、Facebook、Stackoverflow、Cisco、ebay、Uber等諸多廠商。

1.Logstash

Logstash是一種功能強大的信息採集工具,類似於Hadoop生態圈裏的Flume,任何類型的事件流都可以被input、filter、output這三個Logstash中的插件處理和轉換。另外還可以在配置文件中添加codec插件通過簡單編碼來簡化處理過程。下面以DB2的一條日誌爲例。

圖3.DB2數據庫產生的半結構化日誌樣例

 

在使用logstash進行解析時,input組件中引入codec插件中的multiline,用來將多行文本封裝爲一個事件流,並使用正則表達式指定分離事件流的標誌,在此用例中,該標誌爲以時間戳開始的行。在實際應用中,有時DB2的一條日誌會超過500行,這超出了multiline組件默認的事件封裝的最大行數,這需要我們在multiline中設置max_lines屬性。通過腳本:

awk '/Event Id/{if(t++)if(c>m)m=c;c=0;next}{c++}END{print "Event ID times="t",max="m}' JobAllDetailLog.ods_dev.Batch\:\:Calculate_CISF_Tables_count.log JobAllDetailLog.*

查看兩個Event Id之間最大的行數。

經過input讀入預處理後的數據流入filter,filter中使用grok、mutate等插件來過濾文本和匹配字段,並且我們自己可以爲事件流添加額外的字段信息:

filter {

  mutate{

    gsub => ['message', "\n", " "]

  }

  grok {

    match => { "message" => 

    "(?<timestamp>%{YEAR}-%{MONTHNUM}-%{MONTHDAY}-%{HOUR}\.%{MINUTE}\.%{SECOND})%{INT:timezone}(?:%{SPACE}%{WORD:recordid}%{SPACE})(?:LEVEL%{SPACE}:%{SPACE}%{DATA:level}%{SPACE})(?:PID%{SPACE}:%{SPACE}%{INT:processid}%{SPACE})(?:TID%{SPACE}:%{SPACE}%{INT:threadid}%{SPACE})(?:PROC%{SPACE}:%{SPACE}%{DATA:process}%{SPACE})?(?:INSTANCE%{SPACE}:%{SPACE}%{WORD:instance}%{SPACE})?(?:NODE%{SPACE}:%{SPACE}%{WORD:node}%{SPACE})?(?:DB%{SPACE}:%{SPACE}%{WORD:dbname}%{SPACE})?(?:APPHDL%{SPACE}:%{SPACE}%{NOTSPACE:apphdl}%{SPACE})?(?:APPID%{SPACE}:%{SPACE}%{NOTSPACE:appid}%{SPACE})?(?:AUTHID%{SPACE}:%{SPACE}%{WORD:authid}%{SPACE})?(?:HOSTNAME%{SPACE}:%{SPACE}%{HOSTNAME:hostname}%{SPACE})?(?:EDUID%{SPACE}:%{SPACE}%{INT:eduid}%{SPACE})?(?:EDUNAME%{SPACE}:%{SPACE}%{DATA:eduname}%{SPACE})?(?:FUNCTION%{SPACE}:%{SPACE}%{DATA:function}%{SPACE})(?:probe:%{SPACE}%{INT:probe}%{SPACE})%{GREEDYDATA:functionlog}"

    }

  }

  date {

    match => [ "timestamp", "YYYY-MM-dd-HH.mm.ss.SSSSSS" ]

  }

 }

經如上filter插件處理後的事件流便就都處理成了json格式。

Output插件用於指定事件流的去向,可以是消息隊列、全文搜索引擎、TCP Socket、Email等幾十種目標端。

2.Elasticsearch

Elasticsearch是基於Lucene的近實時搜索平臺,它能在一秒內返回你要查找的且已經在Elasticsearch做了索引的文檔。它默認基於Gossip路由算法的自動發現機制構建配置有相同cluster name的集羣,但是有的時候這種機制並不可靠,會發生腦裂現象。鑑於主動發現機制的不穩定性,用戶可以選擇在每一個節點上配置集羣其他節點的主機名,在啓動集羣時進行被動發現。

Elasticsearch中的Index是一組具有相似特徵的文檔集合,類似於關係數據庫模型中的數據庫實例,Index中可以指定Type區分不同的文檔,類似於數據庫實例中的關係表,Document是存儲的基本單位,都是JSON格式,類似於關係表中行級對象。我們處理後的JSON文檔格式的日誌都要在Elasticsearch中做索引,相應的Logstash有Elasticsearch output插件,對於用戶是透明的。

3.Kibana

Kibana是專門設計用來與Elasticsearch協作的,可以自定義多種表格、柱狀圖、餅狀圖、折線圖對存儲在Elasticsearch中的數據進行深入挖掘分析與可視化。下圖定製的儀表盤可以動態監測數據庫集羣中每個數據庫實例產生的各種級別的日誌。

圖4. 實時監測DB2實例運行狀態的動態儀表盤

 

三、Kafka

Kafka是LinkedIn開源的分佈式消息隊列,它採用了獨特的消費者-生產者架構實現數據平臺各組件間的數據共享。集羣概念中的server在Kafka中稱之爲broker,它使用主題管理不同類別的數據,比如DB2日誌歸爲一個主題,tomcat日誌歸爲一個主題。我們使用Logstash作爲Kafka消息的生產者時,output插件就需要配置好Kafka broker的列表,也就是Kafka集羣主機的列表;相應的,用作Kafka消費者角色的Logstash的input插件就要配置好需要訂閱的Kafka中的主題名稱和ZooKeeper主機列表。Kafka通過將數據持久化到硬盤的Write Ahead Log(WAL)保證數據可靠性與順序性,但這並不會影響實時數據的傳輸速度,實時數據仍是通過內存傳輸的。Kafka是依賴於ZooKeeper的,它將每組消費者消費的相應topic的偏移量保存在ZooKeeper中。據稱LinkedIn內部的Kafka集羣每天已能處理超過1萬億條消息。

圖5. 基於消息訂閱機制的Kafka架構

 


除了可靠性和獨特的push&pull架構外,相較於其他消息隊列,Kafka還擁有更大的吞吐量:

圖6. 基於消息持久化機制的消息隊列吞吐量比較

 

四、Spark Streaming

Spark 由加州大學伯克利分校 AMP 實驗室 (Algorithms, Machines, and People Lab) 開發,可用來構建大型的、低延遲的數據分析應用程序。它將批處理、流處理、即席查詢融爲一體。Spark社區也是相當火爆,平均每三個月迭代一次版本更是體現了它在大數據處理領域的地位。

Spark Streaming不同於Storm,Storm是基於事件級別的流處理,Spark Streaming是mini-batch形式的近似流處理的微型批處理。Spark Streaming提供了兩種從Kafka中獲取消息的方式:

第一種是利用Kafka消費者高級API在Spark的工作節點上創建消費者線程,訂閱Kafka中的消息,數據會傳輸到Spark工作節點的執行器中,但是默認配置下這種方法在Spark Job出錯時會導致數據丟失,如果要保證數據可靠性,需要在Spark Streaming中開啓Write Ahead Logs(WAL),也就是上文提到的Kafka用來保證數據可靠性和一致性的數據保存方式。可以選擇讓Spark程序把WAL保存在分佈式文件系統(比如HDFS)中。

第二種方式不需要建立消費者線程,使用createDirectStream接口直接去讀取Kafka的WAL,將Kafka分區與RDD分區做一對一映射,相較於第一種方法,不需再維護一份WAL數據,提高了性能。讀取數據的偏移量由Spark Streaming程序通過檢查點機制自身處理,避免在程序出錯的情況下重現第一種方法重複讀取數據的情況,消除了Spark Streaming與ZooKeeper/Kafka數據不一致的風險。保證每條消息只會被Spark Streaming處理一次。以下代碼片通過第二種方式讀取Kafka中的數據:

// Create direct kafka stream with brokers and topics

JavaPairInputDStream<String, String> messages = KafkaUtils.createDirectStream(

               jssc,

               String.class,

               String.class,

               StringDecoder.class,

               StringDecoder.class,

               kafkaParams,

               topicsSet);

messages.foreachRDD(new Function<JavaPairRDD<String,String>,Void>(){

public Void call(JavaPairRDD<String, String> v1)

           throws Exception {

v1.foreach(new VoidFunction<Tuple2<String, String>>(){

                     public void call(Tuple2<String, String> tuple2) {

                          try{

                            JSONObject a = new JSONObject(tuple2._2);

                            ...

Spark Streaming獲取到消息後便可以通過Tuple對象自定義操作消息,如下圖是針對DB2數據庫日誌的郵件告警,生成告警郵件發送到Notes郵箱:

圖6. 基於Spark Streaming對DB2異常日誌實現Notes郵件告警

 

 

五、互聯網行業日誌處理方案舉例介紹與應用

1.新浪

新浪採用的技術架構是常見的Kafka整合ELK Stack方案。Kafka作爲消息隊列用來緩存用戶日誌;使用Logstash做日誌解析,統一成JSON格式輸出給Elasticsearch;使用Elasticsearch提供實時日誌分析與強大的搜索和統計服務;Kibana用作數據可視化組件。該技術架構目前服務的用戶包括微博、微盤、雲存儲、彈性計算平臺等十多個部門的多個產品的日誌搜索分析業務,每天處理約32億條(2TB)日誌。

新浪的日誌處理平臺團隊對Elasticsearch做了大量優化(比如調整max open files等),並且開發了一個獨立的Elasticsearch Index管理系統,負責索引日常維護任務(比如索引的創建、優化、刪除、與分佈式文件系統的數據交換等)的調度及執行。爲Elasticsearch安裝了國內中文分詞插件elasticsearch-analysis-ik,滿足微盤搜索對中文分詞的需求。

2.騰訊

騰訊藍鯨數據平臺告警系統的技術架構同樣基於分佈式消息隊列和全文搜索引擎。但騰訊的告警平臺不僅限於此,它的複雜的指標數據統計任務通過使用Storm自定義流式計算任務的方法實現,異常檢測的實現利用了曲線的時間週期性和相關曲線之間的相關性去定義動態的閾值,並且基於機器學習算法實現了複雜的日誌自動分類(比如summo logic)。

告警平臺把撥測(定時curl一下某個url,有問題就告警)、日誌集中檢索、日誌告警(5分鐘Error大於X次告警)、指標告警(cpu使用率大於X告警)整合進同一個數據管線,簡化了整體的架構。

3.七牛

七牛採用的技術架構爲FlumeKafkaSpark混部在8臺高配機器。根據七牛技術博客提供的數據,該日誌處理平臺每天處理500億條數據,峯值80TPS 

Flume相較於Logstash有更大的吞吐量,而且與HDFS整合的性能比Logstash強很多。七牛技術架構選型顯然考慮了這一點,七牛雲平臺的日誌數據到Kafka後,一路同步到HDFS,用於離線統計,另一路用於使用Spark Streaming進行實時計算,計算結果保存在Mongodb集羣中。

 

任何解決方案都不是十全十美的,具體採用哪些技術要深入瞭解自己的應用場景。就目前日誌處理領域的開源組件來說,在以下幾個方面還比較欠缺:

l Logstash的內部狀態獲取不到,目前沒有好的成熟的監控方案。

l Elasticsearch具有海量存儲海量聚合的能力,但是同Mongodb一樣,並不適合於寫入數據非常多(1萬TPS以上)的場景。

l 缺乏真正實用的異常檢測方法;實時統計方面缺乏成熟的解決方案,Storm就是一個底層的執行引擎,而Spark還缺少時間窗口等抽象。

l 對於日誌自動分類,還沒有開源工具可以做到summo logic那樣的效果。

 

結束語:

大數據時代的運維管理意義重大,好的日誌處理平臺可以事半功倍的提升開發人員和運維人員的效率。本文通過簡單用例介紹了ELK Stack、Kafka和Spark Streaming在日誌處理平臺中各自在系統架構中的功能。現實中應用場景繁多複雜、數據形式多種多樣,日誌處理工作不是一蹴而就的,分析處理過程還需要在實踐中不斷挖掘和優化,筆者也將致力於DB2數據庫運行狀態更細節數據的收集和更全面細緻的監控。

參考資源 (resources)

· 參考 “日誌: 每個軟件工程師都應該知曉的實時數據集成提取的那點事”,詳細瞭解日誌處理。

· 查看文章“新浪是如何分析處理32億條實時日誌的?”,瞭解新浪的日誌處理方案設計。

· 查看文章“騰訊藍鯨數據平臺之告警系統”,瞭解騰訊在大型系統運維工程上的實踐。

· 查看文章“七牛是如何搞定每天500億條日誌的”,瞭解七牛海量日誌處理解決方案。

· 查看文章“Mesos在去哪兒網的應用”,瞭解去哪兒網利用日誌在集羣管理中的實踐。

· 參考網站“https://softwaremill.com/mqperf/”,瞭解基於消息持久化的各消息隊列各種負載下的性能分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章