轉-大數據主題分享第三期 | 基于ELK的億級實時日志分析平臺實踐

1. ELK是什么,為什么要使用ELK;

2. 斗魚ELK日志分析平臺實踐;

3. 高并發環境下的ELK相關優化;

在講解ELK之前我先來闡述一下日志在互聯網應用中的重要性。在互聯網行業里日志數據非常重要,形式也多種多樣。通過日志我們可以計算請求量、流量來源分析、了解用戶行為、鑒別作弊用戶(如:是否是機器人)等等。

在計算PV、UV的場景下,根據業務需求我們通常以離線方式(MR / HIVE)隔天進行報表相關數據生產。但是對于故障排查肯定是希望能夠快速的進行日志查詢、定位、解決問題,對于實時性要求非常高。

舉個例子,對于一個大流量的Web應用通常以Stateless方式設計,這樣可以更方便的進行水平擴容。但是隨著應用實例數量越來越多,我們查詢日志就越來越困難。在沒有日志系統的情況下,首先我們需要定位到請求的服務器地址,如果每臺服務器都部署了多個應用實例,我們則需要去每個應用實例的日志目錄下去找日志文件。每個服務可能還會設置日志滾動策略(如:每200M一個文件),還有日志壓縮歸檔策略。

我們查詢一條出錯信息就要在茫茫多的日志文件里去找到它,于是使出我們的十八般武藝head less tail grep wc awk count cut,但是如果需要統計最近3天的某個接口的異常次數。。。。

除了上面出現的狀況我們還需要考慮:日志量太大如何歸檔、文本搜索太慢怎么辦、如何多維度查詢,ELK就是幫我們來解決這些問題的。

1. ELK是什么,為什么要使用ELK

ELK 是elastic公司提供的一套完整的日志收集、展示解決方案,是三個產品的首字母縮寫,分別是ElasticSearch、Logstash 和 Kibana。

ElasticSearch簡稱ES,它是一個實時的分布式搜索和分析引擎,它可以用于全文搜索,結構化搜索以及分析。它是一個建立在全文搜索引擎 Apache Lucene 基礎上的搜索引擎,使用 Java 語言編寫。

Logstash是一個具有實時傳輸能力的數據收集引擎,用來進行數據收集(如:讀取文本文件)、解析,并將數據發送給ES。

Kibana為 Elasticsearch 提供了分析和可視化的 Web 平臺。它可以在 Elasticsearch 的索引中查找,交互數據,并生成各種維度表格、圖形。

2. 斗魚ELK日志分析平臺實踐;

最初我們引入ELK的原因是實現一個小需求,實時統計服務器500錯誤數量,在使用過程中發現ELK的功能確實非常強大,隨后接入其它業務部門應用日志,解決日志查詢慢的痛點,加速錯誤定位。于2016年底接入全站所有服務器日志,并完成了ES 5.0的升級。

隨著對ELK技術棧的不斷深入,我們將監控報警系統的數據存儲層由HBase替換成ES。監控報警系統的數據存儲層主要數據類型是時間序列數據,如某一時刻的應用CPU使用率。通常在做數據展示時我們會將數據先以某一時間粒度(如:5分鐘)進行后端聚合匯總再交給前端進行渲染,并且這個時間粒度會隨著用戶選擇的時間區間而變化,針對此類需求我們依靠ES提供的強大數據聚合特性極大減少了開發成本。

最初我們并沒有使用ELK全套技術棧,我們使用了Flume(一個Java編寫的日志采集、聚合和傳輸系統類似上述的Logstash)作為日志收集Agent。Flume使用 tail -f 的方式實時收集日志文件中追加的文本內容。通過Flume配置文件中定義的正則表達式對日志文本進行字段分割,隨后寫入ElasticSearch,整體架構如下圖:

在使用過程中發現Flume偶爾會OOM,原因是使用了Flume的Memory Channel。使用此方式時,Flume會將 tail -f 讀取到的數據寫入內存,隨后輸出到ES。但是一旦數據輸出速度小于數據讀取速度時內存中積壓的數據就會越來越多,從而產生OOM。

于是我們將Flume中的Memory Channel替換成File Channel,該方式在數據讀取之后,將數據寫入Flume中的本地文件存儲再讀取(個人覺得不是很優雅)。

使用過程中還發現在日志收集過程中Flume搶占了大量CPU資源用于日志解析(通過正則),導致服務器中其他應用資源不足。于是我們搭建了一個Flume日志聚合層,將日志解析工作放在聚合層中完成,Agent只做數據收集、推送。隨后架構變成下面這個樣子。

聚合層中的Flume實例為無狀態節點,如果性能不足可以增加聚合層中的Flume實例數量,但是要在Agent端配置文件中添加新Flume聚合層實例的IP端口信息,并重新啟動。

穩定一段時間后,問題又來了。tail -f 方式收集日志在Flume Agent重啟時會丟失重啟時間段的數據。嘗試使用Flume提供的 Spooling Directory Source 也并不能完美的解決問題(需要修改所有日志文件存儲方式,每分鐘去切割文件,如果跟其他業務團隊這樣說,估計會被打死)。并且我們當時正在準備進行ES的1.x to 2.x版本的升級,但是Flume并不支持數據寫入ES 2.x版本,于是我們果斷放棄了Flume投入Logstash的懷抱。

Logstash相對于Flume提供了更加豐富的日志處理器,并且支持最新ES版本(畢竟是親兒子)。Logstash在進行文本數據收集時并沒有使用 tail -f 這種簡單粗暴的方式,而是在本地文件中記錄了日志文件被讀取到的位置,完美解決了上面說的升級重啟時丟失數據的問題。

將Flume聚合層替成了Kafka消息隊列,我們的監控系統通過Kafka提供的API實時獲取Kafka中的隊列Metrics,并設置閾值進行報警,這種集中式的隊列監控也是Flume聚合層無法做到的。

在這種標準的ELK架構下,日志收集已經非常穩定,但是還有2點不足:

1. Logstash體積太大,依賴Java環境,其他部門的運維同學每次都要先部署一套JDK,不開心;

2. Logstash日志解析資源占用偏高;

為了減少Agent體積,方便運維同學部署,我們將Logstash替換成了FileBeat(也是elastic公司的產品)、Rsyslog(用來收集系統日志),而且這2個組件無需依賴Java環境就能運行,安裝包10M不到。并且Agent內存占用也得到了極大改善。

針對第二個日志解析資源占用偏高的問題。Logstash的核心代碼是用ruby語言開發,雖然是運行在jruby上,但是由于中間涉及到數據結構的轉化,性能是跟用原生的java語言運行在jvm上肯定是有所差距的,于是我們在部分場景使用Hangout替換了Logstash。

最后針對日志存不規范的情況,一個日志文件中日志有多種結構,可能正則表達式(或者GROK)不是很好寫,即便是寫出來之后性能也達不到要求。針對這種日志不規范的這種情況我們自己寫了一些基于規則判斷的解析器代替正則表達式去完成解析工作,性能獲得極大提升,日志解析時的CPU占用率降低了一個數量級。

說到這里,一個能應對高并發的ELK架構終于成型了,上圖。

從上圖中可以看到,這里部署了多套ES集群(A、B、C)。這樣做是為了避免所有業務放在一個大集群中相互影響。如此一來每個業務(或者某些業務)都有獨立的集群,更加方便運維。

Kibana與多個ES集群之間通過Tribe Node進行交互,Tribe Node作為集群聯邦節點負責將請求路由到正確的后端ES集群上,做到后端ES集群拓撲變化時對使用方透明。

目前整個斗魚負責日志這一塊的ELK集群總共包含50+物理服務器、700T數據、日增數據量為15T。

3. 高并發環境下的ELK相關優化;

首先來介紹索引的。在最初我們以天為單位,使用ES中的Index templates方式自動創建索引。但是一旦ES節點出現故障,由于分片中的數據量非常大,分片恢復速度十分緩慢,于是我們將索引改為按小時劃分。按小時劃分后每個索引中的數據自然少了許多,當ES故障時可以更快的恢復當前索引,不阻塞后續的數據寫入。

針對索引的優化我們關閉了_all及其他不必要的field以降低索引大小切關閉字段分詞。這樣設置以后查詢只能通過某個具體的Key去查詢(類似level:ERROR),在日志場景下完全夠用。可以將日志打印成JSON格式,減少日志解析工作量。通過索引模板設置按照某一規則解析Field的類型,如:將xxxCount、xxxSize的Field自動解析成數字類型,其它字段解析成text等等。

關于索引分片,在服務器壓力不大的前提下,索引的分片數量盡量少,只要能滿足業務正常執行,越多的分片在查詢時需要合并的次數也就越多。通常每個分片只設置1個副本,副本分片在ES中默認配置下是以同步方式寫入的,每次寫入數據時當所有副本寫入完成以后才返回結果,也就是說副本越多寫入壓力越大且耗時越長,所以設置1個副本保證最基本的容災即可。

如果使用副本異步同步,ES主分片寫入完成后不會等待副本分片寫入完畢,直接返回結果給客戶端。在高并發環境下日志生產的速度很快,在日志解析器速度夠快的情況下會直接對ES發起第二批寫入請求,這樣循環下來會導致ES副本在高峰期永遠同步不完,失去容災的意義,所以不推薦使用。

當索引穩定無數據寫入時,對索引進行ForceMerge。ForceMerge操作會合并分片中的segment,簡單點解釋就是可以把多個小文件中的數據合并到一個大文件中再進行索引排序,可明顯提升查詢性能。ForceMerge對服務器資源消耗比較高,并且執行時間很長(基于索引的大小),建議在集群壓力最小的時候(比如凌晨,通過定時任務)執行。

下面再來談一下ES節點的部署方式。最重要的一點就是節點角色獨立,在一個小型ES集群里每個節點通常既作為Master又負責數據處理,但是在一個大型集群中節點角色混合會發生不穩定的情況。比如當數據壓力過大時導致頻繁GC、甚至節點掉線。無論GC導致的停頓還是節點掉線均會影響該節點上Master角色所提供的服務,如果該Master是當前活動的主節點的話,掉線就又會產生重新選主的行為,代價還是蠻大的。

我們服務器的配置為2CPU32核 / 128G RAM / 16 * 6T SATA。每個集群上Master部署奇數個(3~7個),同時設置discovery.zen.minimum_

master_nodes=master總數/2+1 避免集群腦裂,內存不宜過多,控制GC導致的停頓時間。

每個Data節點分配30G內存,最多不超過31.xxG內存,不同JDK版本的這個邊界值不一樣,少于該邊界值時JVM會采用內存對象指針壓縮技術提高內存利用率(至于如何確定這個邊界值,我會在最后給出鏈接)。那么對于128GB內存的服務器我們該如何分配內存呢?我們將每臺服務器部署了2個Data節點實例,加起來占用大約一半內存,剩余的內存留給操作系統緩存,在搜索時Lucence會查找Segment文件,這時如果命中操作系統緩存會大幅度提升搜索速度。

在服務器啟動多個Data節點實例的情況下要注意一個問題,一旦服務器宕機有可能導致主從分片均不可用(主從分片被分配在同一臺服務器的不同實例上了)。針對這種情況需要開啟?cluster.routing.allocation.

same_shard.host?選項,禁止主從分片被分到同一臺服務器上,保證服務器宕機時有副本分片可用。

還有,注意給每個ES節點分配不同的磁盤,避免節點之間的IO競爭。

關于ES相關的優化其實還有很多,網上一搜一大把這里就不一一列舉。調優的過程中最基礎的還是對物理服務器以及集群做持續監控,通過ES提供的CAT API我們可以很方便的獲取集群中的各項指標,如查詢負載、查詢延遲、索引隊列長度、請求拒絕次數等等,我們可以將這些指標數據通過腳本定時讀取然后回寫到ES中,在KIBANA上建立這些數據的可視化圖形,這樣一個簡單的監控系統就出來了。

服務器級別的監控能最快落地的方式就是搭一個Zabbix,主要了解CPU、內存、IO等硬件資源使用情況,方便定位問題,找出性能瓶頸。

在來說一下ES的安全問題。在2017年年初的時候暴露在互聯網上的ElasticSearch集群在全球范圍遭到大量劫持,黑客在ES中留下了一條與贖金要求相關的索引定義,具體如下所示:

文本內容寫道,如果希望恢復數據需要向黑客的賬戶中支付比特幣,如何避免這種悲劇發生呢?

1、最關鍵的一點就是不要將ES暴露在互聯網中,這一點應該是針對所有服務器應用。除非直接與用戶交互,所有應用都不應該暴露在互聯網中,Web應用應該通過Nginx反向代理并且僅暴露需要交互接口,防止黑客調用那些私有接口以及使用Web容器漏洞。

如果服務器配置了外網IP,可以在外網交換機上封鎖不需要的端口。如果不方便這么做,則開啟服務器上的iptables(記得高并發情況下增大iptables跟蹤表大小,這里就不展開了),只允許部分端口的入站請求。還可以將所有服務設置成只監聽本地局域網請求(ES中可以設置network.bind_host=192.168.x.x)。

2. 關閉不必要的ES HTTP端口。用戶能連接到ES的HTTP端口,就可以通過REST API去對集群進行操作。僅開啟Client節點上的HTTP端口,并通過反向代理方式暴露給用戶,配置反向代理屏蔽那些有風險的API接口并開啟訪問日志,做到操作能夠被審計。

3. 及時更新ElasticSearch版本,ElasticSearch完全遵循語義化版本號(x.y.z),小版本的升級基本不會出現兼容性問題。

主版本號(x):當你做了不兼容的 API 修改;

次版本號(y):當你做了向下兼容的功能性新增;

修正版本號(z):當你做了向下兼容的問題修正;

4. 修改默認的ElasticSearch集群名稱,避免出現集群中出現陌生節點;

5. 禁用通配符刪除索引(小手一抖,數據帶走);

6. 使用非Root用戶啟動ES;

問答:

1、斗魚有用到RabbitMQ或者Kafka之類的消息隊列嗎?消息隊列適合哪種使用場景,有哪些注意點?Redis如何和消息隊列結合使用,Redis使用有哪些注意事項?

答:消息隊列的場景還是在于數據驅動的場景,如果上游服務不關注下游的執行結果,很適合使用消息隊列。Redis也有消息隊列的功能,但是好像并不支持多消費者。只是一個FIFO的隊列

2、目前斗魚這邊接入elk平臺的業務有哪些共同特性?碰到es 慢寫入和慢查詢的時候,排查的步驟有哪些?關于es使用object與嵌套結構的分別是什么場景?

答:碰到ES寫入慢和查詢慢的時候,先是查看監控、硬件資源以及ES中各種線程池的狀況。

3、kafka消息隊列支持更新隊列里面的消息嗎?支持優先級嗎?

答:不支持

4、在Flume無法支撐當前業務系統時如何進行技術替換以及可行性分析,

答:如果只是Flume寫Kafka這一個流程,換Logstash就行了。關于技術選型,可以看一下谷歌指數、GITHUB星星數量對比一下同類框架,社區活躍才是真的好

5、kafka消息持久化支持嗎?就是kafka服務掛了之后,消息是否會丟失

:消息不會丟失的,但是Kafka刪除數據是基于時間,比如一周,這個不會一直存儲。Kafka還是針對于大數據場景,會發生數據丟失的情況,測試過。如果是敏感數據還是使用RabbitMQ

6、請問有沒有好的社區推薦?

答:推薦ES的官方文檔還是很全的,最好的社區就是GITHUB以及ES官方論壇然后國內也有個問答網站的?https://elasticsearch.cn/,還有關注ES公眾號

7、kafka的消息也是存在內存中的嗎?

:是直接落盤, Kafka有個ACK機制,如果是不需要ACK是會丟的,看自己的設置。

8、一般程序都是用log4j和log back的,為啥不自定義appender 通過zookeeper +kafka 消費kafka 數據直接建立索引到es 這樣不是快?

答:1. 做基礎組件一定要使用最小依賴,給應用依賴留有空間,讓應用方不要有顧慮。

2. Agent收集方便停機維護,即使Kafka掛了也不會丟消息。

3. 不能保證Kafka的日志Appender日志不會產生其他阻塞情況。

9、收集到的數據進入了HSDF了嗎?

答:目前沒有持久化需求,如果想永久保留日志,可以新建個Kafka消費者寫HDFS。

10、斗魚有用日志做調用鏈嗎?

答:有日志調用鏈,正在做可視化的東西,調用鏈可以參考PinPoint,用JavaAgent做logger的字節碼織入,只不過PinPoint運行時依賴有點重。調用鏈主要還是記錄調用的setp以及他的深度,可以想象成一個樹形結構,可以定義一個ThreadLocal變量存放這些信息。

11、日志告警的定制化需求,比如多少分鐘內出現多少次錯誤就報警

:我們開發了自己的告警平臺,可以做到“包括日志告警的定制化需求,比如多少分鐘內出現多少次錯誤就報警”這種定定制話的需求,如果想在公司里開發一套,可以先玩玩Zabbix,學習一些它的理念,很有幫助。

12、用了jstom這種流式處理吧?

:用了,還有spark streaming

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容