基于ELK和Python搭建簡單的監控告警系統

簡介

在做完支付系統后,我搭建了兩套監控系統。
一套是點評的CAT,主要用于代碼級的實時統計和歷史統計以及異常監控、主機監控等,如DAO、CACHE、MONGO、RPC、URL執行時間統計,應用HTTP輪詢監控等,當然CAT的功能并不僅限于此,我們只是用了很少的一部分。
還有一套日志監控系統,基于非常流行的ELK Stack,也就是ElasticSearch + Logstash + Kibana,本文主要說一說這套系統的玩法。

系統架構

ELK_Python監控.png

整個架構還是比較簡單的,Logstash負責收集日志數據并推送到Kafka集群中做緩沖,再由另一套Logstash從Kafka集群中取出數據推入到Elasticsearch中存儲。Python程序每隔一段時間根據關鍵字查詢上一段時間是否有錯誤日志產生,如果有,就發送郵件和微信告警。

下面分別說一說各個組件使用上的一些問題。由于網上已經有很多基礎講解、權威指南的內容,我會盡量只講干貨。

Logstash

使用版本2.3.4。
Logstash(Github,Docs)用于收集日志。在file中指定tagstype主要是為了數據打到ES時的搜索。sincedb_path是記錄日志讀取位置的文件,使用sincedb_write_interval控制寫入文件的間隔,默認是15秒。codec => multiline用于錯誤堆棧信息的合并,比如下邊的錯誤日志,就會合并成一個消息。

<pre>
2017061904514678558975|2017-06-19 04:51:53,043|DubboServerHandler:4431-thread-1372|扣款請求異常:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
</pre>

貼出部分logstash的配置文件。

# 從文件收集應用日志,推送到kafka
input {
  file {
    tags => ["pay","site"]
    path => ["/data/www/logs/pay/biz/pay-failure-0?.log","/data/www/logs/pay/biz/pay-success-0?.log"]
    type => "biz"
    sincedb_path => "/tmp/logstash_p_sincedb_biz"
  }
   file {
    tags => ["pay","site"]
    path => ["/data/www/logs/pay/debug/debug-0?.log"]
    type => "debug"
    sincedb_path => "/tmp/logstash_p_sincedb_debug"
    codec => multiline {
        pattern => "^[\d|\\|]"
        negate => true
        what => "previous"
        max_lines => 500
        multiline_tag => ["exception_stack"]
    }
  }
 }

output {
  kafka {
    bootstrap_servers => "kafka1.host:9092,kafka2.host:9092,kafka3.host:9092"
    topic_id => "pay_log_topic"
  }
}

啟動方式如下,-r --reload-interval 30 表示每30秒掃描一次配置文件,如果有改動就重新加載配置文件。

nohup /usr/local/logstash-2.3.4/bin/logstash agent -l /usr/local/logstash-2.3.4/logstash_pay.log -r --reload-interval 30 -f /usr/local/logstash-2.3.4/config/pay_to_kafka.conf >/dev/null 2>&1 &

在收集日志時,也要做好日志的分類工作,哪些需要存儲,哪些不需要,哪些日志該用什么標簽區分出來,都需要考慮。

# 從kafka取日志,推送到ES
input {
  kafka {
    zk_connect => "kafka1.host:2181,kafka2.host:2181,kafka3.host:2181"
    consumer_threads => 1
    topic_id => "pay_log_topic"
    # 注意同一個topic要使用同一個group_id,否則會導致重復消息(類似發布訂閱模式)
    group_id => "logstash_pay"
    type => "pay"
  }
}

output {
  elasticsearch {
    hosts => ["es.host"]
    # es索引格式
    index => "pay-%{+YYYY.MM.dd}"
    idle_flush_time => 5
    workers => 2
  }
}

啟動方式和收集應用日志的logstash類似。

Kafka

使用版本為2.10-0.8.2.2。
使用Kafka集群做數據緩沖,主要是考慮到網絡波動和組件重啟可能導致的服務不可用,尤其是ES和業務服務器分布在不同機房,需要走外網VPN做數據交互,網絡問題的出現概率就大大增加了。
目前我們用于日志處理的Kafka和Zookeeper使用3臺服務器,每個topic分別3 partitions、3 replications。

Kafka在使用上沒有遇到太多問題,暫略。

ElasticSearch

使用版本為2.3.5。
由于服務器資源有限,ES暫時只使用一臺服務器做數據節點。目前我們收集的日志量不是很多,每天大概20G的3000W+條日志。可以使用ES的插件Elastic HQ查看ES的內部狀態。
ES在上手使用上非常簡單,配置文件稍微修改就可以使用。
我們遇到的問題:

  • 為了性能上的考慮,最好使用bootstrap.mlockall: true來鎖住內存避免使用swap。
  • ES會占用較多的文件句柄數,在我們的系統中是5W+,所以需要調整操作系統的文件句柄數到比較大的值,官方建議65536或以上。可通過ulimit -n 65536/etc/security/limits.conf調整。
  • ES會占用較多的內存,建議分配較多內存。我現在使用的參數是-Xms12g -Xmx24g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintClassHistogram -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC。如果服務器是ES專用,可以把Xms與Xmx設置成一樣的。堆內存設置的太小,會導致頻繁GC,嚴重影響性能。GC優先使用CMS,降低GC導致的應用停頓時間。

Kibana

使用版本為4.5.4。
Kibana的作用是方便用戶和ES交互。
修改config/kibana.yml,將ES地址填寫到elasticsearch.url后,使用nohup bin/kibana &啟動即可。

數據的存儲和展示都做好了,下邊就是監控的部分。

Python監控程序

使用apscheduler作為定時器,定時做監控任務。除了對錯誤日志的監控,還寫了對activemq隊列消息積壓情況、JAVA應用線程數的監控(基于jolokia)。這次只說日志監控。

from apscheduler.schedulers.blocking import BlockingScheduler

def job_monitor_es_error_pay():
    try:
        monitor_es_error.monitor()
    except Exception, e:
        handle_error('monitor_es_error_pay', e)


if __name__ == '__main__':
    # 嘗試獲取鎖再執行。自己實現的分布式鎖,避免監控系統單點故障,主要使用https://github.com/glasslion/redlock
    master_lock_util.get_lock_block()
    # 創建阻塞型定時器
    sched = BlockingScheduler()
    # es 錯誤日志
    es_interval = props['es_err']['interval']  # default 180
    sched.add_job(job_monitor_es_error_pay, 'interval', seconds=es_interval)
    sched.start()

monitor_es_error.monitor()的具體代碼就不貼出來了,只說下邏輯:

  1. 獲取本次查詢的時間段,本次的開始時間為上次執行的結束時間,結束時間為當前時間。
  2. 確定ES索引,es的索引在每天8點才會新建(不確定其他版本是否規則相同),所以當天8點前是要查詢昨天的索引的。查詢關鍵字:tags:exception_stack AND type:error AND @timestamp:['+str(time_range[0])+' TO '+str(time_range[1])+']'。tags和type都是之前logstash推送時加入的標簽,error表示錯誤日志,exception_stack是帶有錯誤堆棧的日志。還可以通過AND -"關鍵字"的方式排除不想查找的關鍵字。@timestamp確定了時間段。
  3. 根據查詢出的結果,選擇是否報警,可選擇微信或郵件報警。郵件中將前100個錯誤的每個錯誤堆棧信息前50行打印。微信只做摘要,將錯誤信息截取發送。郵件模板使用jinja2
  4. 發送郵件時,帶有kibana的url,負責人可直接訪問kibana獲取相關錯誤信息。也可以根據錯誤的requestId將所有相關日志查詢出來,便于分析。

總結

這套監控系統上線半年多了,雖然可能看起來簡陋無比,但對于我們來說,是真正從兩眼一抹黑根據用戶反饋處理問題的原始部落時代進步到了透明化近乎實時地處理和響應問題的新石器時代。不僅僅是對于用戶相關的問題,系統中很多隱患和重大問題,通常都會有一些前兆,只有更主動地發現問題,才能在越來越復雜地業務場景面前立于不敗之地。
依據這套系統修復的bug已數不勝數(誰還沒寫點bug :P),做出的系統優化也非常多。比如GC時間過長問題、支付網關http連接池問題、rpc調用瞬時異常、activemq集群阻塞不消費等等問題。
因為不屬于公司要求的項目,所有這些都是我用業余時間一點點做起來的。公司的服務器資源也有限,所有的服務器都是復用的,連監控程序也是跑在測試環境的,為了高可用,才做的分布式鎖避免單點故障。
先到這吧。

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

推薦閱讀更多精彩內容