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

posted @ 2022-12-09 23:32  yangwen0228  阅读(2784)  评论(0编辑  收藏  举报