摘要:眾所周知,Nginx是目前最流行的Web Server之一,也廣泛應用於負載均衡、反向代理等服務,但使用過程中可能因為對Nginx工作原理、變量含義理解錯誤,或是參數配置不當導致Nginx工作異常。本文介紹的就是開機廣告Nginx的參數location處理靜態文件配置不當引發的nginx日志驟增到14G的問題排期過程。
一、問題現象及系統介紹
現象:12月15日 21:02分,正在外面吃宵夜,手機收到監控平台的一條“服務器磁盤空間<20%”報警短信。
系統介紹:為了看此文的童鞋更好理解我下面介紹的東西,這里我先簡單介紹下福建開機廣告系統。
整個系統可以分為管理平台與API兩個部分:
管理平台完成素材(包括下面提到素材圖片名也是有放到緩存里的)、廣告、策略、排期制作和下發等工作,提供接口將廣告策略、用戶分組等信息同步到API;
API向機頂盒/EPG提供廣告接口,采集廣告請求日志,當STB訪問EPG,EPG調用廣告請求接口獲取廣告策略(地區、分組、平台、黑白名單等策略),並在匹配到策略的時候進行展示;
API節點我們是放在其中6台服務器的23個tomcat里面,使用nginx實現負載請求分發;圖片服務器我們是放在另外的3台服務器,也是使用的nginx實現的負載請求分發。相信大家對nginx都不陌生,這里我就不在贅述。
二、問題排查過程
2.1 初步分析
判斷一:可能是crontab未執行
一看是Nginx所在服務器,初步判斷可能是crontab異常,沒有定期清除5天以前的日志導致(這里說明下:我們線上的nginx日志是每天凌晨切割access.log日志,然后通過crontab實現只保留最近五天日志)。
2.2 深入分析
判斷二:可能圖片同步出問題
回到家,打開SHH客戶端 查看/data/nginx_log目錄查看,發現access.log只有近五天的日志,「排除原以為是crontab異情況」。
然后發現error_log很大,命令du -h error_log一看都有14G了,tail -200 error_log發現全是“/usr/local/nginx/html/resources/material/img/1511488532192.JPG”圖片請求失敗的記錄,於是趕緊清空error_log,排除短信空間報警。
心想,難道是圖片沒有同步?
為驗證我的猜想,我打開瀏覽器訪問這張圖片:http://IP:port/resources/material/img/1511488532192.JPG(上面IP指的是nginx所在服務器IP,port是nginx.conf配置圖片分發端口),請求幾次返回都是404。
於是切換到主圖片服務器查看,發現這張大寫圖片存在,切換到其他兩台從圖片服務器,發現也是存在的(這里說明下:我們系統的素材圖片都是通過管理平台以接口的形式下發主圖片服務器,主圖片服務器再通過inotify+sync同步到其他兩台從圖片服務器),「排除圖片同步異常情況」。
判斷三:可能是請求不到大寫后綴圖片導致
因為看到圖片服務器目錄下,唯有這幾張大寫后綴圖片是請求異常的,那改成小寫會怎么樣呢?接着改了下三台圖片服務器的圖片大寫后綴為小寫后綴。再打開瀏覽器請求,發現請求正常了,繼而判斷可能運營人員在管理平台制作廣告的時候上傳了大寫后綴的格式的圖片,同步到API和數據庫的緩存,那么導致有廣告請求的從緩存查詢到的圖片地址也就是大寫的了。
順着這個思路,我先到登錄到數據庫改了下素材表圖片大寫后綴為小寫后綴,再登錄redis,准備改緩存,info命令一看,傻眼了,136萬的key數量,而我又不記得具體廣告策略key,
由於沒辦法查找,那就只能flushall清空緩存,重啟ad-cache工程(這里說明下:ad-cache工程的作用主要就是兩個,一是把當前符合要求的用戶、廣告策略等相關信息初始加載到緩存,另一個是啟一個定時任務,每小時加載當前時段的策略到緩存),然后在查看tail -f error_log查看日志,發現還在增加之前那種大寫后綴圖片請求失敗的錯誤,「排除圖片后綴大寫情況」。
判斷四:可能是nginx配置不當導致
這么操作完還是不行,當時着實有點懵逼,我心想當時已經把廣告請求所有涉及到會查詢圖片大寫后綴的地方改過來了,為什么還是會有大寫后綴圖片請求失敗的記錄?但轉念一想會不是nginx的配置有問題?
為驗證我的判斷,我先sz命令從圖片服務器上下載了一張名為“1511488578911.JPG”的大寫后綴格式的圖片,然后通過管理平台上傳這個“1511488578911.JPG”圖片素材,發現這張圖片是可以預覽的。由此更加確信就是nginx某些參數配置不當導致。vim命令查看配置nginx.conf,當定位到圖片請求配置這里的時候,
發現location ~是表示區分大小寫的,而后面全是配置小寫后綴格式,於是加上JPG,使用/usr/local/nginx/sbin/nginx -s reload命令重載nginx的配置,打開瀏覽器發現可以查看到這張圖片了,再切換到nginx日志目錄,tail -f error_log,發現日志沒有再增加,至此問題終於解決。
三、問題反思
反思一:要做到知其然並且知其所以然
對Nginx工作原理、參數含義理解不深,從而參數配置不當,導致產生nginx日志驟增這種問題產生。
反思二:缺少一個快速定位問題的系統或工具,導致排查的時間比較長。
當時在作出判斷三的時候,因為沒在公司,不記得廣告策略緩存key,導致不得不直接執行flushall命令直接清空緩存,再重新刷入緩存,這樣做其實是有風險的,因為把廣告策略、用戶、分組等信息從緩存清空之后,用戶的廣告請求只能直接去查詢數據庫,這樣響應的時間肯定會慢了,而且緩存中還存了廣告請求的日志記錄,直接flushall就會丟失部分的廣告請求數據,影響到PV、UV統計。所以當時也是想就是有一個系統,在瀏覽器直接輸入一個用戶名或是圖片名,就能從數據庫和緩存查詢到中涉及到相關聯的數據,以可視化的形式在頁面展示,這樣定位問題也就可以更快定位問題了。於是也就是后期跟老大確認做一個問題定位輔助系統,這樣方便定位問題
四、引申
語法規則: location [=|~|~*|^~] /uri/ { … }
= 開頭表示精確匹配
^~ 開頭表示uri以某個常規字符串開頭,理解為匹配 url路徑即可。nginx不對url做編碼,因此請求為/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意是空格)。
~ 開頭表示區分大小寫的正則匹配
~* 開頭表示不區分大小寫的正則匹配
!~和!~*分別為區分大小寫不匹配及不區分大小寫不匹配 的正則
/ 通用匹配,任何請求都會匹配到。
多個location配置的情況下匹配順序為(參考資料而來,還未實際驗證,試試就知道了,不必拘泥,僅供參考):
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最后是交給 / 通用匹配。當有匹配成功時候,停止匹配,按當前匹配規則處理請求。
例子,有如下匹配規則:
[plain] view plain copy
location = / {
#規則A
}
location = /login {
#規則B
}
location ^~ /static/ {
#規則C
}
location ~ \.(gif|jpg|png|js|css)$ {
#規則D
}
location ~* \.png$ {
#規則E
}
location !~ \.xhtml$ {
#規則F
}
location !~* \.xhtml$ {
#規則G
}
location / {
#規則H
}
那么產生的效果如下:
訪問根目錄/, 比如http://localhost/ 將匹配規則A
訪問 http://localhost/login 將匹配規則B,http://localhost/register 則匹配規則H
訪問 http://localhost/static/a.html 將匹配規則C
訪問 http://localhost/a.gif, http://localhost/b.jpg 將匹配規則D和規則E,但是規則D順序優先,規則E不起作用,而 http://localhost/static/c.png 則優先匹配到 規則C
訪問 http://localhost/a.PNG 則匹配規則E, 而不會匹配規則D,因為規則E不區分大小寫。
訪問 http://localhost/a.xhtml 不會匹配規則F和規則G,http://localhost/a.XHTML不會匹配規則G,因為不區分大小寫。規則F,規則G屬於排除法,符合匹配規則但是不會匹配到,所以想想看實際應用中哪里會用到。
訪問 http://localhost/category/id/1111 則最終匹配到規則H,因為以上規則都不匹配,這個時候應該是nginx轉發請求給后端應用服務器,比如FastCGI(php),tomcat(jsp),nginx作為方向代理服務器存在。
學習本就是一個不斷模仿、練習、再到最后面自己原創的過程。
雖然可能從來不能寫出超越網上通類型同主題博文,但為什么還是要寫?
於自己而言,博文主要是自己總結。假設自己有觀眾,畢竟講是最好的學(見下圖)。於讀者而言,筆者能在這個過程get到知識點,那就是雙贏了。
當然由於筆者能力有限,或許文中存在描述不正確,歡迎指正、補充!
感謝您的閱讀。如果本文對您有用,那么請點贊鼓勵。