轉自:Nginx服務狀態監控
在Nginx的插件模塊中有一個模塊stub_status可以監控Nginx的一些狀態信息,默認安裝可能沒有這個模塊,手動編譯的時候加一下即可。
Nginx 還有一個商業版 Nginx Plus,功能更加豐富,對應的監控頁面http://demo.nginx.com/status.html
1. 模塊安裝
先使用命令查看是否已經安裝這個模塊:
[root@ihxb123Z nginx]# ./nginx -V (V大寫會顯示版本號和模塊等信息、v小寫僅顯示版本信息。
或用此使用看:nginx -V 2>&1 | grep -o with-http_stub_status_module
如返回 with-http_stub_status_module,則說明該模塊已被開放,而什么都不返回的話就是沒有被開放。
如果已經安裝,會在顯示的信息中包含 --with-http_stub_status_module信息。如果沒有此模塊,需要重新安裝,編譯命令如下:
./configure –with-http_stub_status_module
2. Nginx配置
安裝后只要修改nginx配置即可,配置如下:
location /hxbcdnstatus { stub_status on; access_log off; allow 127.0.0.1; deny all; #auth_basic "NginxStatus"; #auth_basic_user_file conf/nginxstaus; }
此處默認只有本地訪問,如果遠程可以查看需要加相關的IP或者干脆去掉Deny all即可。加密文件可以使用#htpasswd -c /usr/nginx/conf hxb 命令來創建。配置完成后需要重啟Nginx服務。
狀態配置只能是針對某個Nginx服務。目前Nginx還無法做到針對單個站點進行監控。
3. 狀態查看
配置完成后在瀏覽器中輸入http://127.0.0.1/hxbcdnstatus查看(或者用$ curl localhost/
hxbcdnstatus),顯示信息如下:
Active connections: 100 server accepts handled requests 1075 1064 6253 Reading: 0 Writing: 5 Waiting: 95
Accepts(接受)、Handled(已處理)、Requests(請求數)是一直在增加的計數器。Active(活躍)、Waiting(等待)、Reading(讀)、Writing(寫)隨着請求量而增減。
名稱 | 描述 | 指標類型 |
---|---|---|
Accepts(接受) | NGINX 所接受的客戶端連接數 | 資源: 功能 |
Handled(已處理) | 成功的客戶端連接數 | 資源: 功能 |
Dropped(已丟棄,計算得出) | 丟棄的連接數(接受 - 已處理) | 工作:錯誤* |
Requests(請求數) | 客戶端請求數 | 工作:吞吐量 |
4. 參數說明
active connections – 活躍的連接數量
server accepts handled requests — 總共處理了1075個連接 , 成功創建1064次握手, 總共處理了6253個請求
每個連接有三種狀態waiting、reading、writing
reading —讀取客戶端的Header信息數.這個操作只是讀取頭部信息,讀取完后馬上進入writing狀態,因此時間很短。
writing — 響應數據到客戶端的Header信息數.這個操作不僅讀取頭部,還要等待服務響應,因此時間比較長。
waiting — 開啟keep-alive后等候下一次請求指令的駐留連接.
正常情況下waiting數量是比較多的,並不能說明性能差。反而如果reading+writing數量比較多說明服務並發有問題。
當用戶請求連接Nginx服務器時,accepts計數器會加一。且當服務器處理該連接請求時,handled計數器同樣會加一。一般而言,兩者的值是相等的,除非達到了某些資源極限(如worker_connection的限制)。
用戶連接請求被處理,就會進入 active 狀態。如果該連接沒有其他 request,則進入 waiting 的子狀態;如果有 request,nginx 會讀取 request 的 header,計數器 request 加一,進入 reading 的子狀態。 reading 狀態持續時間非常短,header 被讀取后就會進入 writing 狀態。事實上,直到服務器將響應結果返回給用戶之前,該連接會一直保持 writing 狀態。所以說,writing 狀態一般會被長時間占用。
一旦 NGINX 成功處理一個連接時,連接會移動到Active狀態,在這里對客戶端請求進行處理:
Active狀態
Waiting: 活躍的連接也可以處於 Waiting 子狀態,如果有在此刻沒有活躍請求的話。新連接可以繞過這個狀態並直接變為到 Reading 狀態,最常見的是在使用“accept filter(接受過濾器)” 和 “deferred accept(延遲接受)”時,在這種情況下,NGINX 不會接收 worker 進程的通知,直到它具有足夠的數據才開始響應。如果連接設置為 keep-alive ,那么它在發送響應后將處於等待狀態。
Reading: 當接收到請求時,連接離開 Waiting 狀態,並且該請求本身使 Reading 狀態計數增加。在這種狀態下 NGINX 會讀取客戶端請求首部。請求首部是比較小的,因此這通常是一個快速的操作。
Writing: 請求被讀取之后,其使 Writing 狀態計數增加,並保持在該狀態,直到響應返回給客戶端。這意味着,該請求在 Writing 狀態時, 一方面 NGINX 等待來自上游系統的結果(系統放在 NGINX “后面”),另外一方面,NGINX 也在同時響應。請求往往會在 Writing 狀態花費大量的時間。
通常,一個連接在同一時間只接受一個請求。在這種情況下,Active 連接的數目 == Waiting 的連接 + Reading 請求 + Writing 。
5、怎么利用這些參數
開源的 Nginx 提供的原始參數中,實時性的會比較有用,如 Active connections、Reading、Writing 以及 Waiting。這些數據能夠反映當前 Nginx 的負載情況,方便在服務器出現問題時及時發現問題。而另一些數據由於不是狀態量,Nginx 無法計算當前的量值而改做其統計數,如 accepts、handled 和 requests。
對於維護網站人員,accepts、handled 和 requests 的統計值用處是不大的,值得參考的是短時間內這三者數值的增量。這個短時間可以是一秒,如 accepts_per_second、handled_per_second 和 requests_per_second。一個簡單的做法就是每秒都去讀取這些參數,返回一個和上一秒的差值就行。當然,handled_per_second 替換成 dropped_per_second=accepts_per_second-handled_per_second 就更完美了。
通過這七個參數,就可以從連接到請求全方位的監控起 Nginx 的運行狀態。為了方便檢測,對每次獲取的參數保留下來,然后按時間展現出來。下圖展示了 Nginx 在運行時的參考數據。

補充:
查看Nginx並發進程數:ps -ef | grep nginx | wc -l
查看Web服務器TCP連接狀態:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
其中截取了兩個shell腳本。
/usr/local/zabbix/bin/nginx_status.sh
#!/bin/bash #check nginx status ip=127.0.0.1 function ping() { #用於檢測nginx進程是否存在 /sbin/pidof nginx | wc -l } function active() { #用於提取status中的active數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '1p' | awk '{print $NF}' } function accepts() { #用於提取status中的accepts數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $1}' } function handled() { #用於提取status中的handled數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $2}' } function requests() { #用於提取status中的request數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $3}' } function reading() { #用於提取status中的reading數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $2}' } function writing() { #用於提取status中的writing數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $4}' } function waiting() { #用於提取status中的waiting數值 /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $6}' } $1 #通過第一個位置參數的值來調用相應的函數
類似的
touch /home/nginx/ngx-status.sh vim /home/nginx/ngx-status.sh #!/bin/bash ###########################nginx_check########################### # V20170929 # #active|reading|writing|waiting|accepts|handled|requests|dropped# ###########################nginx_check########################### HOST="127.0.0.1" PORT="80" # 檢測nginx相關參數 case $1 in ping) result=`/bin/pidof nginx 2>/dev/null| wc -l` echo $result ;; active) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| grep 'Active' | awk '{print $NF}'` echo $result ;; reading) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| grep 'Reading' | awk '{print $2}'` echo $result ;; writing) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| grep 'Writing' | awk '{print $4}'` echo $result ;; waiting) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| grep 'Waiting' | awk '{print $6}'` echo $result ;; accepts) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| awk NR==3 | awk '{print $1}'` echo $result ;; handled) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| awk NR==3 | awk '{print $2}'` echo $result ;; requests) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| awk NR==3 | awk '{print $3}'` echo $result ;; dropped) result=`/usr/bin/curl "http://$HOST:$PORT/ngx_status/" 2>/dev/null| awk NR==3 | awk '{print $1-$2}'` echo $result ;; *) echo "Usage:$0(ping|active|reading|writing|waiting|accepts|handled|requests|dropped)" ;; esac
php-fpm status數值提取腳本為/usr/local/zabbix/bin/php_fpm_status.sh
#!/bin/bash #check php-fpm status case $1 in ping) #檢測php-fpm進程是否存在 /sbin/pidof php-fpm | wc -l ;; start_since) #提取status中的start since數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==4{print $3}' ;; conn) #提取status中的accepted conn數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==5{print $3}' ;; listen_queue) #提取status中的listen queue數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==6{print $3}' ;; max_listen_queue) #提取status中的max listen queue數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==7{print $4}' ;; listen_queue_len) #提取status中的listen queue len /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==8{print $4}' ;; idle_processes) #提取status中的idle processes數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==9{print $3}' ;; active_processes) #提取status中的active processes數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==10{print $3}' ;; total_processes) #提取status中的total processess數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==11{print $3}' ;; max_active_processes) #提取status中的max active processes數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==12{print $4}' ;; max_children_reached) #提取status中的max children reached數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==13{print $4}' ;; slow_requests) #提取status中的slow requests數值 /usr/bin/curl localhost/php_fpm-status 2>/dev/null | awk 'NR==14{print $3}' ;; *) echo "Usage: $0 {conn|listen_queue|max_listen_queue|listen_queue_len|idle_processes|active_processess|total_processes|max_active_processes|max_children_reached|slow_requests}" exit 1 ;; esac