Linux服务器内核参数优化

       每次写日志,都要先搜索一番,开头怎么写。要装出很牛B的样子,让自己有优越感。这次QTMD的吧,技术人说话简单直接。之前在workman的群里看到一小哥,聊什么优化内核参数。我就想所谓内核参数优化,指什么呢?

所谓内核参数优化:linux系统中针对业务服务应用而进行的系统内核参数调整。

优化并无一定的标准。

1 最大文件数

我们常听说linux万物皆文件,一个连接要打开一个socket句柄文件。那么打开的文件句柄数(文件描述符),就一定程序上限制着我们的连接数。

1>  用户级限制 : 目标用户运行的所有进程总共能打开的文件描述符数

ulimit -n  默认是1024  这表示当前用户的每个进程最多允许同时打开1024个文件。

这1024个文件中还得除去每个进程必然打开的标准输入,

标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,

那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。

也就是说缺省情况下,基于Linux的通讯程序最多

允许同时1014个TCP并发连接)

临时修改 :max-file-number   

 ulimit -SHn max-file-number 

永久修改方法:

sudo vim /etc/security/limits.conf 

添加如下两行

* hard nofile max-file-number # 系统硬限制

* soft nofile max-file-number # 软限制

2> 系统级限制: 所有用户总共能打开的文件描述符数

查看最大  cat /proc/sys/fs/file-max

临时修改   sysctl -w fs.file-max=max-file-number

永久修改    在 /etc/sysctl.conf   fs.file-max=max-file-number

注意:以上需要执行sysctl -p 使更改生效

单个进程 打开的文件数

fs.nr_open 

NR_OPEN是一个进程可以打开的最大文件数

查看方法:

cat /proc/sys/fs/nr_open   1048576

sysctl -a  | grep fs.nr_open

修改方法:

sysctl -w fs.nr_open = 1048576

2 TCP连接数量

image.png

查看linux内核版本:uname -r。

半连接的数量:

tcp_max_syn_backlog  该参数决定了系统中处于 SYN_RECV 状态的 TCP 连接数量。SYN_RECV 状态指的是当系统收到 SYN 后,作了 SYN+ACK 响应后等待对方回复三次握手阶段中的最后一个 ACK 的阶段。

查看方法:

cat /proc/sys/net/ipv4/tcp_max_syn_backlog 256  

sysctl -a |grep net.ipv4.tcp_max_syn_backlog

修改方法:

sysctl -w net.ipv4.tcp_max_syn_backlog = 511

该参数定义了系统中每一个端口最大的监听队列的长度,是个全局参数。该参数和 net.ipv4.tcp_max_syn_backlog 有关联,后者指的是还在三次握手的半连接的上限,该参数指的是处于 ESTABLISHED 的数量上限。若您的业务负载很高,则有必要调高该参数。listen(2) 函数中的参数 backlog 同样是指明监听的端口处于 ESTABLISHED 的数量上限,当 backlog 大于 net.core.somaxconn时,以 net.core.somaxconn 参数为准。

超过这个数量就会看到connection refused。

查看方法:

cat /proc/sys/net/core/somaxconn  128

修改方法:

sysctl -w net.core.somaxconn =  511

上图可以看出来,somaxconn和tcp_max_syn_backlog 会选择两个当中比较小的那个来作为全连接的队列的长度。

这俩数值适当的调整(QPS=backlog),如果backlog过小(较小值),在大量并发连接的情况下,容易造成Accept_queue 溢出。 这个值php的fpm默认的是511 (listen.backlog = 511) ,nginx 也是默认511。

2 tcp缓冲区参数 

tcp发送缓冲区

cat /proc/sys/net/ipv4/tcp_wmem 

4096 16384 4194304

它包含3个值,分别指定一个socket的TCP写缓冲区的最小值,默认值和最大值。

可参考的优化值: 8192 436600 873200

发送缓冲区大小,理想数值是吞吐量 * 延迟,这样才可以达到最大网络利用率。

tcp接收缓冲区

/proc/sys/net/ipv4/tcp_rmem 它包含3个值,分别指定一个socket 的tcp读缓冲区的最小值,默认值 最大值  通过修改这个参数 可以改变接收 通告窗口的大小

tcp内存大小  

注意这里单位是页:一页=4kb=4096字节 

 cat /proc/sys/net/ipv4/tcp_mem

23604 31474 47208

low           press        high

low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。

pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。

high:允许所有tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出“TCP: too many of orphaned sockets”。(dmesg 可以看到)

tcp_syncookies

/proc/sys/net/ipv4/tcp_syncookies 指定是否打开TCP同步标签(syncookie),同步标签通过启动cookie来 自同一个地址的连接请求,而导致listen 监听队列溢出。

该参数表示是否打开 TCP 同步标签(SYN_COOKIES),内核必须开启并编译 CONFIG_SYN_COOKIES,SYN_COOKIES 可以防止一个套接字在有过多试图连接到达时引起过载。默认值 0 表示关闭。

当该参数被设置为 1 且 SYN_RECV 队列满了之后,内核会对 SYN 包的回复做一定的修改,即,在响应的 SYN+ACK 包中,初始的序列号是由源 IP + Port、目的 IP + Port 及时间这五个参数共同计算出一个值组成精心组装的 TCP 包。由于 ACK 包中确认的序列号并不是之前计算出的值,恶意攻击者无法响应或误判,而请求者会根据收到的 SYN+ACK 包做正确的响应。启用 net.ipv4.tcp_syncookies 后,会忽略 net.ipv4.tcp_max_syn_backlog。

tcp重试次数

cat /proc/sys/net/ipv4/tcp_syn_retries 5 次  该参数指明了处于 SYN_RECV 状态时重传 SYN+ACK 包的次数。  (每次超时重试时间为 2^n-1 秒)默认为5 减少重复次数,可以快速释放半连接。 修改为1或者2.

关闭 TCP 连接时,TCP 连接的两端都可以发起关闭连接的请求,若对端发起了关闭连接,但本地没有关闭连接,那么该连接就会处于 CLOSE_WAIT 状态。虽然该连接已经处于半开状态,但是已经无法和对端通信,需要及时的释放掉该链接

开启端口复用  这样,被 TIME_WAIT 状态占用的端口,还能用到新建的连接中。

net.ipv4.tcp_tw_reuse 

查看方式: 

sysctl -a |grep tcp_tw_reuse 默认是 0

修改方式

sysctl -w net.ipv4.tcp_tw_reuse = 1

 增大处于TIME_WAIT 状态的连接数量

 可以调整内核中管理 TIME_WAIT 状态的数量,当实例中处于 TIME_WAIT 及需要转换为 TIME_WAIT 状态连接数之和超过了 net.ipv4.tcp_max_tw_buckets 参数值时,message 日志将报错

message 日志中将报错 time wait bucket table,同时内核关闭超出参数值的部分 TCP 连接。您需要根据实际情况适当调高 net.ipv4.tcp_max_tw_buckets,同时从业务层面去改进 TCP 连接。

执行 netstat -ant|grep TIME_WAIT|wc -l 统计处于 TIME_WAIT 状态的 TCP 连接数

net.ipv4.tcp_max_tw_buckets :增大处于TIME_WAIT 状态的连接数量

sysctl -a |grep tcp_max_tw_buckets 查看方式,默认值是 4096

建议修改值:

sysctl -w net.ipv4.tcp_max_tw_buckets = 1048576

缩短处于FIN_WAIT_2 状态的时长。

HTTP 服务中,Server 由于某种原因会主动关闭连接,例如 KEEPALIVE 超时的情况下。作为主动关闭连接的 Server 就会进入 FIN_WAIT2 状态

TCP/IP 协议栈中,存在 半连接 的概念,FIN_WAIT2 状态不算做超时,如果 Client 不关闭,FIN_WAIT_2 状态将保持到系统重启,越来越多的 FIN_WAIT_2 状态会致使内核 Crash。

减少这个数值以便加快系统关闭处于 FIN_WAIT2 状态的 TCP 连接。

/proc/sys/net/ipv4/tcp_fin_timeout 默认60 建议设置30

配套配置的话

 net.ipv4.tcp_syncookies = 1

 net.ipv4.tcp_fin_timeout = 30

 net.ipv4.tcp_max_syn_backlog = 8192

 net.ipv4.tcp_max_tw_buckets = 5000

出现大量 CLOSE_WAIT 状态的 TCP 连接

关闭 TCP 连接时,TCP 连接的两端都可以发起关闭连接的请求,若对端发起了关闭连接,但本地没有关闭连接,那么该连接就会处于 CLOSE_WAIT 状态。虽然该连接已经处于半开状态,但是已经无法和对端通信,需要及时的释放掉该链接.

建议从业务层面及时判断某个连接是否已经被对端关闭,即在程序逻辑中对连接及时关闭检查。

解决思路

编程语言中对应的读、写函数一般包含了检测 CLOSE_WAIT TCP 连接功能,例如:

Java 语言:

通过 read 方法来判断 I/O 。当 read 方法返回 -1 时则表示已经到达末尾。

通过 close 方法关闭该链接。

C 语言:

检查 read 的返回值:

若等于 0 则可以关闭该连接。

若小于 0 则查看 errno,若不是 AGAIN 则同样可以关闭连接。

端口范围

cat /proc/sys/net/ipv4/ip_local_port_range  

32768   61000

表示TCP/UDP协议允许使用的本地端口号

因此新连接的本地端口将介于32768和61000之间,默认情况下28232个随机端口,看起来很多,但在繁忙的流量服务器的时候可能很容易达到这个限制。

增大本地端口范围,可以支持更多连接,提高整体的并发能力

增大本地端口的范围

sysctl -w net.ipv4.ip_local_port_range = "1024 65535"

KEEPALIVE

减少 Keepalive 探测失败后,一直到通知应用程序前的重试次数 

net.ipv4.tcp_keepalive_probes。

查看方法 sysctl -a |grep net.ipv4.tcp_keepalive_.*

net.ipv4.tcp_keepalive_intvl = 75 

net.ipv4.tcp_keepalive_probes = 9 //在这个连接被认为是断开之前,keep alive请求被重发的次数

sysctl -w net.ipv4.tcp_keepalive_probes=3;//建议修改值:3

net.ipv4.tcp_keepalive_time = 7200 // KeepAlive的空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2小时)  这个值在nginx配置中 keepalive_timeout 65;

默认65s

建议修改值:

net.ipv4.tcp_keepalive_intvl = 75 //:探测消息发送的频率,每75s发送一次。建议值 30

修改方法

sysctl -w net.ipv4.tcp_keepalive_intvl=30 //KeepAlive探测包的发送间隔,默认值为75s

net.ipv4.tcp_keepalive_time = 7200 //tcp 发送keepalive的消息频率 建议值600 

sysctl -w net.ipv4.tcp_keepalive_time=600

意思是如果某个TCP连接在idle 2个小时后,内核才发起probe.如果probe 9次(每次75秒)不成功,内核才彻底放弃,认为该连接已失效.对服务器而言,显然上述值太大。

网络层优化

ip_conntrack 是 Linux 系统内 NAT 的一个跟踪连接条目的模块。ip_conntrack 模块会使用一个哈希表记录 TCP 协议 established connection 记录,当这个哈希表满了的时候,便会导致 nf_conntrack: table full, dropping packet 错误,会出现网络连接丢包的问题。Linux 系统会开辟一个空间用来维护每一个 TCP 链接,这个空间的大小与 nf_conntrack_buckets、nf_conntrack_max 相关,后者的默认值是前者的 4 倍,而前者在系统启动后无法修改,所以一般都是建议调大 nf_conntrack_max

增大连接跟踪表的大小

net.netfilter.nf_conntrack_max 1048576

sysctl -w  net.netfilter.nf_conntrack_max=1048576

修改超时参数:net.netfilter.nf_conntrack_tcp_timeout_established = 1200 默认为432000秒 

1 开启ip转发

net.ipv4.ip_forward = 1

2 增大数据包的生存周期

sysctl -a |grep net.ipv4.ip_default_ttl 默认值是64,这个其实会降低系统性能

3  开启数据包的反向地址校验,防止IP欺骗,减少伪造IP带来的DDOS问题

net.ipv4.conf.eth0.rp_filter = 1

调整MTU

从分片角度出发,最主要的是调整MTU(maximum transmission unit)的大小

通常,MTU 的大小应该根据以太网的标准来设置。以太网标准规定,一个网络帧最大为 1518B,那么去掉以太网头部的 18B 后,剩余的 1500 就是以太网 MTU 的大小。

查看:cat /sys/class/net/eth0/mtu 默认是 1500

修改: echo "1450" > /sys/class/net/eth0/mtu

禁止 ICMP 协议

可以禁止 ICMP 协议,即设置 net.ipv4.icmp_echo_ignore_all = 1。这样,外部主机就无法通过 ICMP 来探测主机。

设置为1之后,再来ping会显示超时的。

或者,你还可以禁止广播 ICMP,即设置 net.ipv4.icmp_echo_ignore_broadcasts = 1。

可以避免 ICMP 主机探测、ICMP Flood 等各种网络问题

net.core.netdev_max_backlog

当内核处理速度比网卡接收速度慢时,这部分多出来的包就会被保存在网卡的接收队列上,而该参数说明了这个队列的数量上限。这个数值默认是1000.

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注