Skip to content

查看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地址解决(同端口耗尽)

tcp