nginx反向代理worker_rlimit_nofile和worker_connections配置
nginx反向代理worker_rlimit_nofile和worker_connections配置
当worker_rlimit_nofile和worker_connections配置过小时,会导致调用大量失败。具体这个值和用户量的关系是怎样的呢?
先说结论,验证过程还挺麻烦的,试了一天才发现这个规律,要想服务调用返回不报错:
worker_rlimit_nofile >= 7 + 2 * worker_proceses + 2 * user_count
worker_connections >= 2 + 2 * user_count
当然这个是反向代理的情况,如果是正向静态资源的服务器,因为不涉及到后端服务器的反向连接,所以,不需要乘以2。
其中,worker_rlimit_nofile是限制能够打开多少静态资源或者连接的真正限制,worker_connections是nginx内部连接池的大小:
- 错误配置模式一:当worker_rlimit_nofile比worker_connections小时,建立socket会失败,但建立socket成功的,最后会执行成功,整体的错误率不会太高。
- 错误配置模式二:当worker_rlimit_nofile比worker_connections大时,建立socket会成功,但获取内部空闲连接池会失败,会导致大量的报错,整体错误率很高。
压测时,两种模式实际正确的数量是差不多的,错误的数量会差别比较大,因为模式一一旦创建成功,实际的业务处理过程是消耗时间的,而模式二会在建立连接阶段就报错。
这个仅与JMeter的压测模式有关系,实际场景中,不同的场景有不同的效果,比如登录场景,一个用户不可能一直在那里登录登出,所以,效果是一样的。但其他的可以持续操作的场景,并且关掉了keepalive等功能,那模式一的感受是,大多数操作是正常的,偶尔会有报错,而模式二,响应很快,但大多数操作是错误的,偶尔是正确的。而现在keepalive是http1.1默认的配置,短时间内重复调用(nginx默认60s),tcp是可以复用的,也不存在这个问题。所以,在实际场景中,将worker_rlimit_nofile和worker_connections都设置到一个比较大的值即可。
nginx的基本配置在/etc/nginx/nginx.conf
如下:
user www-data;
worker_processes 1;
worker_rlimit_nofile 10;
events {
worker_connections 2;
}
http {
upstream app {
server 127.0.0.1:8080;
}
server {
keepalive_requests 1; #单连接请求上限次数。
keepalive_timeout 1;
listen 4545 ssl; #监听端口
server_name 127.0.0.1; #监听地址
location /app/api/ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
proxy_pass http://app/api/;
}
}
}
先是把nginx启动起来,worker_rlimit_nofile < 10时,会直接启动失败,查看日志 /var/log/nginx/error.log
:
当worker_connections < 2时,会直接启动失败:
所以,能够启动的最小配置是worker_rlimit_nofile = 10, worker_connections = 2,但这仅是启动的最小配置,不是能够服务的最小配置:
调用会全部失败,JMeter配置如下,JMeter的使用不赘述,需要注意的是其中的Same user on each iteration是5.0之后新增的选项,可以让每次请求产生新的线程,并把http的cookie清除,保证每次都创建新的tcp连接:
全部失败:
失败原因:
查看日志 /var/log/nginx/error.log
:
将worker_rlimit_nofile改为11,worker_connections改为3,还是全部失败:
失败原因:
查看日志 /var/log/nginx/error.log
:
所以,当worker_connections为3时,可以建立client到nginx的连接,但是nginx到upstream反向代理的连接是创建不了的。每个连接需要2个文件句柄fd和2个connection。最小的可以工作的worker_rlimit_nofile是11,worker_connections是4,可以服务一个user。
经过各种测试,最后总结出来了规律:
当worker_processes设置为1时
worker_rlimit_nofile = 9 + 2 * user_count
worker_connections = 2 + 2 * user_count
为什么会有一个9和2呢?用lsof
神器(list of files)命令看一下nginx worker 进程打开了哪些文件,毕竟linux里面所有的设备都是文件。
先用ps
命令查看nginx的进程情况和用户名,nginx: worker process的用户名是 www-data
:
ps -ef | grep nginx
www-data 3426 27402 0 22:53 ? 00:00:00 nginx: worker process
root 3432 27388 0 22:58 pts/4 00:00:00 grep nginx
root 27402 16790 0 Dec08 ? 00:00:00 nginx: master process nginx
使用 lsof
的 -u
选项指定用户名 www-data
即可查出nginx: worker process打开了哪些文件:
lsof -u www-data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3426 www-data cwd DIR 8,16 4096 167 /home/yangwen
nginx 3426 www-data rtd DIR 8,16 4096 2 /
nginx 3426 www-data txt REG 8,16 1190896 5263 /usr/sbin/nginx
nginx 3426 www-data mem REG 8,16 180632 5233 /usr/lib/nginx/modules/ngx_stream_module.so
nginx 3426 www-data mem REG 8,16 112104 5218 /usr/lib/nginx/modules/ngx_mail_module.so
...
nginx 3426 www-data DEL REG 0,1 1202 /dev/zero
nginx 3426 www-data 0u CHR 1,3 0t0 3 /dev/null
nginx 3426 www-data 1u CHR 1,3 0t0 3 /dev/null
nginx 3426 www-data 2w REG 8,16 230 15099 /var/log/nginx/error.log
nginx 3426 www-data 3w REG 8,16 1330 59514 /var/log/nginx/access.log
nginx 3426 www-data 4w REG 8,16 230 15099 /var/log/nginx/error.log
nginx 3426 www-data 6u IPv4 549335 0t0 TCP *:4545 (LISTEN)
nginx 3426 www-data 7u unix 0x00000000d5c2f304 0t0 2363423 type=STREAM
nginx 3426 www-data 10u a_inode 0,11 0 17160 [eventpoll]
最主要的是下面那几个0u 1u 2w那些,刚好是8个,为什么不是9?
实际上,当我们把worker_rlimit_nofile调大到12,再次查看,会发现刚好是9了,会多一个[eventfd]:
lsof -u www-data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3463 www-data cwd DIR 8,16 4096 167 /home/yangwen
nginx 3463 www-data rtd DIR 8,16 4096 2 /
nginx 3463 www-data txt REG 8,16 1190896 5263 /usr/sbin/nginx
nginx 3463 www-data mem REG 8,16 180632 5233 /usr/lib/nginx/modules/ngx_stream_module.so
nginx 3463 www-data mem REG 8,16 112104 5218 /usr/lib/nginx/modules/ngx_mail_module.so
...
nginx 3463 www-data DEL REG 0,1 1202 /dev/zero
nginx 3463 www-data 0u CHR 1,3 0t0 3 /dev/null
nginx 3463 www-data 1u CHR 1,3 0t0 3 /dev/null
nginx 3463 www-data 2w REG 8,16 148 33176 /var/log/nginx/error.log
nginx 3463 www-data 3w REG 8,16 0 59515 /var/log/nginx/access.log
nginx 3463 www-data 4w REG 8,16 148 33176 /var/log/nginx/error.log
nginx 3463 www-data 6u IPv4 549335 0t0 TCP *:4545 (LISTEN)
nginx 3463 www-data 7u unix 0x000000008055c079 0t0 2359598 type=STREAM
nginx 3463 www-data 8u a_inode 0,11 0 17160 [eventpoll]
nginx 3463 www-data 9u a_inode 0,11 0 17160 [eventfd]
当worker_processes设置为2时
worker_rlimit_nofile = 10 + 2 * user_count
worker_connections = 2 + 2 * user_count
worker_rlimit_nofile最小值是13:
lsof -u www-data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3482 www-data cwd DIR 8,16 4096 167 /home/yangwen
nginx 3482 www-data rtd DIR 8,16 4096 2 /
nginx 3482 www-data txt REG 8,16 1190896 5263 /usr/sbin/nginx
nginx 3482 www-data mem REG 8,16 180632 5233 /usr/lib/nginx/modules/ngx_stream_module.so
nginx 3482 www-data mem REG 8,16 112104 5218 /usr/lib/nginx/modules/ngx_mail_module.so
...
nginx 3482 www-data DEL REG 0,1 1202 /dev/zero
nginx 3482 www-data 0u CHR 1,3 0t0 3 /dev/null
nginx 3482 www-data 1u CHR 1,3 0t0 3 /dev/null
nginx 3482 www-data 2w REG 8,16 315 1498 /var/log/nginx/error.log
nginx 3482 www-data 3w REG 8,16 0 59514 /var/log/nginx/access.log
nginx 3482 www-data 4w REG 8,16 315 1498 /var/log/nginx/error.log
nginx 3482 www-data 5u unix 0x000000008f70a4ac 0t0 2359618 type=STREAM
nginx 3482 www-data 6u IPv4 549335 0t0 TCP *:4545 (LISTEN)
nginx 3482 www-data 7u unix 0x0000000036c7fa98 0t0 2359617 type=STREAM
nginx 3482 www-data 10u a_inode 0,11 0 17160 [eventpoll]
nginx 3482 www-data 11u a_inode 0,11 0 17160 [eventfd]
nginx 3483 www-data cwd DIR 8,16 4096 167 /home/yangwen
nginx 3483 www-data rtd DIR 8,16 4096 2 /
nginx 3483 www-data txt REG 8,16 1190896 5263 /usr/sbin/nginx
nginx 3483 www-data mem REG 8,16 180632 5233 /usr/lib/nginx/modules/ngx_stream_module.so
nginx 3483 www-data mem REG 8,16 112104 5218 /usr/lib/nginx/modules/ngx_mail_module.so
...
nginx 3483 www-data DEL REG 0,1 1202 /dev/zero
nginx 3483 www-data 0u CHR 1,3 0t0 3 /dev/null
nginx 3483 www-data 1u CHR 1,3 0t0 3 /dev/null
nginx 3483 www-data 2w REG 8,16 315 1498 /var/log/nginx/error.log
nginx 3483 www-data 3w REG 8,16 0 59514 /var/log/nginx/access.log
nginx 3483 www-data 4w REG 8,16 315 1498 /var/log/nginx/error.log
nginx 3483 www-data 5u unix 0x000000003ce00657 0t0 2359616 type=STREAM
nginx 3483 www-data 6u IPv4 549335 0t0 TCP *:4545 (LISTEN)
nginx 3483 www-data 11u unix 0x00000000b66fbba0 0t0 2359619 type=STREAM
nginx 3483 www-data 12u a_inode 0,11 0 17160 [eventpoll]
相比于一个worker process的情况,两个worker process时,会有两个STREAM类型的文件fd。
结论
同理,当有3个worker process时,需要有三个STREAM类型的fd,最小的启动worker_rlimit_nofile是15。
所以最小可以运行的:
worker_rlimit_nofile = 7 + 2 * worker_proceses + 2 * user_count