ngx_http_stub_status監(jiān)控連接信息
nginx現(xiàn)已成為目前使用最廣泛的web服務(wù)器和反向代理服務(wù)器,我們線上的Tomcat服務(wù)器一般都會由nginx進行代理,以此實現(xiàn)負載均衡的效果。既然nginx被應(yīng)用得那么廣泛,我們自然也得學習如何去對nginx做性能監(jiān)控。本小節(jié)將介紹如何使用nginx的ngx_http_stub_status模塊來對連接信息進行監(jiān)控。本文默認讀者有nginx的基礎(chǔ),所以一些基礎(chǔ)性的東西不會過多介紹。
關(guān)于該模塊的官方文檔地址如下:
http://nginx.org/en/docs/http/ngx_http_stub_status_module.html
如果你的nginx是使用yum進行安裝的,那么一般會自帶這個模塊,可以忽略以下這段為了安裝ngx_http_stub_status模塊而重新編譯安裝nginx的部分。因為我的nginx是編譯安裝的,當時并沒有加上這個模塊進行編譯,所以現(xiàn)在還需要重新去編譯安裝一次。過程如下:
[root@01server ~]# /usr/local/nginx/sbin/nginx -V # 列出安裝了哪些模塊,可以看到我這里沒有安裝任何模塊 nginx version: nginx/1.12.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) configure arguments: --prefix=/usr/local/nginx [root@01server ~]# rm -rf /usr/local/nginx/ # 刪除原本的nginx [root@01server ~]# cd /usr/local/src/ # 進入存放安裝包的路徑 [root@01server /usr/local/src]# ls nginx-1.12.1 nginx-1.12.1.tar.gz [root@01server /usr/local/src]# cd nginx-1.12.1 # 進入之前已經(jīng)解壓好的目錄 [root@01server /usr/local/src/nginx-1.12.1]# ./configure --prefix=/usr/local/nginx --with-http_stub_status_module # 加入編譯參數(shù),指定需要安裝的模塊 [root@01server /usr/local/src/nginx-1.12.1]# make && make install # 編譯安裝 [root@01server /usr/local/src/nginx-1.12.1]# cd /usr/local/nginx/sbin/ [root@01server /usr/local/nginx/sbin]# ./nginx -V # 可以已經(jīng)把模塊安裝好了 nginx version: nginx/1.12.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module [root@01server /usr/local/nginx/sbin]#
安裝好之后,還需要編輯一下配置文件,不使用nginx默認的配置文件:
[root@01server /usr/local/nginx/sbin]# cd ../conf/ [root@01server /usr/local/nginx/conf]# mv nginx.conf nginx.conf.bak # 不使用nginx自帶的配置文件 [root@01server /usr/local/nginx/conf]# vim nginx.conf # 將以下內(nèi)容粘貼進去 user nobody nobody; worker_processes 2; error_log /usr/local/nginx/logs/nginx_error.log crit; pid /usr/local/nginx/logs/nginx.pid; worker_rlimit_nofile 51200; events { use epoll; worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 3526; server_names_hash_max_size 4096; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /usr/local/nginx/logs/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 30; client_header_timeout 3m; client_body_timeout 3m; send_timeout 3m; connection_pool_size 256; client_header_buffer_size 1k; large_client_header_buffers 8 4k; request_pool_size 4k; output_buffers 4 32k; postpone_output 1460; client_max_body_size 10m; client_body_buffer_size 256k; client_body_temp_path /usr/local/nginx/client_body_temp; proxy_temp_path /usr/local/nginx/proxy_temp; fastcgi_temp_path /usr/local/nginx/fastcgi_temp; fastcgi_intercept_errors on; tcp_nodelay on; gzip on; gzip_min_length 1k; gzip_buffers 4 8k; gzip_comp_level 5; gzip_http_version 1.1; gzip_types text/plain application/x-Javascript text/css text/htm application/xml; include vhost/*.conf; } [root@01server /usr/local/nginx/conf]# mkdir vhost [root@01server /usr/local/nginx/conf]# vim vhost/default.conf # 虛擬主機配置文件,將以下內(nèi)容粘貼進去 server{ listen 80; server_name localhost; index index.html index.htm index.php; root /usr/local/nginx/html; location = /nginx_status{ # 配置訪問路徑,即uri stub_status on; # 開啟該模塊 access_log off; # 關(guān)閉日志 allow 101.106.102.129; # 允許訪問的ip,即白名單ip allow 127.0.0.1; deny all; # 拒絕白名單ip以外的ip訪問 } } [root@01server ~]#
啟動nginx:
[root@01server /usr/local/nginx/conf]# cd ../sbin/ [root@01server /usr/local/nginx/sbin]# ./nginx -t # 檢查nginx的配置文件是否正常 nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@01server /usr/local/nginx/sbin]# ./nginx -c /usr/local/nginx/conf/nginx.conf # 啟動nginx [root@01server /usr/local/nginx/sbin]# netstat -lntp |grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 22713/nginx: master [root@01server /usr/local/nginx/sbin]#
啟動成功后,使用瀏覽器訪問/nginx_status,訪問成功響應(yīng)的信息如下:
說明:
- Active connections 當前活動的連接數(shù)量(包括等待的)
- accepts 已接收的連接總數(shù)
- handled 已處理的連接總數(shù)
- requests 當前的請求總數(shù)
- Reading nginx正在讀取的連接數(shù)量
- Writing nginx正在響應(yīng)的連接數(shù)量
- Waiting 當前空閑的連接數(shù)量
如上,通過這些簡單的參數(shù)可以看到nginx當前的連接信息。在高并發(fā)場景下,可以根據(jù)Active connections參數(shù)判斷當前的一個并發(fā)數(shù)量,Reading 參數(shù)則可以告訴我們當前nginx是否繁忙。當然,這只是最簡單的一個nginx的監(jiān)控方式,參數(shù)也就只有那么幾個。但這些都是其他更高級的監(jiān)控工具的基礎(chǔ),所以了解這些基礎(chǔ)監(jiān)控也是有必要的。
ngxtop監(jiān)控請求信息
在上一小節(jié)中,我們介紹了如何利用 ngx_http_stub_status 模塊去監(jiān)控nginx的連接信息。本小節(jié)將介紹如何使用ngxtop工具來監(jiān)控nginx的請求信息。
ngxtop可以實時解析nginx訪問日志,并且將處理結(jié)果輸出到終端,功能類似于系統(tǒng)命令top,所以這個軟件起名ngxtop。有了ngxtop,你可以實時了解到當前nginx的訪問狀況,再也不需要tail日志看屏幕刷新。
ngxtop項目地址:
https://github.com/lebinh/ngxtop
安裝ngxtop:
由于ngxtop是Python編寫的,我們可以使用pip進行安裝。如果你的機器上沒有安裝pip,需要先把pip裝上,安裝命令如下:
[root@01server ~]# yum install -y epel-release [root@01server ~]# yum install -y python-pip
然后通過pip安裝ngxtop,命令如下:
[root@01server ~]# pip install ngxtop
ngxtop使用說明:
[root@01server ~]# ngxtop --help ngxtop - ad-hoc query for nginx access log. Usage: ngxtop [options] ngxtop [options] (print|top|avg|sum) <var> ... ngxtop info ngxtop [options] query <query> ... Options: -l <file>, --access-log <file> # 需要分析的訪問日志 -f <format>, --log-format <format> # log_format指令指定的日志格式 [默認: combined] --no-follow ngxtop default behavior is to ignore current lines in log and only watch for new lines as they are written to the access log. Use this flag to tell ngxtop to process the current content of the access log instead. # 簡而言之,對歷史信息進行統(tǒng)計 -t <seconds>, --interval <seconds> report interval when running in follow mode [default: 2.0] # 指定監(jiān)控信息刷新的間隔,單位為秒 [默認: 2.0] -g <var>, --group-by <var> # 根據(jù)變量分組 [默認: request_path] -w <var>, --having <expr> # 具備子句 [默認: 1] having clause [default: 1] -o <var>, --order-by <var> # 排序 [默認: count] -n <number>, --limit <number> # 顯示的條數(shù) [默認: 10] -a <exp> ..., --a <exp> ... add exp (must be aggregation exp: sum, avg, min, max, etc.) into output # 添加聚合表達式到輸出信息中 -v, --verbose # 更多的輸出 -d, --debug # 打印所有行和解析記錄,debug -h, --help # 當前幫助信息. --version # 輸出版本信息.
高級選項:
-c <file>, --config <file> # 運行ngxtop解析nginx配置文件 -i <filter-expression>, --filter <filter-expression> filter in, records satisfied given expression are processed. # 根據(jù)指定的表達式進行過濾,僅顯示過濾后的信息 -p <filter-expression>, --pre-filter <filter-expression> in-filter expression to check in pre-parsing phase. # 在篩選器表達式中檢查預(yù)解析階段
范例:
All examples read nginx config file for access log location and format. If you want to specify the access log file and / or log format, use the -f and -a options. "top" like view of nginx requests 指定配置文件啟動ngxtop: $ ngxtop -c /usr/local/nginx/conf/nginx.conf 404前十的請求: $ ngxtop top request_path --filter 'status == 404' 總流量前十的請求: $ ngxtop --order-by 'avg(bytes_sent) * count' 訪問量前十的ip地址: $ ngxtop --group-by remote_addr 輸出400以上狀態(tài)碼的請求以及請求來源: $ ngxtop -i 'status >= 400' print request status http_referer Average body bytes sent of 200 responses of requested path begin with 'foo': $ ngxtop avg bytes_sent --filter 'status == 200 and request_path.startswith("foo")'
指定nginx的配置文件進行啟動:
[root@01server ~]# ngxtop -c /usr/local/nginx/conf/nginx.conf
啟動后如下:
注:Summary相當于請求的概覽信息,Detailed就自然是請求的詳細信息了。2xx、3xx、4xx以及5xx,都是表示的http狀態(tài)。avg_bytes_sent表示請求所發(fā)送的字節(jié)數(shù)平均值,request_path則是請求路徑,count表示請求的總次數(shù)。
默認情況下,ngxtop不會顯示啟動ngxtop之前的請求信息,只會顯示ngxtop啟動之后新的請求信息。所以我們可以到瀏覽器上刷新一下,隨便訪問一些頁面,人為制造一些請求。如下圖,這時就可以看到ngxtop成功監(jiān)控到了請求信息:
我們可以通過選項來指定一些條件,例如我希望只顯示http狀態(tài)是200的,就可以使用-i進行指定:
[root@01server ~]# ngxtop -c /usr/local/nginx/conf/nginx.conf -i 'status == 200'
如下:
例如我希望顯示訪問最多的ip,就可以使用-g進行指定:
[root@01server ~]# ngxtop -c /usr/local/nginx/conf/nginx.conf -g remote_addr
如下:
如果想要查看之前的請求信息可以使用–no-follow選項,相當于是對歷史的請求信息做了一個統(tǒng)計,如下:
關(guān)于ngxtop常用操作就先簡單介紹到這,希望詳細了解最直接的就是查閱該項目在github上的文檔。
nginx-rrd圖形化監(jiān)控
在上兩小節(jié)中,我們介紹了兩個基礎(chǔ)的nginx工具,能夠監(jiān)控連接信息和請求信息,它們都是基于命令行的。本小節(jié)則介紹一個圖形化的nginx監(jiān)控工具,該工具就是nginx-rrd。nginx-rrd 也是 Nginx 官方推薦的一款 Nginx 監(jiān)控工具,利用 nginx-rrd 可以很方便的生成圖表,它可以監(jiān)控連接信息和請求信息。
nginx-rrd 官網(wǎng)地址如下:
https://www.nginx.com/resources/wiki/modules/rrd_graph/
那么我們接下來就看看如何安裝并使用nginx-rrd吧。nginx-rrd部分功能是基于上兩小節(jié)所介紹的工具實現(xiàn)的,所以在安裝nginx-rrd之前需要根據(jù)上兩節(jié)的介紹安裝好所需的工具。由于nginx-rrd是使用php實現(xiàn)的,所以在此之前,我們得先安裝好php的運行環(huán)境,以及安裝rrdtool的相關(guān)依賴。我這里使用yum進行安裝,命令如下:
[root@01server ~]# yum install -y php php-gd php-soap php-mbstring php-xmlrpc php-dom php-fpm [root@01server ~]# yum install -y perl rrdtool perl-libwww-perl libwww-perl perl-rrdtool
安裝好php運行環(huán)境以及rrdtool后,我們還需要把nginx和php-fpm進行一個整合。修改php-fpm的配置文件,將文件中的user和group修改為與nginx.conf中的user一致:
[root@01server ~]# vim /etc/php-fpm.d/www.conf user = nobody group = nobody [root@01server ~]#
還需要讓nginx支持解析php,在虛擬主機配置文件中,增加如下內(nèi)容:
[root@01server ~]# vim /usr/local/nginx/conf/vhost/default.conf # 添加以下內(nèi)容 location ~ .php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name; } [root@01server ~]#
配置好后,啟動php-fpm服務(wù),并且重新加載nginx:
[root@01server ~]# systemctl start php-fpm [root@01server ~]# netstat -lntp |grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 24418/php-fpm: mast [root@01server ~]# nginx -s reload
然后在虛擬主機配置文件中所指向的網(wǎng)站根目錄下,新建一個簡單的php文件,用于測試nginx是否已經(jīng)能夠正常解析php代碼:
[root@01server ~]# vim /usr/local/nginx/html/index.php # 文件內(nèi)容如下 <?php phpinfo(); ?> [root@01server ~]#
接著到瀏覽器上進行訪問,如下則是代表nginx已經(jīng)能夠支持解析php了:
現(xiàn)在我們就可以開始安裝nginx-rrd了,首先使用如下命令,下載nginx-rrd的壓縮包:
[root@01server ~]# cd /usr/local/src/ [root@01server /usr/local/src]# wget http://soft.vpser.net/status/nginx-rrd/nginx-rrd-0.1.4.tgz
然后解壓,并且拷貝一些腳本文件及配置文件到相應(yīng)的系統(tǒng)目錄下:
[root@01server /usr/local/src]# tar -zvxf nginx-rrd-0.1.4.tgz [root@01server /usr/local/src]# cd nginx-rrd-0.1.4 [root@01server /usr/local/src/nginx-rrd-0.1.4]# ls etc html usr [root@01server /usr/local/src/nginx-rrd-0.1.4]# cp etc/nginx-rrd.conf /etc [root@01server /usr/local/src/nginx-rrd-0.1.4]# cp usr/sbin/* /usr/sbin [root@01server /usr/local/src/nginx-rrd-0.1.4]# rm -rf /usr/local/nginx/html/index.php # 刪除之前測試用的php文件 [root@01server /usr/local/src/nginx-rrd-0.1.4]# cp html/index.php /usr/local/nginx/html/
修改nginx-rrd配置文件,配置數(shù)據(jù)存儲目錄以及圖片存儲目錄,如下:
[root@01server ~]# vim /etc/nginx-rrd.conf # dir where rrd databases are stored RRD_DIR="/usr/local/nginx/html/nginx-rrd"; # 數(shù)據(jù)存儲目錄 # dir where png images are presented WWW_DIR="/usr/local/nginx/html"; # 圖片存儲目錄 [root@01server ~]#
配置完之后,我們還需要使用 crontab 新建定時任務(wù),用于定時執(zhí)行nginx-rrd的兩個腳本,因為nginx-rrd需要定時去采集數(shù)據(jù)才能實現(xiàn)一個監(jiān)控的效果:
[root@01server ~]# crontab -e * * * * * /bin/sh /usr/sbin/nginx-collect # 采集數(shù)據(jù)腳本 */1 * * * * /bin/sh /usr/sbin/nginx-graph # 生成圖片腳本 [root@01server ~]#
我們這里設(shè)定的定時任務(wù)是每一分鐘執(zhí)行一次,可以使用如下命令查看定時任務(wù)是否有在執(zhí)行:
[root@01server ~]# tail -f /var/log/cron
確認定時任務(wù)有正常執(zhí)行后,我們來安裝apache的一個壓測工具,方便于我們生成大量的請求數(shù)據(jù):
[root@01server ~]# yum -y install httpd-tools
安裝完成后,使用以下命令,對nginx進行壓測,可以多執(zhí)行幾次:
[root@01server ~]# ab -n 10000 -c 10 http://127.0.0.1/index.html
命令說明:
- -n 指定總共發(fā)送多少個請求
- -c 指定同時發(fā)送多少個請求
使用壓測工具產(chǎn)生了一些請求數(shù)據(jù)后,到瀏覽器上訪問nginx-rrd的index.php文件,效果如下:
nginx優(yōu)化
在以上小節(jié)中,我們介紹了一些nginx的監(jiān)控工具。知道了如何對nginx進行性能監(jiān)控后,我們自然就需要知道一些nginx的常用優(yōu)化參數(shù)和配置,所以本小節(jié)就是介紹一些nginx的常見優(yōu)化方式。
1.配置工作進程數(shù)和并發(fā)連接數(shù)。
默認情況下,nginx只有一個工作進程,1024個并發(fā)連接數(shù)。當我們需要提高nginx的并發(fā)負載能力時,可以適當?shù)脑黾庸ぷ鬟M程數(shù)和并發(fā)連接數(shù)。在nginx.conf里進行配置:
[root@01server ~]# vim /usr/local/nginx/conf/nginx.conf # 修改或增加如下幾個參數(shù) worker_processes 2; # 工作進程數(shù)受cpu核心數(shù)的限制,數(shù)量不能超過cpu的核心數(shù) events { use epoll; # 使用epoll模型,可以提高并發(fā)效率 multi_accept on; # 開啟一次建立多個連接 worker_connections 10240; # 每一個工作進程能夠打開的最大連接數(shù),包含了nginx與客戶端和nginx與upstream之間的連接 } [root@01server ~]#
2.配置反向代理(后端Server)的長連接
Nginx upstream與后端的連接默認為短連接,通過HTTP/1.0向后端發(fā)起連接,并把請求的”Connection” header設(shè)為”close”。Nginx與前端的連接默認為長連接,一個用戶跟Nginx建立連接之后,通過這個長連接發(fā)送多個請求。如果Nginx只是作為reverse proxy的話,可能一個用戶連接就需要多個向后端的短連接。如果后端的服務(wù)器(源站或是緩存服務(wù)器)處理并發(fā)連接能力不強的話,就可能導(dǎo)致瓶頸的出現(xiàn)。所以我們才需要配置反向代理的長連接,以此緩解瓶頸的問題。示例配置如下:
[root@01server ~]# vim /usr/local/nginx/conf/vhost/default.conf upstream server_pool{ server localhost:8080 weight=1 max_fails=2 fail_timeout=30s; server localhost:9080 weight=1 max_fails=2 fail_timeout=30s; keepalive 300; # 設(shè)置300個長連接,長連接能夠大大提高請求轉(zhuǎn)換的效率 } location / { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://server_pool/; } [root@01server ~]#
3.配置gzip壓縮
我們都知道http傳輸?shù)幕径际俏谋緮?shù)據(jù),對文本數(shù)據(jù)進行壓縮后,能夠減小數(shù)據(jù)的體積。這樣就能夠大幅提高訪問效率,與頁面的加載速度,并且還能夠降低帶寬資源的消耗。示例配置如下:
[root@01server ~]# vim /usr/local/nginx/conf/nginx.conf gzip on; # 開啟Gzip gzip_http_version 1.1; gzip_disable "MSIE [1-6].(?!.*SV1)"; # ie6不提供gzip gzip_proxied any; gzip_types text/plain application/x-javascript text/css application/xml application/json application/x-font-ttf application/sfg+xml application/x-icon text/javascript application/x-httpd-php image/jpeg image/gif image/png; # 需要壓縮的類型 gzip_vary on; gzip_static on; # 如果有壓縮好的,直接使用 [root@01server ~]#
4.操作系統(tǒng)優(yōu)化
在Linux操作系統(tǒng)中,我們可以通過修改 /etc/sysctl.conf
系統(tǒng)配置文件,以此來設(shè)置tcp/ip連接的相關(guān)參數(shù),可以在操作系統(tǒng)層面上提高網(wǎng)絡(luò)連接的效率。示例配置如下:
[root@01server ~]# vim /etc/sysctl.conf net.ipv4.tcp_syncookies = 1 # 防止一個套接字在有過多試圖連接到達時引起過載 net.core.somaxconn = 1024 # 連接隊列的長度,默認值為128, net.ipv4.tcp_fin_timeout = 10 # timewait的超時時間,設(shè)置短一些 net.ipv4.tcp_tw_reuse = 1 # os直接使用timewait的連接 net.ipv4.tcp_tw_recycle = 0 # 回收禁用,不回收timewait連接 [root@01server ~]#
還可以在 /etc/security/limits.conf
配置文件中,配置一個進程可以打開的最大文件數(shù)量。示例配置如下:
[root@01server ~]# vim /etc/security/limits.conf * hard nofile 204800 * soft nofile 204800 * soft core unlimited * soft stack 204800 [root@01server ~]#
5.其他優(yōu)化:
示例配置如下:
[root@01server ~]# vim /usr/local/nginx/conf/nginx.conf sendfile on; # 減少文件在應(yīng)用和內(nèi)核之間的拷貝 tcp_nopush on; # 當數(shù)據(jù)包達到一定大小再發(fā)送,避免頻繁發(fā)送數(shù)據(jù)包 tcp_nodelay off; # 關(guān)閉有數(shù)據(jù)就隨時發(fā)送,也是避免頻繁發(fā)送數(shù)據(jù)包 [root@01server ~]#