寫之前這裡先打個廣告,java 版本的logstash已經開源,git位址 https://github.com/dtstack ;再放個招聘資訊 https://m.zhipin.com/weijd/v2/job/de2292afc38d32fe1XV73t25EFU~?date8=20180609&sid=self_jd&from=singlemessage&isappinstalled=0
,歡迎對技術有追求的碼農。
下面進入正題。
一是提升性能:
先說說性能問題,當時袋鼠雲的雲日志系統日志接收端是ruby 版本的logstash,存儲用elasticsearch,前端的展示沒有用原生的kibana,而是自己寫的一套前端。本人是負者日志接收端的logstash開發,基于ruby版本的logstash寫一些滿足公司業務的插件,當時為了提升性能做了各種優
化,一些子產品也用java寫的,在用ruby調用java,比如ip的解析,但是最終優化的結果是單機4core,4g的虛拟機每小時最多跑800萬的資料(我們的場景跟大部分人一樣都是訂閱kafka的消息,在經過一些filter(瓶頸主要在這裡比較耗cpu),在寫入elasticsearch)。因為logstash的核心代碼是用ruby語言開發,雖然是運作在jruby上,但是由于中間涉及到資料結構的轉化,性能是跟用原生的
java語言運作在jvm上肯定是有所差距的。是以當時也是抱着試試的心态,花了2個星期用java重寫logstash,并把自己所需要的插件也用java重寫,在同樣的4core,4g的虛拟機環境下,每小時能跑4000萬資料,性能近5倍的提升。
這是一個java logstash 和 ruby logstash(2.3.2版本)做的性能對比
二是保證資料盡量不丢失:
ruby 版本的logstash 對保證資料不丢失這塊沒做太多的設計,舉個簡單的列子,資料從kafka消費,在output到elasticsearch,一旦elasticsearch叢集不可能,ruby logstash會重試幾次還不成功就會扔掉繼續消費kafka資料,而且重試的動作也是elasticsearch插件自身完成,logstash本生沒對資料的不丢失做設計。而java 版本的logstash 的BaseOutput 這個抽象類裡面有個failedMsgQueue 這個隊列,每個output執行個體維護一個,output 插件需要自身判斷哪些資料失敗了,在把失敗的資料調用addFailedMsg 這個方法,寫入到failedMsgQueue這個隊列裡,java logstash一旦發現failedMsgQueue有資料就會調用sendFailedMsg這個方法消費failedMsgQueue這裡的資料直到沒有資料,才會消費input裡的資料這個邏輯可以通過consistency 這個屬性控制,預設是關閉的。還有一點是input和output插件都提供了release方法,這個主要是為了jvm退出時,要執行的一些動作而設計的,因為大部分的input和output插件在擷取和發送的資料都會先放在一個集合裡面,在會慢慢消耗集合裡面的資料,這樣jvm退出時,插件各自就可以實作自己的邏輯保證jvm退出時,集合裡面的資料要消費完,才能退出jvm,當然 你要是kill -9 程序那就沒法保證了。現在elasticsearch插件我們已經實作了資料不丢失這個邏輯,也在我們的線上穩定的跑了很長一段時間。
注釋:有人問jlogstash跟hangout有什麼差別,這裡就不做說明了,有興趣的同學可以看看這兩個的源碼就知道差別了。也希望jlogstash能為一些開發者解決一些問題,也希望有更多的人參與到jlogstash的開發裡來。