龙空技术网

TCP/IP内核参数优化

寒笛过霜天 215

前言:

现在朋友们对“socket接收缓冲区最大值”大致比较关注,小伙伴们都需要分析一些“socket接收缓冲区最大值”的相关资讯。那么小编也在网摘上收集了一些有关“socket接收缓冲区最大值””的相关文章,希望同学们能喜欢,朋友们一起来学习一下吧!

/proc/sys/net目录

所有的TCP/IP参数都位于/proc/sys/net目录下(请注意, 对/proc/sys/net目录下内容的修改都是临时的, 任何修改在系统重启后都会丢失), 例如下面这些重要的参数:

参数(路径+文件) 描述 默认值 优化值

/proc/sys/net/core/rmem_default 默认的TCP数据接收窗口大小(字节)。 229376 256960

/proc/sys/net/core/rmem_max 最大的TCP数据接收窗口(字节)。 131071 513920

/proc/sys/net/core/wmem_default 默认的TCP数据发送窗口大小(字节)。 229376 256960

/proc/sys/net/core/wmem_max 最大的TCP数据发送窗口(字节)。 131071 513920

/proc/sys/net/core/netdev_max_backlog 在每个网络接口接收数据包的速率比内核处理这些包的速率快时, 允许送到队列的数据包的最大数目。 1000 2000

/proc/sys/net/core/somaxconn 定义了系统中每一个端口最大的监听队列的长度, 这是个全局的参数。 128 2048

/proc/sys/net/core/optmem_max 表示每个套接字所允许的最大缓冲区的大小。 20480 81920

/proc/sys/net/ipv4/tcp_mem 确定TCP栈应该如何反映内存使用, 每个值的单位都是内存页(通常是4KB)。第一个值是内存使用的下限; 第二个值是内存压力模式开始对缓冲区使用应用压力的上限; 第三个值是内存使用的上限。

在这个层次上可以将报文丢弃, 从而减少对内存的使用。对于较大的BDP可以增大这些值(注意, 其单位是内存页而不是字节)。 94011 125351 188022 131072 262144 524288

/proc/sys/net/ipv4/tcp_rmem 为自动调优定义socket使用的内存。第一个值是为socket接收缓冲区分配的最少字节数;第二个值是默认值(该值会被rmem_default覆盖), 缓冲区在系统负载不重的情况下可以增长到这个值;

第三个值是接收缓冲区空间的最大字节数(该值会被rmem_max覆盖)。 4096 87380 4011232 8760 256960 4088000

/proc/sys/net/ipv4/tcp_wmem 为自动调优定义socket使用的内存。第一个值是为socket发送缓冲区分配的最少字节数;

第二个值是默认值(该值会被wmem_default覆盖), 缓冲区在系统负载不重的情况下可以增长到这个值;

第三个值是发送缓冲区空间的最大字节数(该值会被wmem_max覆盖)。 4096 16384 4011232 8760 256960 4088000

/proc/sys/net/ipv4/tcp_keepalive_time TCP发送keepalive探测消息的间隔时间(秒), 用于确认TCP连接是否有效。 7200 1800

/proc/sys/net/ipv4/tcp_keepalive_intvl 探测消息未获得响应时, 重发该消息的间隔时间(秒)。 75 30

/proc/sys/net/ipv4/tcp_keepalive_probes 在认定TCP连接失效之前, 最多发送多少个keepalive探测消息。 9 3

/proc/sys/net/ipv4/tcp_sack 启用有选择的应答(1表示启用), 通过有选择地应答乱序接收到的报文来提高性能, 让发送者只发送丢失的报文段,

(对于广域网通信来说)这个选项应该启用, 但是会增加对CPU的占用。 1 1

/proc/sys/net/ipv4/tcp_fack 启用转发应答, 可以进行有选择应答(SACK)从而减少拥塞情况的发生, 这个选项也应该启用。 1 1

/proc/sys/net/ipv4/tcp_timestamps TCP时间戳(会在TCP包头增加12个字节), 以一种比重发超时更精确的方法(参考RFC 1323)来启用对RTT 的计算, 为实现更好的性能应该启用这个选项。 1 1

/proc/sys/net/ipv4/tcp_window_scaling 启用RFC 1323定义的window scaling, 要支持超过64KB的TCP窗口, 必须启用该值(1表示启用), TCP窗口最大至1GB, TCP连接双方都启用时才生效。 1 1

/proc/sys/net/ipv4/tcp_syncookies 表示是否打开TCP同步标签(syncookie), 内核必须打开了CONFIG_SYN_COOKIES项进行编译, 同步标签可以防止一个套接字在有过多试图连接到达时引起过载。 1 1

/proc/sys/net/ipv4/tcp_tw_reuse 表示是否允许将处于TIME-WAIT状态的socket(TIME-WAIT的端口)用于新的TCP连接 。 0 1

/proc/sys/net/ipv4/tcp_tw_recycle 能够更快地回收TIME-WAIT套接字。 0 1

/proc/sys/net/ipv4/tcp_fin_timeout 对于本端断开的socket连接, TCP保持在FIN-WAIT-2状态的时间(秒)。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。 60 30

/proc/sys/net/ipv4/ip_local_port_range 表示TCP/UDP协议允许使用的本地端口号 32768 61000 1024 65000

/proc/sys/net/ipv4/tcp_max_syn_backlog 对于还未获得对方确认的连接请求, 可保存在队列中的最大数目。如果服务器经常出现过载, 可以尝试增加这个数字。 2048 2048

/proc/sys/net/ipv4/tcp_low_latency 允许TCP/IP栈适应在高吞吐量情况下低延时的情况, 这个选项应该禁用。 0

/proc/sys/net/ipv4/tcp_westwood 启用发送者端的拥塞控制算法, 它可以维护对吞吐量的评估, 并试图对带宽的整体利用情况进行优化, 对于WAN 通信来说应该启用这个选项。 0

/proc/sys/net/ipv4/tcp_bic 为快速长距离网络启用Binary Increase Congestion, 这样可以更好地利用以GB速度进行操作的链接, 对于WAN通信应该启用这个选项。 1

net.core.rmem_default = 256960 # 默认的TCP数据接收窗口大小(字节)。默认值: 229376

net.core.rmem_max = 513920 # 最大的TCP数据接收窗口(字节)。默认值: 131071

net.core.wmem_default = 256960 # 默认的TCP数据发送窗口大小(字节)。默认值: 229376

net.core.wmem_max = 513920 # 最大的TCP数据发送窗口(字节)。默认值: 131071

net.core.netdev_max_backlog = 2000 # 在每个网络接口接收数据包的速率比内核处理这些包的速率快时, 允许送到队列的数据包的最大数目。 默认值: 1000

net.core.somaxconn = 2048 # 定义了系统中每一个端口最大的监听队列的长度, 这是个全局的参数。 默认值: 128

net.core.optmem_max = 81920 # 表示每个套接字所允许的最大缓冲区的大小。 默认值: 20480

net.ipv4.tcp_mem = 131072 262144 524288 # 确定TCP栈应该如何反映内存使用, 每个值的单位都是内存页(通常是4KB)。第一个值是内存使用的下限;第二个值是内存压力模式开始对缓冲区使用应用压力的上限;第三个值是内存使用的上限。在这个层次上可以将报文丢弃, 从而减少对内存的使用。对于较大的BDP可以增大这些值(注意, 其单位是内存页而不是字节)。 默认值: 94011 125351 188022

net.ipv4.tcp_rmem = 8760 256960 4088000 # 为自动调优定义socket使用的内存。第一个值是为socket接收缓冲区分配的最少字节数;第二个值是默认值(该值会被rmem_default覆盖), 缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是接收缓冲区空间的最大字节数(该值会被rmem_max覆盖)。 默认值: 4096 87380 4011232

net.ipv4.tcp_wmem = 8760 256960 4088000 # 为自动调优定义socket使用的内存。第一个值是为socket发送缓冲区分配的最少字节数;第二个值是默认值(该值会被wmem_default覆盖), 缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是发送缓冲区空间的最大字节数(该值会被wmem_max覆盖)。 默认值: 4096 16384 4011232

net.ipv4.tcp_keepalive_time = 1800 # TCP发送keepalive探测消息的间隔时间(秒), 用于确认TCP连接是否有效。

net.ipv4.tcp_keepalive_intvl = 30 # 探测消息未获得响应时,重发该消息的间隔时间(秒)。

net.ipv4.tcp_keepalive_probes = 3 # 在认定TCP连接失效之前, 最多发送多少个keepalive探测消息。

# net.ipv4.tcp_sack = 1 # 启用有选择的应答(1表示启用), 通过有选择地应答乱序接收到的报文来提高性能, 让发送者只发送丢失的报文段, (对于广域网通信来说)这个选项应该启用, 但是会增加对CPU的占用。 默认值: 1

# net.ipv4.tcp_fack = 1 # 启用转发应答, 可以进行有选择应答(SACK)从而减少拥塞情况的发生, 这个选项也应该启用。 默认值: 1

# net.ipv4.tcp_timestamps = 1 # TCP时间戳(会在TCP包头增加12个字节), 以一种比重发超时更精确的方法(参考RFC 1323)来启用对RTT 的计算, 为实现更好的性能应该启用这个选项。 默认值: 1

# net.ipv4.tcp_window_scaling = 1 # 启用RFC 1323定义的window scaling, 要支持超过64KB的TCP窗口, 必须启用该值(1表示启用), TCP窗口最大至1GB, TCP连接双方都启用时才生效。 默认值: 1

# net.ipv4.tcp_syncookies = 1 # 表示是否打开TCP同步标签(syncookie), 内核必须打开了CONFIG_SYN_COOKIES项进行编译, 同步标签可以防止一个套接字在有过多试图连接到达时引起过载。 默认值: 1

net.ipv4.tcp_tw_reuse = 1 # 表示是否允许将处于TIME-WAIT状态的socket(TIME-WAIT的端口)用于新的TCP连接 。 默认值: 0

# net.ipv4.tcp_tw_recycle = 1 # 能够更快地回收TIME-WAIT套接字。不推荐使用, ubuntu20.04 不支持此参数

net.ipv4.tcp_fin_timeout = 30 # 对于本端断开的socket连接, TCP保持在FIN-WAIT-2状态的时间(秒)。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。 默认值: 60

net.ipv4.ip_local_port_range = 1024 65000 # 表示TCP/UDP协议允许使用的本地端口号 默认值: 32768 61000

net.ipv4.tcp_max_syn_backlog = 2048 # 对于还未获得对方确认的连接请求, 可保存在队列中的最大数目。如果服务器经常出现过载, 可以尝试增加这个数字。 默认值: 2048

vim /etc/sysctl.conf

net.core.rmem_default = 256960

net.core.rmem_max = 513920

net.core.wmem_default = 256960

net.core.wmem_max = 513920

net.core.netdev_max_backlog = 2000

net.core.somaxconn = 2048

net.core.optmem_max = 81920

net.ipv4.tcp_mem = 131072 262144 524288

net.ipv4.tcp_rmem = 8760 256960 4088000

net.ipv4.tcp_wmem = 8760 256960 4088000

net.ipv4.tcp_keepalive_time = 1800

net.ipv4.tcp_keepalive_intvl = 30

net.ipv4.tcp_keepalive_probes = 3

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 30

net.ipv4.ip_local_port_range = 1024 65000

net.ipv4.tcp_max_syn_backlog = 2048

> # sysctl -p /etc/sysctl.conf

net.ipv4.tcp_tw_recycle = 1

启用TIME-WAIT状态sockets的快速回收, 这个选项不推荐启用。在NAT(Network Address Translation)网络下, 会导致大量的TCP连接建立错误。如果没有技术大神的指点的话, 千万不要去改动他, ubuntu20.04 不支持此参数。

查看当前系统下所有连接状态的数

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

ESTABLISHED 600

FIN_WAIT2 25

TIME_WAIT 14266

问题1: 查看队列溢出

root@miner:/home/milan# netstat -s |grep -i listen

60 SYNs to LISTEN sockets dropped

root@miner:/home/milan# ss -lnt

State Recv-Q Send-Q Local Address:Port Peer Address:Port Process

LISTEN 0 65535 202.10.42.5:2345 0.0.0.0:*

LISTEN 0 4096 0.0.0.0:111 0.0.0.0:*

LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*

LISTEN 0 128 0.0.0.0:22 0.0.0.0:*

LISTEN 0 65535 0.0.0.0:24001 0.0.0.0:*

LISTEN 0 4096 [::]:111 [::]:*

LISTEN 0 128 [::]:22

解决: 60 SYNs to LISTEN sockets dropped 队列溢出

内核调优

vim /etc/sysctl.conf

net.ipv4.tcp_syncookies=1 # Ubuntu20.04 默认值为1, 不需要设置

net.core.somaxconn=65535

net.ipv4.tcp_max_syn_backlog=262144

net.ipv4.tcp_abort_on_overflow=0 # Ubuntu20.04 默认值为0, 不需要设置

或者

echo 'net.ipv4.tcp_syncookies=1' | sudo tee -a /etc/sysctl.conf

echo 'net.core.somaxconn=65535' | sudo tee -a /etc/sysctl.conf

echo 'net.ipv4.tcp_max_syn_backlog=262144' | sudo tee -a /etc/sysctl.conf

echo 'net.ipv4.tcp_abort_on_overflow=0' | sudo tee -a /etc/sysctl.conf

参数详解:

绕开半连接队列

如果 SYN 半连接队列已满,可以开启 syncookies 功能,在不使用 SYN 队列的情况下也能建立连接, 默认值为1。

net.ipv4.tcp_syncookies=1

accept 队列

服务器收到 ACK 后表示连接建立成功, 此时内核会把连接从半连接队列中移出再移入 accept 队列, 等待进程调用 accept 函数时把连接取出来。

如果进程不能及时地调用 accept 函数, 就会造成 accept 队列溢出

net.core.somaxconn=65535

半连接队列长度

服务端状态在 SYN_RECV 下, 会建立一个 SYN 半连接队列来维护未完成的握手信息, 当这个队列溢出后, 服务器将无法再建立新连接。可以适当增加队列长度

net.ipv4.tcp_max_syn_backlog=262144

RST 复位

accept 队列溢出会导致建立好的 TCP 连接被丢弃。我们可以选择向客户端发送 RST 复位报文, 告诉客户端连接已经建立失败。通常会出现下面这两个错误 Connection reset/Connect reset by peer 默认值为0

net.ipv4.tcp_abort_on_overflow=0

注意: tcp_abort_on_overflow设置为0可以提高连接建立的成功率。当accept队列频繁溢出的时候, 才可以设置为1

查看默认值方法

cat /proc/sys/net/ipv4/tcp_syncookies

cat /proc/sys/net/core/somaxconn

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

cat /proc/sys/net/ipv4/tcp_abort_on_overflow

问题2: TIME_WAIT 过多

查看当前系统下所有连接状态的数

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

ESTABLISHED 600

FIN_WAIT2 25

TIME_WAIT 14266

ESTABLISHED 连接已建立

FIN_WAIT_2 套接字已关闭, 正在等待远程套接字关闭[在FIN_WAIT_1状态下收到发过去FIN对应的ACK]

TIME_WAIT 这个套接字已经关闭, 正在等待远程套接字的关闭传送[FIN、ACK、FIN、ACK都完毕, 这是主动方的最后一个状态, 在过了2MSL时间后变为CLOSED状态]

查询time_wait的数量

> # netstat -an | grep TIME_WAIT | wc -l

9506

cat /proc/sys/net/ipv4/ip_local_port_range

32768 60999

cat /proc/sys/net/ipv4/tcp_max_tw_buckets

解决 TIME_WAIT 过多

vim /etc/sysctl.conf

net.ipv4.ip_local_port_range=1024 65000

net.ipv4.tcp_max_tw_buckets=10000

net.ipv4.tcp_tw_reuse=1

net.ipv4.tcp_fin_timeout=10

sudo sysctl -p # 立即生效

参数详解:

# 用于外连的端口范围。(默认: 32768 到 60999)

net.ipv4.ip_local_port_range=1024 65000

# 当 TIME_WAIT 的连接数量超过 buckets, 新关闭的连接就不再经历 TIME_WAIT 而直接关闭

net.ipv4.tcp_max_tw_buckets=10000

# 允许 TIME_WAIT socket 重用。

net.ipv4.tcp_tw_reuse= 1

# FIN_WAIT 超时时间。

net.ipv4.tcp_fin_timeout=10

问题3: Connection reset by peer原因分析定位

net.ipv4.tcp_keepalive_time=1800

net.ipv4.tcp_keepalive_intvl=30

net.ipv4.tcp_keepalive_probes=5

tcp_keepalive_time, 在TCP保活打开的情况下, 最后一次数据交换到TCP发送第一个保活探测消息的时间, 即允许的持续空闲时间。默认值为7200s(2h)。

tcp_keepalive_intvl, 保活探测消息的发送频率。默认值为75s。

发送频率tcp_keepalive_intvl乘以发送次数tcp_keepalive_probes, 就得到了从开始探测直到放弃探测确定连接断开的时间, 大约为11min。

tcp_keepalive_probes, TCP发送保活探测消息以确定连接是否已断开的次数。默认值为9(次)。

标签: #socket接收缓冲区最大值