Linux - 服务器性能优化
Linux发行版本为 centos7.0
一、文件描述符上限调整
在linux系统中,每一个socket都要占用一个文件描述符。每一个文件描述符都需要占用一定的系统资源,鉴于内存资源有限,linux系统分别从三个层面上对能打开的文件描述符设了上限。
1、系统级。linux系统规定了整个系统文件描述符上限,也就是所有进程加起来能使用的文件描述符的上限。这个值可以通过 `cat /proc/sys/fs/file-max` 命令获取。这个值通常是由系统根据实际资源情况计算出的一个相对合理的建议值,但如果在/etc/sysctl.conf中配置过fs.file-max,则将显示配置的值。
系统最大打开文件描述符数:/proc/sys/fs/file-max 临时性设置:echo 1000000 > /proc/sys/fs/file-max 永久设置:修改/etc/sysctl.conf文件,增加 fs.file-max = 1000000 执行`sysctl -p`可立即生效
2、用户、进程级。使用ulimit -n查看当前设置。使用ulimit -n 1000000进行临时性设置。ulimit -n是设置当前shell的当前用户所有进程能打开的最大文件数量,
Provides control over the resources available to the shell and to processes started by it
但是一个用户可能会同时通过多个shell连接到系统,所以还有一个针对用户的限制,这个值可以通过文件/etc/security/limits.conf查看及修改:
* hard nofile 100000 * soft nofile 100000
注意的就是hard limit不能大于/proc/sys/fs/nr_open,因此有时你也需要修改nr_open的值。nr_open就是linux系统一个进程能够打开的最大文件描述符数量。
soft nproc :单个用户可用的最大进程数量(超过会警告);
hard nproc:单个用户可用的最大进程数量(超过会报错);
soft nofile :可打开的文件描述符的最大数(超过会警告);
hard nofile :可打开的文件描述符的最大数(超过会报错);
Linux 内核源码中有一个常量(NR_OPEN in /usr/include/linux/fs.h), 从系统源码层面限制了最大打开文件数, 多数linux默认设置nr_open是 1024k,也就是1048576,最大不能超过4096k,所以, 想要支持超过100k,还需要在/etc/sysctl.conf中重新上配置fs.nr_open的值,要想支持 C4000K, 你可能还需要重新编译内核。当然,因为默认nr_open是1024k,基本上能满足绝大多数应用场景,很多人在介绍高并发的时候,也可能没有注意到这个参数的存在。
所以,为了支持超过1024k的链接,同样需要把fs.nr_open设置超过1024k,方法同fs.file-max的修改:
echo "fs.nr_open=1100000" >> /etc/sysctl.conf 执行`sysctl -p`可立即生效
注意:/proc/sys/fs/file-max限制不了/etc/security/limits.conf
二、sysctl.conf文件
输入下面的组合命令,查看当前TCP连接的状态和对应的连接数量:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
这个命令会输出类似下面的结果:
LAST_ACK 16
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18098
我们只用关心TIME_WAIT的个数,在这里可以看到,有18000多个TIME_WAIT,这样就占用了18000多个端口。要知道端口的数量只有65535个,占用一个少一个,会严重的影响到后继的新连接。这种情况下,我们就有必要调整下Linux的TCP内核参数,让系统更快的释放TIME_WAIT连接。
用vim打开配置文件:#vim /etc/sysctl.conf
在这个文件中,加入下面的几行内容:
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 20
输入下面的命令,让内核参数生效:#sysctl -p
简单的说明上面的参数的含义:
net.ipv4.tcp_syncookies = 1
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout
#修改系統默认的 TIMEOUT 时间。
在经过这样的调整之后,除了会进一步提升服务器的负载能力之外,还能够防御小流量程度的DoS、CC和SYN攻击。
此外,如果你的连接数本身就很多,我们可以再优化一下TCP的可使用端口范围,进一步提升服务器的并发能力。依然是往上面的参数文件中,加入下面这些配置:
net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.ip_local_port_range = 10000 65000 net.ipv4.tcp_max_tw_buckets = 5000
#这几个参数,建议只在流量非常大的服务器上开启,会有显著的效果。一般的流量小的服务器上,没有必要去设置这几个参数。
net.ipv4.tcp_keepalive_time = 120
#如果在600秒内没有任何数据交互,则进行探测. 缺省值:7200(s)。缺省是2小时,改为2分钟。
net.ipv4.tcp_keepalive_intvl = 5
#探测时发探测包的时间间隔为5秒. 缺省值:75(s)
net.ipv4.tcp_keepalive_intvl = 3
#探测重试的次数. 全部超时则认定连接失效..缺省值:9(次)
net.ipv4.ip_local_port_range = 10000 65000
#表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。(注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!)
net.ipv4.tcp_max_tw_buckets = 6000
#表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默 认为180000,改为6000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT的最大数量,避免Squid服务器被大量的TIME_WAIT拖死。
内核其他TCP参数说明:
#记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216 #最大socket读buffer,可参考的优化值:873200
net.core.wmem_max = 16777216 #最大socket写buffer,可参考的优化值:873200
net.ipv4.tcp_timestsmps = 0
#时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。
net.ipv4.tcp_synack_retries = 2
#为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。
net.ipv4.tcp_syn_retries = 2
#在内核放弃建立连接之前发送SYN包的数量。
#net.ipv4.tcp_tw_len = 1
net.ipv4.tcp_wmem = 8192 436600 873200
# TCP写buffer,可参考的优化值: 8192 436600 873200
net.ipv4.tcp_rmem = 32768 436600 873200
# TCP读buffer,可参考的优化值: 32768 436600 873200
net.ipv4.tcp_mem = 94500000 91500000 92700000
# 同样有3个值,意思是:
net.ipv4.tcp_mem[0]:低于此值,TCP没有内存压力。
net.ipv4.tcp_mem[1]:在此值下,进入内存压力阶段。
net.ipv4.tcp_mem[2]:高于此值,TCP拒绝分配socket。
上述内存单位是页,而不是字节。可参考的优化值是:786432 1048576 1572864
net.ipv4.tcp_max_orphans = 3276800
#系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。
如果超过这个数字,连接将即刻被复位并打印出警告信息。
这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,
更应该增加这个值(如果增加了内存之后)。
三、Backlog
3.1 listen方法传入的backlog参数,net.core.somaxconn
#include <sys/socket.h> int listen(int sockfd, int backlog);
backlog的定义 int类型的backlog参数,listen方法的backlog意义为,已经完成三次握手、已经成功建立连接的套接字将要进入队列的长度。
Now it specifies the queue length for completely established sockets waiting to be accepted,instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using the tcp_max_syn_backlog sysctl. When syncookies are enabled there is no logical maximum length and this sysctl setting is ignored.
If the socket is of type AF_INET, and the backlog argument is greater than the constant SOMAXCONN(128 default), it is silently truncated to SOMAXCONN.
net.core.somaxconn 它是listen的第二个参数int backlog的上限值,全连接队列的最大长度:
backlog保存的是完成三次握手、等待accept的全连接,而不是半连接。
负载不高时,backlog不用太大。(For complete connections) 系统最大的、未处理的全连接数量为:min(backlog, somaxconn),net.core.somaxconn默认为128。
web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值,一般稍微增大net.core.somaxconn值就显得很有必要。设置其值方法:
sysctl -w net.core.somaxconn=65535
较大内存的Linux,65535数值一般就可以了。若让其生效,sysctl -p 即可,然后重启你的Server应用即可。或者:
net.core.somaxconn = 65535
比如经常使用的netty(4.0)框架,在Linux下启动时,会直接读取/proc/sys/net/core/somaxconn值然后作为listen的backlog参数进行调用Linux系统的listen进行初始化等。
int somaxconn = 3072; BufferedReader in = null; try { in = new BufferedReader(new FileReader("/proc/sys/net/core/somaxconn")); somaxconn = Integer.parseInt(in.readLine()); logger.debug("/proc/sys/net/core/somaxconn: {}", somaxconn); } catch (Exception e) { // Failed to get SOMAXCONN } finally { if (in != null) { try { in.close(); } catch (Exception e) { // Ignored. } } } SOMAXCONN = somaxconn; ...... private volatile int backlog = NetUtil.SOMAXCONN;
半连接队列的最大长度:
tcp_max_syn_backlog默认值为256。(For incomplete connections)当使用SYN Cookie时,这个参数变为无效。
net.ipv4.tcp_max_syn_backlog = 65535
3.2 网卡设备将请求放入队列的长度,netdev_max_backlog
内核代码中sysctl.c文件解释:number of unprocessed input packets before kernel starts dropping them, default 300
我所理解的含义,每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的最大数目,一旦超过将被丢弃。
net.core.netdev_max_backlog = 32768
#每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
四:总配置参数net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl = 5 net.ipv4.ip_local_port_range = 10000 65000 net.ipv4.tcp_max_tw_buckets = 5000 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_synack_retries=2 net.ipv4.tcp_syn_retries = 2 net.core.netdev_max_backlog = 65535 net.core.somaxconn=65535 fs.file-max=1000000
参考:
https://blog.csdn.net/aa2650/article/details/17027845
https://blog.csdn.net/bytxl/article/details/46408129
https://blog.csdn.net/mawming/article/details/51941771
Node版单机100w连接(C1000K)是如何达成的
https://www.jianshu.com/p/e0b52dc702d6
使用四种框架分别实现百万websocket常连接的服务器
https://colobu.com/2015/05/22/implement-C1000K-servers-by-spray-netty-undertow-and-node-js/
posted on 2018-08-04 11:37 TrustNature 阅读(153) 评论(0) 收藏 举报
浙公网安备 33010602011771号