查看httpd进程数
ps -ef | grep httpd | wc -l
查看Apache的并发请求数及其TCP连接状态
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
其中的SYN_RECV表示正在等待处理的请求数;
ESTABLISHED表示正常数据传输状态;
TIME_WAIT表示处理完毕,等待超时结束的请求数。
ps -ef | grep httpd | wc -l
查看Apache的并发请求数及其TCP连接状态
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
LAST_ACK 5
SYN_RECV 30
ESTABLISHED 1597
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057
其中的SYN_RECV表示正在等待处理的请求数;
ESTABLISHED表示正常数据传输状态;
TIME_WAIT表示处理完毕,等待超时结束的请求数。
并发连接数查看
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
netstat -n|grep ^tcp|awk '{print $NF}'|sort -nr|uniq -c
或者:
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'
返回结果一般如下:
LAST_ACK 5 (正在等待处理的请求数)
SYN_RECV 30
ESTABLISHED 1597 (正常数据传输状态)
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)
其他参数说明:
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接 ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
netstat -n|grep ^tcp|awk '{print $NF}'|sort -nr|uniq -c
或者:
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'
返回结果一般如下:
LAST_ACK 5 (正在等待处理的请求数)
SYN_RECV 30
ESTABLISHED 1597 (正常数据传输状态)
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)
其他参数说明:
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接 ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
https://www.isfirst.net/yunwei/89
二、高并发状态下nginx的配置(20万并发)
[!TIP] nginx出现了十六七万将近二十万并发(ESTABLISH连接数)的情况
2.1 操作系统基础优化
关键需要修改地方
net.ipv4.tcp_max_tw_buckets = 940000
net.ipv4.tcp_tw_recycle=0
net.ipv4.ip_local_port_range = 1024 65000
#端口范围尽量大一些
关键需要修改地方
net.ipv4.tcp_max_tw_buckets = 940000
net.ipv4.tcp_tw_recycle=0
net.ipv4.ip_local_port_range = 1024 65000
#端口范围尽量大一些
2.2 nf_conntrack的配置
如果启用了nf_conntrack,并且配置的数值较小,那么会遇到
nf_conntrack: table full, dropping packet
如果可能的话,建议关闭nf_conntrack,设置NOTRACK或者调大数值
nf_conntrack_max = 4194304
nf_conntrack_buckets = 1048576
nf_conntrack_tcp_timeout_time_wait = 60
如果启用了nf_conntrack,并且配置的数值较小,那么会遇到
nf_conntrack: table full, dropping packet
如果可能的话,建议关闭nf_conntrack,设置NOTRACK或者调大数值
nf_conntrack_max = 4194304
nf_conntrack_buckets = 1048576
nf_conntrack_tcp_timeout_time_wait = 60
2.3 文件打开数配置
如果你的文件打开数是65535,那么应该先遇到的错误是”Too many open files”
error: 2019/06/15 17:03:51 [crit] 3325#0: accept4() failed (24: Too many open files)
需要调整操作系统的/etc/security/limits.conf以及附属文件。
在nginx层面有2个参数也需要调整
worker_rlimit_nofile 512000;
##@@worker进程的最大打开文件数限制。
worker_connections 151200;
##@@worker进程可以保持的最大并发连接。官方文档明确标出,作为代理使用时,这个值包含"nginx与客户端的连接"和"nginx与upstream的连接"。
如果你的文件打开数是65535,那么应该先遇到的错误是”Too many open files”
error: 2019/06/15 17:03:51 [crit] 3325#0: accept4() failed (24: Too many open files)
需要调整操作系统的/etc/security/limits.conf以及附属文件。
在nginx层面有2个参数也需要调整
worker_rlimit_nofile 512000;
##@@worker进程的最大打开文件数限制。
worker_connections 151200;
##@@worker进程可以保持的最大并发连接。官方文档明确标出,作为代理使用时,这个值包含"nginx与客户端的连接"和"nginx与upstream的连接"。
网上有个公式: max_clients = worker_processes * worker_connections / 2; (部分文档是除以4,是考虑浏览器并发数为2) 这个参数解决了,基本上七八万的ESTABLISH是没问题了
2.4 端口耗尽的问题
如果并发数继续往上增长,可能出现如下错误:
2019/06/16 08:37:35 [crit] 27744#0: *137027418 connect() to 10.140.2.47:443 failed (99: Cannot assign requested address) while connecting to upstream, client: 10.140.2.200, server: 0.0.0.0:9443, upstream: "10.140.2.47:443", bytes from/to client:0/0, bytes from/to upstream:0/0
如果并发数继续往上增长,可能出现如下错误:
2019/06/16 08:37:35 [crit] 27744#0: *137027418 connect() to 10.140.2.47:443 failed (99: Cannot assign requested address) while connecting to upstream, client: 10.140.2.200, server: 0.0.0.0:9443, upstream: "10.140.2.47:443", bytes from/to client:0/0, bytes from/to upstream:0/0
[!WARNING] 这里的端口耗尽,并不是指1-65535端口,而是socket五元组,如下
- 对于客户端访问nginx的连接来说
源IP和源端口都是随机的,目的IP(nginx本机IP)和目的端口(nginx本机服务端口)是固定的,这样理论上来说,是没有限制的
- 对于nginx访问upstream来说
源IP固定(nginx本机IP),源端口随机,目的IP和目的端口(upstream地址)需要看upstream的数量,总数就是6万随机端口乘以upstream的个数
如果upstream的个数很少,那就会出现端口耗尽,例如5个upstream地址,那么总数就是6万*5=30万(实际只有80-90%)大约25万
使用 “ss -n” 也发现确实是按照五元组使用的,例如下面的13958本机端口就是用了两次,产生了两个socket连接
ESTAB 0 0 172.28.4.173:13958 172.28.4.161:3000
ESTAB 0 0 172.28.4.173:13958 172.28.4.162:3000
ESTAB 0 0 172.28.4.173:13958 172.28.4.161:3000
ESTAB 0 0 172.28.4.173:13958 172.28.4.162:3000
- 那么如何解决端口耗尽的问题
一方面可以在upstream机器上增加IP地址或者端口,
另一方面也可以在nginx主机上增加IP地址,然后使用nginx的proxy_bind指定源地址
一方面可以在upstream机器上增加IP地址或者端口,
另一方面也可以在nginx主机上增加IP地址,然后使用nginx的proxy_bind指定源地址
2.5 系统内存
在操作系统层面每个TCP连接会占用3k-10k的内存,以20万来计算,需要2G内存。
nginx程序本身还要消耗内存,特别是nginx反向代理POST请求比较多的情况,20万连接情况下推荐16G内存配置
2.6 TCP连接会不会占用文件描述符
处在ESTABLISH状态的TCP连接,是会占用文件描述符的。而处在TIME_WAIT等非连接状态的TCP连接不会占用。
注意:CLOSE_WAIT状态也会占用文件描述符(losf)
2.6 关于TIME_WAIT数量过大会有什么影响
这个担心是多余的,我目前机器上TIME_WAIT数量在60万左右,tcp_max_tw_buckets 设置的是94万,由于TIME_WAIT占用内存很小,并且不占用文件描述符,目前没发现有什么问题。唯一需要担心的就是TIME_WAIT耗尽了nginx访问upstream时候的五元组,这个担心可以通过在nginx主机上增加IP地址解决(同端口耗尽)
这个担心是多余的,我目前机器上TIME_WAIT数量在60万左右,tcp_max_tw_buckets 设置的是94万,由于TIME_WAIT占用内存很小,并且不占用文件描述符,目前没发现有什么问题。唯一需要担心的就是TIME_WAIT耗尽了nginx访问upstream时候的五元组,这个担心可以通过在nginx主机上增加IP地址解决(同端口耗尽)