如何挖掘Nginx日誌中隱藏的金礦?

2021-09-10 10:27:01 字數 3589 閱讀 6619

編輯|小智

對很多開發運維人員來說,nginx 日誌檔案在被刪除前可能都不會看上一眼。但實際上,nginx 隱藏了相當豐富的資訊,或許其中便蘊含著未知的金礦等你挖掘!

寫在前面

nginx(讀作 engine-x)是現在最流行的負載均衡和反向**伺服器之一。如果你是一名中小微型**的開發運維人員,很可能像我們一樣,僅 nginx 每天就會產生上百 m 甚至數以十 g 的日誌檔案。如果沒有出什麼錯誤,在被 logrotate 定期分割並滾動刪除以前,這些日誌檔案可能都不會被看上一眼。

實際上,nginx 日誌檔案可以記錄的資訊相當豐富,而且格式可以定製,考慮到$time_local請求時間字段幾乎必有,這是乙個典型的基於檔案的時間序列資料庫。nginx 日誌被刪除以前,或許我們可以想想,其中是否蘊含著未知的金礦等待挖掘?

請求訪問分析

nginx 中的每條記錄是乙個單獨的請求,可能是某個頁面或靜態資源的訪問,也可能是某個 api 的呼叫。通過幾條簡單的命令,了解一下系統的訪問壓力:

備註:本文使用 awk 命令處理,與 nginx 日誌的格式有關,如果您格式不同,請酌情修改命令。本文所用的 nginx 日誌格式:

nginx 日誌如果開啟,除了請求時間,一般會包含響應時間、頁面尺寸等字段,據此很容易計算出網路流量、速率。

等等,你可能會有疑問,上面的請求訪問分析,這裡的流量速率分析,按時間軸畫出來,不就是監控系統幹的事兒嗎,何苦這麼麻煩查詢 nginx 日誌?

的確如此,監控系統提供了更實時、更直觀的方式。而 nginx 日誌檔案的原始資料,可以從不同維度分析,使用得當,會如大浪淘沙般,發現屬於我們的金子。

備註:nginx 配置檔案中日誌格式使用了 $body_sent_size,指 http 響應體的大小,如果想檢視整個響應的大小,應該使用變數 $sent_size。

借助 sed 命令,通過三個方法對 url 格式進行歸一化處理:去掉所有的引數;去掉.html.json字尾;把數字替換為*。可以得到更準確的統計結果,:

備註:這裡使用了擴充套件正規表示式,gnu sed 的引數為 -r,bsd sed 的引數為 -e。

那些累計占用了更多響應時間的請求,通常也耗用了更多的 cpu 時間,是效能優化重點照顧的物件。

慢查詢分析

「服務號剛推送了文章,有使用者反映點開很慢」,你剛端起桌子上的水杯,就聽到產品經理的大嗓門從辦公室角落呼嘯而來。「使用者用的什麼網路」,你一邊問著,一邊開啟服務號親自嘗試一下。是使用者網路環境不好,還是後台系統有了訪問壓力?是這乙個使用者慢,還是很多使用者都慢?你一邊腦子裡在翻騰,一邊又開啟命令列去檢視日誌。

考慮一下 mysql 資料庫,可以開啟慢查詢功能,定期查詢並優化慢查詢,與此類似,nginx 日誌中的響應時間,不相當於自帶慢查詢功能嘛。利用這一特性,我們分步進行慢查詢分析:

第一步:是不是使用者的網路狀況不好?根據既往的經驗,如果只有少量的請求較慢,而前後其他 ip 的請求都較快,通常是使用者手機或網路狀況不佳引起的。最簡單的方法,統計慢查詢所佔比例:

第二步:是不是應用系統的瓶頸?對比應用伺服器的返回時間 ($upstream_response_time 字段),與 nginx 伺服器的處理時間 ($request_time 字段),先快速排查是否某一台伺服器抽風。

我們遇到過類似問題,平均響應時間 90ms,還算正常,但某台伺服器明顯變慢,平均響應時間達到了 200ms,影響了部分使用者的訪問體驗。

第三步:應用系統沒有瓶頸,是頻寬的問題?快速檢視一下每秒的流量:

還能做哪些優化?

seo 團隊抱怨優化了那麼久,為什麼頁面索引量和排名上不去。列印出不同爬蟲的請求頻次($http_user_agent),或者檢視某個特定的頁面,最近有沒有被爬蟲爬過:

三、周四的轉換率比週末高不少,可能跟平台的發貨週期有關,客戶週三四下單,希望週末就能收到貨,開始快樂的週末。你猜測到使用者的心理和期望,連資料一起交市場品團隊,期待更好地改善。

這樣的例子可以有很多。事實上,上述分析限於 nginx 日誌,如果有系統日誌,並且日誌格式定義良好,可以做的事情遠不止於此:這是乙個時間序列資料庫,可以查詢 it 系統的運**況,可以分析營銷活動的效果,也可以**業務資料的趨勢;這是乙個比較小但夠用的大資料來源,運用你學會的大資料分析方法,也可以像滴滴那樣,分並**不同天氣、時間段下不同地區的車輛供需,並作出優化。

幾點建議

規範日誌格式。這是很多團隊容易忽略的地方,有時候多乙個空格會讓日誌分析的複雜度大為增加。

無論如何,使用時間戳字段。以時間序列的方式看待日誌檔案,這也是很多公司把系統日誌直接寫入到時間序列資料庫的原因;

如有可能,記錄以下字段:使用者(或者客戶端)標識、單次請求標識、應用標識(如果單次請求會走到多個應用)。能夠方便地查出使用者鏈路、請求鏈路,是排查錯誤請求、分析使用者行為的基礎;

關注寫的操作。就像業務建模時,需要特別關注具有時標性、狀態會發生改變的模型一樣,任何寫的操作,都應記錄到日誌系統中。萬一某個業務出錯,不但可以通過業務模型復演,也可以通過日誌系統復演。

規範 url 格式。這一點同樣容易遭到忽略,商品詳情頁面要不要新增"?from=***"**引數?支付頁面採用路徑標記「payment/alipay」,還是引數標記「/payment?type=alipay」更合適?區別細微但影響不可忽略。

技術團隊應該像對待協議一樣對待這些規範。仔細定義並嚴格遵守,相當於拿到了金礦的鑰匙。

還需要尋找乙個合適的日誌分析工具,基於 python、go、lua,都有免費的日誌分析工具可供使用;想更輕量,準備幾條常用的 shell 指令碼,比如作者整理了一些到 github 的這個專案上(或者基於 elk 技術棧,把 nginx 訪問日誌、業務日誌統一儲存,並通過 kibana 進行不同維度的聚合分析,都是不錯的辦法。

或許你早就使用 nginx 日誌了,你是怎麼使用的,有什麼好的方法呢,歡迎一起交流。

今日薦文

004 Nginx日誌挖掘accessLog

remote addr 192.168.56.1 對應客戶端ip位址 remote user 對應遠端使用者,沒有遠端使用者,所以用 充填 time local 23 dec 2020 23 13 04 0800 訪問時間 request status 403 訪問的狀態碼 body bytes s...

如何調整Docker中nginx的日誌級別詳解

目錄 最近發現我們的乙個應用產生了很多日誌,而這些日誌大多都是 nginx 的 access log,我們缺省會把標準輸出收集到 es 裡分析應用日誌,但是很多都是 access log 就可能會掩蓋掉真實的錯誤日誌,所以可能有時候我們並不想輸出這些 access log,示例如下 去 github...

nginx 如何配置日誌及切割日誌

remote addr remote user time local request ip位址 請求方式 status body bytes sent 狀態 請求多少位元組 http referer 從哪個頁面進來的 http user agent 使用者 http x forwarded for ...