日誌分析在web系統中故障排查、效能分析方面有著非常重要的作用。目前,開源的ELK系統是成熟且功能強大的選擇。但是部署及學習成本亦然不低,這裡我實現了一個方法上相對簡單(但準確度和效率是有保證的)的實現。另外該指令碼的側重點不是通常的PV,UV等展示,而是短期內(如三天歷史or一週歷史)提供細粒度的異常和效能分析。
先說一下我想實現這個功能的驅動力(痛點)吧:
我們有不少站點,前邊有CDN,原站前面是F5,走到源站的訪問總量日均PV約5000w。下麵是我們經常面臨一些問題:
-
CDN回源異常,可能導致我們源站頻寬和負載都面臨較大的壓力。這時需要能快速的定位到是多了哪些回源IP(即CDN節點)或是某個IP的回源量異常,又或是哪些url的回源量異常
-
在排除了CDN回源問題之後,根據zabbix監控對一些異常的流量或者負載波動按異常時段對比正常時段進行分析,定位到具體的某(幾)類url。反饋給開發進行review以及最佳化
-
有時zabbix會監控到應用伺服器和DB或者快取伺服器之間的流量異常,這種問題一般定位起來是比較麻煩的,甚至波動僅僅是在一兩分鐘內,這就需要對日誌有一個非常精細的分析粒度
-
我們希望能所有的應用伺服器能過在本機分析日誌(分散式的思想),然後將分析結果彙總到一起(MySQL)以便檢視;並且還希望能盡可能的實時(將定時任務間隔設定低一些),以便發現問題後能儘快的透過此平臺進行分析
-
通用和效能:對於不同的日誌格式只需對指令碼稍加改動即可分析;因為將日誌分析放在應用伺服器本機,所以指令碼的效能和效率也要有保證,不能影響業務
再說下原理:
比較簡單,就是利用python的re模組透過正則運算式對日誌進行分析處理,取得uri、args、時間當前、狀態碼、響應大小、響應時間、使用者IP、CDN ip、server name 等資訊儲存進資料庫。
當然前提規範也是必須的:
-
各臺server的日誌檔案按統一路徑存放
-
日誌格式保持一致
-
每天的0點日誌切割
我的nginx日誌格式如下:
日誌分析原理:
透過Python的re模組,按照應用伺服器的日誌格式編寫正則,例如按照我的日誌格式,寫出的正則如下(編寫正則時,先不要換行,確保空格或引號等與日誌格式一致,最後考慮美觀可以折行)
用以上正則來整體匹配一行日誌記錄,然後各個部分可以透過log_pattern_obj.search(log).group(‘remote_addr’)、log_pattern_obj.search(log).group(‘body_bytes_sent’)
等形式來訪問
對於其他格式的nginx日誌或者Apache日誌,按照如上原則,並對資料庫結構做相應調整,都可以輕鬆的使用該指令碼分析處理。
原理雖簡單但實現起來卻發現有好多坑,主要是按照上述的日誌格式(靠空格或雙引號來分割各段)主要問題是面對各種不規範的記錄時(原因不一而足,而且也是樣式繁多),如何正確的分割及處理日誌的各欄位,這也是我用re模組而不是簡單的split()函式的原因。程式碼裡對一些“可以容忍”的異常記錄透過一些判斷邏輯予以處理;對於“無法容忍”的異常記錄則傳回空字串並將日誌記錄於檔案。
其實對於上述的這些不規範的請求,最好的辦法是在nginx中定義日誌格式時,用一個特殊字元作為分隔符,例如“|”。這樣都不用Python的re模組,直接字串分割就能正確的獲取到各段。
接下來看看使用效果:
先看一行資料庫裡的記錄
其中uri_abs和args_abs是對uri和args進行抽象化(抽象出一個樣式出來)處理之後的結果。對uri中個段和args中的value部分除了完全由[a-zA-Z-_]+組成的部分之外的部分都用“?”做替換。uri_abs_crc32和args_abs_crc32兩列是對抽象化結果進行crc32計算,這兩列單純只是為了在MySQL中對uri或args進行分類統計彙總時得到更好的效能。
現在還沒有完成統一分析的入口指令碼,所以還是以sql陳述句的形式來查詢(對使用者的sql功底有要求,不友好待改善)
-
查詢某站點日/小時pv(其實這一套東西的關註點並不在類似的基礎的統計上)
select count(*) from www where time_local>=’2016-12-09 00:00:00′ and time_local<='2016-12-09 23:59:59'
-
查詢某型別url總量(or指定時間段內該url總量)
依據表中的url_abs_crc32欄位
mysql> select count(*) from www where uri_abs_crc32=2043925204 and time_local > ‘2016-11-23 10:00:00’ and time_local
-
平均響應時間排行(可基於總量分析;亦可根據時段對比分析)
-
平均響應大小排行
以上只列舉了幾個例子,基本上除了UA部分(程式碼中已有捕捉,但是筆者用不到),其他的資訊都以包含到表中。因此幾乎可以對網站流量,負載,響應時間等方面的任何疑問給出資料上的支援。
Python外部包依賴:pymysql
MySQL(筆者5.6版本)將innodb_file_format設定為Barracuda(這個設定並不對其他庫表產生影響,即使生產資料庫設定也無妨),以便在建表陳述句中可以透過ROW_FORMAT=COMPRESSED將innodb表這隻為壓縮樣式,筆者實驗開啟壓縮樣式後,資料檔案大小將近減小50%。
接下來請看程式碼:
最後按照我們期望的間隔設定計劃任務即可:*/30 * * * * export LANG=zh_CN.UTF-8;python3 /root/log_analyse_parall.py &> /tmp/log_analyse.py3
關於這樣一個對不確定格式的大量文字進行分析的指令碼來說,通用性和執行效率兩個因素非常重要。通用性上文中已大致說明瞭原理;效能方面,經筆者在一臺4核虛擬機器上進行測試結果如下:
作者:kaifly
連結:http://blog.csdn.net/kai404/article/details/53443693
————近期Python開班————
《馬哥教育Python全能開發實戰班》由馬哥教育導師聯合BAT、豆瓣等一線網際網路Python開發達人,根據目前企業需求的Python開發人才進行了深度定製,加入了大量一線網際網路公司:大眾點評、餓了麼、騰訊等生產環境真是專案,課程由淺入深,從Python基礎到Python高階,讓你融匯貫通Python基礎理論,手把手教學讓你具備Python自動化開發需要的前端介面開發、Web框架、大監控系統、CMDB系統、認證堡壘機、自動化流程平臺六大實戰能力,讓你從0開始蛻變成Hold住年薪20萬的Python自動化開發人才。
10期面授班:2018年03月05號(北京)
09期網路班:騰訊課堂隨到隨學(網路)
掃描二維碼領取學習資料
更多Python好文請點選【閱讀原文】哦
↓↓↓