共计 12111 个字符,预计需要花费 31 分钟才能阅读完成。
ngx_http_stub_status 监控连接信息
nginx 现已成为目前使用最广泛的 web 服务器和反向代理服务器,我们线上的 Tomcat 服务器一般都会由 nginx 进行代理,以此实现负载均衡的效果。既然 nginx 被应用得那么广泛,我们自然也得学习如何去对 nginx 做性能监控。本小节将介绍如何使用 nginx 的 ngx_http_stub_status 模块来对连接信息进行监控。本文默认读者有 nginx 的基础,所以一些基础性的东西不会过多介绍。
关于该模块的官方文档地址如下:
http://nginx.org/en/docs/http/ngx_http_stub_status_module.html
如果你的 nginx 是使用 yum 进行安装的,那么一般会自带这个模块,可以忽略以下这段为了安装 ngx_http_stub_status 模块而重新编译安装 nginx 的部分。因为我的 nginx 是编译安装的,当时并没有加上这个模块进行编译,所以现在还需要重新去编译安装一次。过程如下:
[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 # 进入之前已经解压好的目录
[root@01server /usr/local/src/nginx-1.12.1]# ./configure --prefix=/usr/local/nginx --with-http_stub_status_module # 加入编译参数,指定需要安装的模块
[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 # 可以已经把模块安装好了
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 # 将以下内容粘贴进去
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 # 虚拟主机配置文件,将以下内容粘贴进去
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; # 关闭日志
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,访问成功响应的信息如下:
说明:
- Active connections 当前活动的连接数量(包括等待的)
- accepts 已接收的连接总数
- handled 已处理的连接总数
- requests 当前的请求总数
- Reading nginx 正在读取的连接数量
- Writing nginx 正在响应的连接数量
- Waiting 当前空闲的连接数量
如上,通过这些简单的参数可以看到 nginx 当前的连接信息。在高并发场景下,可以根据 Active connections 参数判断当前的一个并发数量,Reading 参数则可以告诉我们当前 nginx 是否繁忙。当然,这只是最简单的一个 nginx 的监控方式,参数也就只有那么几个。但这些都是其他更高级的监控工具的基础,所以了解这些基础监控也是有必要的。
ngxtop 监控请求信息
在上一小节中,我们介绍了如何利用 ngx_http_stub_status 模块去监控 nginx 的连接信息。本小节将介绍如何使用 ngxtop 工具来监控 nginx 的请求信息。
ngxtop 可以实时解析 nginx 访问日志,并且将处理结果输出到终端,功能类似于系统命令 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 <seconds>, --interval <seconds> report interval when running in follow mode [default: 2.0] # 指定监控信息刷新的间隔,单位为秒 [默认: 2.0]
-g <var>, --group-by <var> # 根据变量分组 [默认: request_path]
-w <var>, --having <expr> # 具备子句 [默认: 1] having clause [default: 1]
-o <var>, --order-by <var> # 排序 [默认: count]
-n <number>, --limit <number> # 显示的条数 [默认: 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. # 根据指定的表达式进行过滤,仅显示过滤后的信息
-p <filter-expression>, --pre-filter <filter-expression> in-filter expression to check in pre-parsing phase. # 在筛选器表达式中检查预解析阶段
范例:
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 以上状态码的请求以及请求来源:
$ 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 状态。avg_bytes_sent 表示请求所发送的字节数平均值,request_path 则是请求路径,count 表示请求的总次数。
默认情况下,ngxtop 不会显示启动 ngxtop 之前的请求信息,只会显示 ngxtop 启动之后新的请求信息。所以我们可以到浏览器上刷新一下,随便访问一些页面,人为制造一些请求。如下图,这时就可以看到 ngxtop 成功监控到了请求信息:
我们可以通过选项来指定一些条件,例如我希望只显示 http 状态是 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 选项,相当于是对历史的请求信息做了一个统计,如下:
关于 ngxtop 常用操作就先简单介绍到这,希望详细了解最直接的就是查阅该项目在 github 上的文档。
nginx-rrd 图形化监控
在上两小节中,我们介绍了两个基础的 nginx 工具,能够监控连接信息和请求信息,它们都是基于命令行的。本小节则介绍一个图形化的 nginx 监控工具,该工具就是 nginx-rrd。nginx-rrd 也是 Nginx 官方推荐的一款 Nginx 监控工具,利用 nginx-rrd 可以很方便的生成图表,它可以监控连接信息和请求信息。
nginx-rrd 官网地址如下:
https://www.nginx.com/resources/wiki/modules/rrd_graph/
那么我们接下来就看看如何安装并使用 nginx-rrd 吧。nginx-rrd 部分功能是基于上两小节所介绍的工具实现的,所以在安装 nginx-rrd 之前需要根据上两节的介绍安装好所需的工具。由于 nginx-rrd 是使用 php 实现的,所以在此之前,我们得先安装好 php 的运行环境,以及安装 rrdtool 的相关依赖。我这里使用 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 运行环境以及 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,在虚拟主机配置文件中,增加如下内容:
[root@01server ~]# vim /usr/local/nginx/conf/vhost/default.conf # 添加以下内容
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 服务,并且重新加载 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
然后在虚拟主机配置文件中所指向的网站根目录下,新建一个简单的 php 文件,用于测试 nginx 是否已经能够正常解析 php 代码:
[root@01server ~]# vim /usr/local/nginx/html/index.php # 文件内容如下
<?php phpinfo(); ?>
[root@01server ~]#
接着到浏览器上进行访问,如下则是代表 nginx 已经能够支持解析 php 了:
现在我们就可以开始安装 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
然后解压,并且拷贝一些脚本文件及配置文件到相应的系统目录下:
[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 配置文件,配置数据存储目录以及图片存储目录,如下:
[root@01server ~]# vim /etc/nginx-rrd.conf
# dir where rrd databases are stored
RRD_DIR="/usr/local/nginx/html/nginx-rrd"; # 数据存储目录
# dir where png images are presented
WWW_DIR="/usr/local/nginx/html"; # 图片存储目录
[root@01server ~]#
配置完之后,我们还需要使用 crontab 新建定时任务,用于定时执行 nginx-rrd 的两个脚本,因为 nginx-rrd 需要定时去采集数据才能实现一个监控的效果:
[root@01server ~]# crontab -e
* * * * * /bin/sh /usr/sbin/nginx-collect # 采集数据脚本
*/1 * * * * /bin/sh /usr/sbin/nginx-graph # 生成图片脚本
[root@01server ~]#
我们这里设定的定时任务是每一分钟执行一次,可以使用如下命令查看定时任务是否有在执行:
[root@01server ~]# tail -f /var/log/cron
确认定时任务有正常执行后,我们来安装 apache 的一个压测工具,方便于我们生成大量的请求数据:
[root@01server ~]# yum -y install httpd-tools
安装完成后,使用以下命令,对 nginx 进行压测,可以多执行几次:
[root@01server ~]# ab -n 10000 -c 10 http://127.0.0.1/index.html
命令说明:
- -n 指定总共发送多少个请求
- -c 指定同时发送多少个请求
使用压测工具产生了一些请求数据后,到浏览器上访问 nginx-rrd 的 index.php 文件,效果如下:
nginx 优化
在以上小节中,我们介绍了一些 nginx 的监控工具。知道了如何对 nginx 进行性能监控后,我们自然就需要知道一些 nginx 的常用优化参数和配置,所以本小节就是介绍一些 nginx 的常见优化方式。
1. 配置工作进程数和并发连接数。
默认情况下,nginx 只有一个工作进程,1024 个并发连接数。当我们需要提高 nginx 的并发负载能力时,可以适当的增加工作进程数和并发连接数。在 nginx.conf 里进行配置:
[root@01server ~]# vim /usr/local/nginx/conf/nginx.conf # 修改或增加如下几个参数
worker_processes 2; # 工作进程数受 cpu 核心数的限制,数量不能超过 cpu 的核心数
events
{use epoll; # 使用 epoll 模型,可以提高并发效率
multi_accept on; # 开启一次建立多个连接
worker_connections 10240; # 每一个工作进程能够打开的最大连接数,包含了 nginx 与客户端和 nginx 与 upstream 之间的连接
}
[root@01server ~]#
2. 配置反向代理(后端 Server)的长连接
Nginx upstream 与后端的连接默认为短连接,通过 HTTP/1.0 向后端发起连接,并把请求的 ”Connection” header 设为 ”close”。Nginx 与前端的连接默认为长连接,一个用户跟 Nginx 建立连接之后,通过这个长连接发送多个请求。如果 Nginx 只是作为 reverse proxy 的话,可能一个用户连接就需要多个向后端的短连接。如果后端的服务器(源站或是缓存服务器)处理并发连接能力不强的话,就可能导致瓶颈的出现。所以我们才需要配置反向代理的长连接,以此缓解瓶颈的问题。示例配置如下:
[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; # 设置 300 个长连接,长连接能够大大提高请求转换的效率
}
location / {proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://server_pool/;
}
[root@01server ~]#
3. 配置 gzip 压缩
我们都知道 http 传输的基本都是文本数据,对文本数据进行压缩后,能够减小数据的体积。这样就能够大幅提高访问效率,与页面的加载速度,并且还能够降低带宽资源的消耗。示例配置如下:
[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. 操作系统优化
在 Linux 操作系统中,我们可以通过修改 /etc/sysctl.conf
系统配置文件,以此来设置 tcp/ip 连接的相关参数,可以在操作系统层面上提高网络连接的效率。示例配置如下:
[root@01server ~]# vim /etc/sysctl.conf
net.ipv4.tcp_syncookies = 1 # 防止一个套接字在有过多试图连接到达时引起过载
net.core.somaxconn = 1024 # 连接队列的长度,默认值为 128,
net.ipv4.tcp_fin_timeout = 10 # timewait 的超时时间,设置短一些
net.ipv4.tcp_tw_reuse = 1 # os 直接使用 timewait 的连接
net.ipv4.tcp_tw_recycle = 0 # 回收禁用,不回收 timewait 连接
[root@01server ~]#
还可以在 /etc/security/limits.conf
配置文件中,配置一个进程可以打开的最大文件数量。示例配置如下:
[root@01server ~]# vim /etc/security/limits.conf
* hard nofile 204800
* soft nofile 204800
* soft core unlimited
* soft stack 204800
[root@01server ~]#
5. 其他优化:
示例配置如下:
[root@01server ~]# vim /usr/local/nginx/conf/nginx.conf
sendfile on; # 减少文件在应用和内核之间的拷贝
tcp_nopush on; # 当数据包达到一定大小再发送,避免频繁发送数据包
tcp_nodelay off; # 关闭有数据就随时发送,也是避免频繁发送数据包
[root@01server ~]#
: