常识一:文件句柄限制
在linux下编写网络服务器程序的朋友肯定都知道每一个tcp连接都要占一个文件描述符,一旦这个文件描述符使用完了,新的连接到来返回给我们的错误是“Socket/File:Can't open so many files”。
这时你需要明白操作系统对可以打开的最大文件数的限制。
常识二:端口号范围限制?
操作系统上端口号1024以下是系统保留的,从1024-65535是用户使用的。由于每个TCP连接都要占一个端口号,所以我们最多可以有60000多个并发连接。我想有这种错误思路朋友不在少数吧?(其中我过去就一直这么认为)
我们来分析一下吧
如何标识一个TCP连接:系统用一个4四元组来唯一标识一个TCP连接:{local ip, local port,remote ip,remote port}。好吧,我们拿出《UNIX网络编程:卷一》第四章中对accept的讲解来看看概念性的东西,第二个参数cliaddr代表了客户端的ip地址和端口号。而我们作为服务端实际只使用了bind时这一个端口,说明端口号65535并不是并发量的限制。
server最大tcp连接数:server通常固定在某个本地端口上监听,等待client的连接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,即使server端有多个ip,本地监听端口也是独占的,因此server端tcp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。
一、系统层面
进程限制
执行 ulimit -n 输出 1024,说明对于一个进程而言最多只能打开1024个文件,所以你要采用此默认配置最多也就可以并发上千个TCP连接。
1、临时调整同时打开文件数量
但是这种临时修改只对当前登录用户目前的使用环境有效,系统重启或用户退出后就会失效
ulimit -SHn 1000000
永久生效:修改/etc/security/limits.conf 尾部修改: 重启后生效
* soft nproc 11000
* hard nproc 11000
* soft nofile 655350
* hard nofile 655350
ulimit -SHn 1000000 >> /etc/rc.local
"soft" 和 "hard" 的区别
soft xxx : 代表警告的设定,可以超过这个设定值,但是超过后会有警告。
hard xxx : 代表严格的设定,不允许超过这个设定的值。
如:soft 设为1024,hard设为2048 ,则当你使用数在1~1024之间时可以随便使用,1024~2048时会出现警告信息,大于2048时,就会报错。
"nproc" 和 "nofile"的区别
nproc : 是操作系统级别对每个用户创建的进程数的限制
nofile : 是每个进程可以打开的文件数的限制
设置限制数量,第一列表示用户,* 表示所有用户
soft nproc :单个用户可用的最大进程数量(超过会警告);
hard nproc:单个用户可用的最大进程数量(超过会报错);
soft nofile :可打开的文件描述符的最大数(超过会警告);
hard nofile :可打开的文件描述符的最大数(超过会报错);
注:①一般soft的值会比hard小,也可相等。
②/etc/security/limits.d/里面配置会覆盖/etc/security/limits.conf的配置
③只有root用户才有权限修改/etc/security/limits.conf
④如果limits.conf没有做设定,则默认值是1024
2、TCP最大连接数(somaxconn) 重启后失效
echo 10000 > /proc/sys/net/core/somaxconn
kern.ipc.somaxconn
3、TCP连接立即回收、回用(recycle、reuse)重启后失效;如需要永久生效,请在 /etc/sysctl.conf中修改
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
4、不做TCP洪水抵御,重启后失效;如需要永久生效,请在 /etc/sysctl.conf中修改
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
5、进程可以同时打开的最大句柄数
这个参数表示进程可以同时打开的最大句柄数,这个参数直接限制最大并发连接数
fs.file-max = 1000000
执行 cat /proc/sys/fs/file-nr 输出 9344 0 592026,分别为:
1.已经分配的文件句柄数,
2.已经分配但没有使用的文件句柄数,
3.最大文件句柄数。
但在kernel 2.6版本中第二项的值总为0,这并不是一个错误,它实际上意味着已经分配的文件描述符无一浪费的都已经被使用了 。
我们可以把这个数值改大些
以上2~5点永久生效均需 /etc/sysctl.conf 文件修改:
以下是参照网上现有的一些优化方案
fs.file-max = 1000000
# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and
# sysctl.conf(5) for more details.
#
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
#
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
#
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
#
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
#
# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1
#
# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1
#
# Disable netfilter on bridges.
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
#
# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65536
#
# Controls the default maxmimum size of a mesage queue
kernel.msgmax = 65536
#
# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736
#
# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296
#
# #syncookie
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
#
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
#
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
#
#time_wait
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 1
#
#修改系統默认的TIMEOUT时间
net.ipv4.tcp_fin_timeout = 5
net.ipv4.tcp_tw_reuse = 1
#
#time wait 最高的队列数
net.ipv4.tcp_max_tw_buckets = 5000
#
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.ip_local_port_range = 1024 65535
#
net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15
保存后执行sysctl -p使配置生效
sysctl -p
sysctl文件说明 https://blog.youkuaiyun.com/sqlquan/article/details/106235700
二、nginx层面
nginx详细优化配置:http://blog.chinaunix.net/uid-25266990-id-2985541.html?=1785233200
修改nginx配置文件,nginx.conf
增加work_rlimit_nofile和worker_connections数量,并禁用keepalive_timeout。
worker_processes 8;//nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数。
//worker_rlimit_nofile 102400;
这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文
件数(ulimit -n)与nginx 进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
events {
use epoll;//使用epoll 的I/O 模型
worker_connections 102400;
//每个进程允许的最多连接数,
理论上每台nginx 服务器的最大连接数为worker_processes*worker_connections。
multi_accept on;
}
http {
keepalive_timeout 0;
}
重启nginx
/usr/local/nginx/sbin/nginx -s reload
参考:
https://blog.youkuaiyun.com/weixin_34064653/article/details/85746370
https://www.cnblogs.com/sunjianguo/p/8298283.html