本文探討了電商場(chǎng)景下 Nginx 的監(jiān)控方案,并將使用過程中遇到的問題和解決方案與大家一起分享。 Nginx 特性 作為 Web 服務(wù)器,Nginx 不免要與 Apache 進(jìn)行比較。 相比 Apache 服務(wù)器,Nginx 因其采用的異步非阻塞工作模型,使其具備高并發(fā)、低資源消耗的特性,高度模塊化設(shè)計(jì)使 Nginx 具備很好的擴(kuò)展性;在處理靜態(tài)文件、反向代理請(qǐng)求等方面,Nginx 表現(xiàn)出很大的優(yōu)勢(shì)。 Nginx 常見的使用方式 Nginx 可以作為反向代理服務(wù)器來轉(zhuǎn)發(fā)用戶請(qǐng)求;并能夠在處理請(qǐng)求的過程中實(shí)現(xiàn)后端實(shí)例負(fù)載均衡,實(shí)現(xiàn)分發(fā)請(qǐng)求的功能;也可將 Nginx 配置為本地靜態(tài)服務(wù)器,處理靜態(tài)請(qǐng)求。 Nginx 監(jiān)控 監(jiān)控指標(biāo)梳理 Nginx 處理請(qǐng)求的全過程應(yīng)被監(jiān)控起來,以便我們及時(shí)發(fā)現(xiàn)服務(wù)是否能夠正常運(yùn)轉(zhuǎn)。 Nginx 處理請(qǐng)求的過程被詳細(xì)地記錄在 access.log 以及 error.log 文件中,我們給出以下(表 1)需要監(jiān)控的關(guān)鍵指標(biāo): 表1:關(guān)鍵指標(biāo) 監(jiān)控實(shí)踐 下面從延遲、錯(cuò)誤、流量以及飽和度四個(gè)指標(biāo)對(duì) Nginx 監(jiān)控實(shí)踐進(jìn)行說明。 延遲監(jiān)控 延遲監(jiān)控主要關(guān)注對(duì) $request_time 的監(jiān)控,并繪制 TP 指標(biāo)圖,來確認(rèn) TP99 指標(biāo)值。 另外,我們還可以增加對(duì) $upstream_response_time 指標(biāo)的監(jiān)控,來輔助定位延遲問題的原因。 圖 1:TP 指標(biāo) 圖 1 展示了過去 15min 內(nèi) Nginx 處理用戶請(qǐng)求的時(shí)間,可以看出用戶 90% 的請(qǐng)求可以在 0.1s 內(nèi)處理完成,99% 的請(qǐng)求可以在 0.3s 內(nèi)完成。 根據(jù) TP 指標(biāo)值,并結(jié)合具體業(yè)務(wù)對(duì)延遲的容忍度,來設(shè)置延遲的報(bào)警閾值。 錯(cuò)誤監(jiān)控 Nginx 作為 Web 服務(wù)器,不但要對(duì) Nginx 本身運(yùn)行狀態(tài)進(jìn)行監(jiān)控,還必須對(duì) Nginx 的各類錯(cuò)誤響應(yīng)進(jìn)行監(jiān)控,HTTP 錯(cuò)誤狀態(tài)碼以及 error.log 中記錄的錯(cuò)誤詳細(xì)日志都應(yīng)被監(jiān)控起來以協(xié)助解決問題。 ①基于 HTTP 語義的 Nginx 端口監(jiān)控 單純的 Nginx 端口監(jiān)控?zé)o法反映服務(wù)真實(shí)運(yùn)行狀態(tài),我們要關(guān)注的是 Nginx 本身存活以及是否可以正常提供服務(wù)。 基于我們的實(shí)踐,我們推薦用語義監(jiān)控代替端口監(jiān)控,即從 Nginx 本機(jī)以 http://local_ip:port/ 的方式進(jìn)行訪問,校驗(yàn)返回的數(shù)據(jù)格式、內(nèi)容及 HTTP 狀態(tài)碼是否符合預(yù)期。 ②錯(cuò)誤碼監(jiān)控 必須添加對(duì)諸如 500/502/504 等 5xx 服務(wù)類錯(cuò)誤狀態(tài)碼的監(jiān)控,它們告訴我們服務(wù)本身出現(xiàn)了問題。 圖 2:狀態(tài)碼監(jiān)控 5xx 類錯(cuò)誤每分鐘出現(xiàn)的頻率應(yīng)該在個(gè)位數(shù),太多的 5xx 應(yīng)及時(shí)排查問題并解決;4xx 類錯(cuò)誤,在協(xié)助解決一些非預(yù)期的權(quán)限錯(cuò)誤、資源丟失或性能等問題上可以給予幫助。 可以選擇性得對(duì) 301/302 重定向類監(jiān)控,應(yīng)對(duì)特殊配置跳轉(zhuǎn)的監(jiān)控,如后端服務(wù)器返回 5xx 后,Nginx 配置重定向跳轉(zhuǎn)并返回跳轉(zhuǎn)后的請(qǐng)求結(jié)果。 ③對(duì)錯(cuò)誤日志監(jiān)控 Nginx 內(nèi)部實(shí)現(xiàn)了對(duì)請(qǐng)求處理錯(cuò)誤的詳細(xì)記錄,并保存在 error.log 文件中。 錯(cuò)誤類型有很多種,我們主要針對(duì)關(guān)鍵的、能體現(xiàn)服務(wù)端異常的錯(cuò)誤進(jìn)行采集并監(jiān)控,以協(xié)助我們進(jìn)行故障定位: 表 2:錯(cuò)誤日志信息 流量監(jiān)控 ①Nginx 所接受請(qǐng)求總量的監(jiān)控 關(guān)注流量波動(dòng)周期,并捕獲流量突增、突降的情況;通常穩(wěn)態(tài)下流量低峰和高峰浮動(dòng) 20% 需要關(guān)注下原因。 對(duì)于有明顯波動(dòng)周期的服務(wù),我們也可以采用同環(huán)比增漲/降低的告警策略,來及時(shí)發(fā)現(xiàn)流量的變化。 圖 3:PV 流量圖 圖 4:關(guān)鍵流量圖 圖 3 為京東云某平臺(tái)一周內(nèi)的流量波動(dòng)圖,流量存在明顯低峰和高峰并有天級(jí)別的周期性。 基于網(wǎng)站運(yùn)行特性,根據(jù)低峰、高峰的值來監(jiān)控網(wǎng)站流量的波動(dòng),并通過自身的監(jiān)控儀表盤配置網(wǎng)站關(guān)鍵頁(yè)面的流量圖(圖 4),以協(xié)助故障排查。 圖 5:網(wǎng)卡流量圖 ②對(duì)網(wǎng)卡 IO 等機(jī)器級(jí)別流量進(jìn)行監(jiān)控 可以及時(shí)發(fā)現(xiàn)服務(wù)器硬件負(fù)載的壓力,當(dāng) Nginx 被用于搭建文件服務(wù)器時(shí),此監(jiān)控指標(biāo)需要我們尤為關(guān)注。 飽和度監(jiān)控 Google SRE 中提到,飽和度應(yīng)關(guān)注服務(wù)對(duì)資源的利用率以及服務(wù)在當(dāng)前運(yùn)行情況下還可以承受多少負(fù)載。 Nginx 是低資源消耗的高性能服務(wù)器,但諸如在電商場(chǎng)景下,新產(chǎn)品搶購(gòu)會(huì)在短時(shí)間內(nèi)造成 CPU 利用率、請(qǐng)求連接數(shù)、磁盤寫入的飆升。 CPU 利用率還要考慮通過 worker_cpu_affinity 綁定 Worker 進(jìn)程到特定 CPU 核心的使用情況,處理高流量時(shí),該配置可以減少 CPU 切換的性能損耗。 Nginx 可以接受的最大連接數(shù)在配置文件 nginx.conf 中由 worker_processes 和 worker_connections 兩個(gè)參數(shù)的乘積決定。 圖 6 通過 Nginx 自帶的模塊 http_stub_status_module 可以對(duì) Nginx 的實(shí)時(shí)運(yùn)行信息(圖 6)進(jìn)行監(jiān)控。 因我們更關(guān)心當(dāng)前 Nginx 運(yùn)行情況,不對(duì)已處理的請(qǐng)求做過多關(guān)注,所以我們只對(duì)如下指標(biāo)進(jìn)行采集監(jiān)控: 表 3:指標(biāo)含義 基于開源軟件搭建 Nginx 可視化監(jiān)控系統(tǒng) ①采用 Elasticsearch Logstash Kibana 搭建可視化日志監(jiān)控 圖 7:ELK 棧架構(gòu)圖 針對(duì)以上四個(gè)監(jiān)控黃金指標(biāo),搭建的 ELK 棧儀表盤,設(shè)置常用的 Nginx 日志過濾規(guī)則(圖 8),以便可以快速定位分析問題。 圖 8:ELK 儀表盤 ②采用 Kibana Elasticsearch Rsyslog Grafana 搭建可視化日志監(jiān)控 圖 9:Grafana 可視化架構(gòu)圖 相較于 Kibana 能快速地對(duì)日志進(jìn)行檢索,Grafana 則在數(shù)據(jù)展示方面體現(xiàn)了更多的靈活性,某些情況下二者可以形成互補(bǔ)。 圖 10:Grafana 儀表盤 我們?cè)趯?shí)踐中實(shí)現(xiàn)上述兩種架構(gòu)的 Nginx 日志可視化監(jiān)控;從需求本身來講,ELK 棧模型可以提供實(shí)時(shí)的日志檢索,各種日志規(guī)則的過濾和數(shù)據(jù)展示,基本可以滿足 Nginx 日志監(jiān)控的需求。 Grafana 架構(gòu)模型無法進(jìn)行日志檢索和瀏覽,但提供了角色權(quán)限的功能,來防護(hù)一些敏感數(shù)據(jù)的訪問。 另外,Grafana 更為豐富的圖表類型和數(shù)據(jù)源支持,使其具有更多的應(yīng)用場(chǎng)景。 基于 Nginx 監(jiān)控發(fā)現(xiàn)并定位問題案例 案例 1:大流量沖擊 問題:某平臺(tái),進(jìn)行了一次新產(chǎn)品的搶購(gòu)活動(dòng)?;顒?dòng)期間因流量飆升導(dǎo)致商品詳情頁(yè)、下單等核心功能處理耗時(shí)增加的情況。 圖 11:PV 飆升圖 解決:訂單監(jiān)控及 Nginx 的 PV、請(qǐng)求時(shí)間等監(jiān)控指標(biāo)發(fā)出報(bào)警后,運(yùn)維人員迅速通過自建的 ELK 監(jiān)控儀表盤,關(guān)注網(wǎng)站流量變化,查看用戶請(qǐng)求 top IP、top URL;發(fā)現(xiàn)存在大量黃牛的惡意搶購(gòu)行為,導(dǎo)致服務(wù)后端處理延時(shí)。 因此,我們通過降低高防產(chǎn)品、Nginx 限流配置中相關(guān)接口防攻擊閾值,及時(shí)攔截了對(duì)系統(tǒng)負(fù)載造成壓力的刷單行為,保障了新品促銷活動(dòng)順利開展。 案例 2:Nginx 錯(cuò)誤狀態(tài)碼警示服務(wù)異常 問題:某平臺(tái)進(jìn)行后端服務(wù)器調(diào)整,某個(gè) Nginx 的 upstream 指向的后端服務(wù)器配置錯(cuò)誤,指向了一個(gè)非預(yù)期的后端服務(wù)。 當(dāng)錯(cuò)誤的配置被發(fā)布到線上后,網(wǎng)站開始出現(xiàn)概率性的異常,并伴有 500 和 302 錯(cuò)誤狀態(tài)碼數(shù)量的飆升。 圖 12:302 錯(cuò)誤碼統(tǒng)計(jì) 解決:Nginx 錯(cuò)誤狀態(tài)碼告警后,通過 ELK 平臺(tái)過濾 302 錯(cuò)誤碼下用戶請(qǐng)求的 URL,發(fā)現(xiàn)請(qǐng)求錯(cuò)誤的 URL 均與后端的某個(gè)模塊相關(guān),該請(qǐng)求都被重定向到了網(wǎng)站首頁(yè)。 進(jìn)一步定位發(fā)現(xiàn),某臺(tái) Nginx 指向了錯(cuò)誤的后端服務(wù)器,導(dǎo)致服務(wù)器返回大量 500 錯(cuò)誤,但因 Nginx 配置中對(duì) 500 錯(cuò)誤做了重定向,并因此產(chǎn)生了很多 302 狀態(tài)碼。 圖 13:配置 upstream 健康監(jiān)測(cè) 在后續(xù)改進(jìn)中,我們通過升級(jí) Nginx,采用 openresty lua 方式來對(duì)后端服務(wù)器進(jìn)行健康監(jiān)測(cè)(圖 13),以動(dòng)態(tài)更新 upstream 中的 server,可以快速摘除異常的后端服務(wù)器,達(dá)到快速止損的目的。 案例 3:Nginx 服務(wù)器磁盤空間耗盡導(dǎo)致服務(wù)異常 問題:Nginx 作為圖片服務(wù)器前端,某天其中一實(shí)例在生產(chǎn)環(huán)境無任何變更的情況下收到報(bào)警提示:500 狀態(tài)碼在整體流量中占比過高。 解決:快速將此機(jī)器從生產(chǎn)環(huán)境中摘除,不再提供服務(wù),經(jīng)排查 Nginx 錯(cuò)誤日志發(fā)現(xiàn)如下報(bào)錯(cuò): open() '/home/work/upload/client_body_temp/0000030704' failed (28: No space left on device)
Nginx 處理請(qǐng)求時(shí),會(huì)將客戶端 POST 長(zhǎng)度超過 client_body_buffer_size 請(qǐng)求的部分或者全部?jī)?nèi)容暫存到 client_body_temp_path 目錄,當(dāng)磁盤空間被占滿時(shí),產(chǎn)生了以上的報(bào)錯(cuò)。 最終,我們確認(rèn)了本次異常是產(chǎn)品升級(jí)后支持上傳的圖片大小由 15MB 改為 50MB,并且運(yùn)營(yíng)方進(jìn)行了新產(chǎn)品推廣活動(dòng),用戶上傳圖片量激增快速打滿磁盤空間所致。 |
|