Linux基础之-高并发内核优化

前言

在默认参数情况下Linux对高并发支持并不好,主要受限于单进程最大打开文件数限制、内核TCP参数方面和IO事件分配机制等。下面就从几方面来调整使Linux系统能够支持高并发环境

单进程最大打开文件数限制

一般的发行版,限制单进程最大可以打开1024个文件,这是远远不能满足高并发需求的,调整过程如下:
在#号提示符下敲入:

[root@localhost ~]$ ulimit –n 65535
将root启动的单一进程的最大可打开的文件数设为65535个。如果系统回显类似于“Operationnotpermitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,需修改Linux系统对用户的关于打开文件数的软限制和硬限制。

第一步,修改limits.conf文件,并添加:

[root@localhost ~]$ vim /etc/security/limits.conf
root            soft    nofile          1024000
root            hard    nofile          1024000
root            soft    nproc           1024000
root            hard    nproc           1024000
*               soft    nofile          1024000
*               hard    nofile          1024000
*               soft    nproc           1024000

其中’*'号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;65536则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。

第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

[root@localhost ~]$ vim /etc/pam.d/login
sessionrequired /lib/security/pam_limits.so

第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

[root@localhost ~]$ cat /proc/sys/fs/file-max
1048575

表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)1048575个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过该数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出的最佳的最大同时打开文件数限制,如无特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改 /etc/sysctl.conf 文件内fs.file-max= 1048575这是让Linux在启动完成后强行将系统级打开文件数硬限制设为1048575。

内核TCP参数方面

Linux系统下,TCP连接断开后,会以 TIME_WAIT 状态保留一定时间,然后才释放端口。当并发请求过多时,会产生大量 TIME_WAIT 状态连接,无法及时断开会占用大量的端口资源和服务器资源。这时可优化TCP内核参数,及时将TIME_WAIT状态的端口清理掉。

下面方法只对大量 TIME_WAIT 状态的连接导致系统资源消耗有效,如不是这种情况,效果可能不明显。可用 netstat 命令查 TIME_WAIT 状态,输入下面命令,

查看当前TCP连接的状态和对应的连接数量:

[root@localhost ~]$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

#这个命令会输出类似下面的结果:

LAST_ACK 16
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT 1229
FIN_WAIT 230
CLOSING 33
TIME_WAIT 18098

只用关心 TIME_WAIT 个数,看到有18000多个 TIME_WAIT,这就占了18000多个端口。端口数量只有65535个,占一个少一个,严重影响到新连接。这时,有必要调整下Linux的TCP内核参数,让系统更快的释放TIME_WAIT连接。

编辑配置文件:/etc/sysctl.conf,在这个文件中,加入下面几行内容:

vim /etc/sysctl.conf

net.ipv4.tcp_syncookies= 1	#开启SYNCookies。当SYN等待队列溢出时,启用cookies处理,可防范少量SYN攻击,默认0,表关闭;
net.ipv4.tcp_tw_reuse= 1	#开启重用。允许将TIME-WAITsockets重用于新的TCP连接,默认0,表示关闭;
net.ipv4.tcp_tw_recycle= 1	#开启TCP连接中TIME-WAITsockets的快速回收,默认0,表关闭;
net.ipv4.tcp_fin_timeout= 30	#修改系統默认的 TIMEOUT 时间。

#输入下面的命令,让内核参数生效:
sysctl -p

经过这样调整后,除进一步提升服务器的负载能力外,还能防御小流量程度的DoS、CC和SYN攻击。

此外,如果连接数本身就很多,可再优化TCP 的可用端口范围,进一步提升服务器的并发能力。依然是往上面的参数文件中,加入下面配置:

net.ipv4.tcp_keepalive_time= 1200	#当keepalive起用时,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range= 1024 65535	#用于向外连接的端口范围。缺省情况下很小,改为1024到65535。
net.ipv4.tcp_max_syn_backlog= 8192	#SYN队列长度,默认为1024,加大队列长度为8192,可容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets= 5000	#表示系统同时保持TIME_WAIT最大数量,如果超过,TIME_WAIT将立刻被清除并打印警告信息。默认180000,改为5000。此项参数可控制TIME_WAIT 最大数量。

这几个参数,建议在流量非常大的服务器上开启,会有显著效果。一般的流量小的服务器上,没必要去设这几个参数。

内核其他TCP参数说明

net.ipv4.tcp_max_syn_backlog= 65536		#记录尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存系统则是128。
net.core.netdev_max_backlog= 32768		#每个网络接口接收数据包的速率比内核处理的速率快时,允许送到队列的数据包的最大数目。
net.core.somaxconn= 32768		#如web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而 nginx 定义的 NGX_LISTEN_BACKLOG 默认511,所以有必要调整这个值。
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_tw_reuse= 1		#开启重用。允许将TIME-WAITsockets重用于新TCP连接。
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。
#上述内存单位是页,而不是字节。可参考优化值是:7864321048576 1572864

net.ipv4.tcp_max_orphans= 3276800
#系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上,如超过,连接将即刻被复位并打印警告信息,这个限制仅是为防止简单的DoS攻击,不能过分依靠它或人为减小这个值,更应该增加这个值(如果增加内存后)。

net.ipv4.tcp_fin_timeout= 30
#如果套接字由本端要求关闭,这个参数决定它保持在FIN-WAIT-2状态的时间。对端可出错并永不关闭连接,甚至意外当机。缺省值是60秒。2.2 内核的通常值是180秒,你可以按这个设置,但即使是个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN-WAIT-2 的危险性比FIN-WAIT-1 小,因为它最多只能吃掉1.5K内存,但它们的生存期长些。

同时还涉及到 TCP 拥塞算法问题,可用下面命令查看本机的拥塞算法控制模块:

sysctl net.ipv4.tcp_available_congestion_control
#对于几种算法的分析,详情参考下:TCP拥塞控制算法的优缺点、适用环境、性能分析,如高延时可以试用hybla,中等延时可以试用htcp算法等。

net.ipv4.tcp_congestion_control=hybla	#如果想设置TCP 拥塞算法为hybla
net.ipv4.tcp_fastopen= 3	#额外的,对于内核版高于3.7.1,可开启tcp_fastopen

sysctl.conf 可优化参数如下:

fs.file-max = 2097152
# 减少交换内存使用,默认60,建议10-30
vm.swappiness = 0
# 脏数据的比例和处理,根据场景不同设置,
# 参考 https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
# 如果是数据库服务器,希望数据能够尽快安全写入,可降低内存缓存比例
# vm.dirty_background_ratio = 5
# vm.dirty_ratio = 10

# 如果是业务服务器,对数据安全写入无要求,可加大内存缓存比例
# vm.dirty_background_ratio = 50
# vm.dirty_ratio = 80
 
# 设置为1,内核允许分配所有的物理内存,Redis常用
vm.overcommit_memory = 1
# 系统拥有的内存数,ElasticSearch启动必备
vm.max_map_count = 262144
# 设置为1
net.ipv4.tcp_no_metrics_save = 1
# 禁用 sysrq 功能
kernel.sysrq = 0
# 控制 core 文件的文件名中是否添加 pid 作为扩展
kernel.core_uses_pid = 1
# 设置为1,防止 SYNC FLOOD 攻击
net.ipv4.tcp_syncookies = 1
# 消息队列的最大消息大小,默认8k,建议64kb
kernel.msgmax = 65536
# 消息队列存放消息的总字节数
kernel.msgmnb = 163840 
# TIME_WAIT socket的最大数目,不宜太大或者太小,nginx反向代理必备
net.ipv4.tcp_max_tw_buckets = 50000
# 打开 SACK 选项,设置为1
net.ipv4.tcp_sack = 1
# 激活窗口扩充因子,支持64kb以上数据传输
net.ipv4.tcp_window_scaling = 1
# TCP 缓冲区内存,连接数达到非常高时候需要配置好
net.ipv4.tcp_mem = 786432 2097152 3145728  
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
# socket缓冲区默认值和最大值
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# ACCEPT等待队列长度,适当,太大了堆积也无用 
net.core.netdev_max_backlog = 65535
# 允许最大并发连接数,重要
net.core.somaxconn = 65535
# 不属于任何进程的socket数目,不宜太大,防止攻击
net.ipv4.tcp_max_orphans = 65535
# SYNC等待队列长度,适当,太大了排队也没用
net.ipv4.tcp_max_syn_backlog = 65535
# 禁用timestamp,重要,高并发下设置为0
net.ipv4.tcp_timestamps = 0
# 发送 SYNC+ACK 的重试次数,不宜太大,5以内
net.ipv4.tcp_synack_retries = 1
# 发送SYNC的重试次数,不宜太大,5以内
net.ipv4.tcp_syn_retries = 1
# 允许回收TCP连接,重要,必须为1
net.ipv4.tcp_tw_recycle = 1 
# 允许重用TCP连接,重要,必须为1
net.ipv4.tcp_tw_reuse = 1 
# 服务端主动关闭后,客户端释放连接的超时,重要,<30
net.ipv4.tcp_fin_timeout = 5 
# 允许TCP保持的空闲keepalive时长,不需要太长
net.ipv4.tcp_keepalive_time = 30 
# 系统作为TCP客户端连接自动使用的端口(start,end),可发起并发连接数为end-start
net.ipv4.ip_local_port_range = 10240 65535
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值