4. 网络环境调优:TCP/IP参数调优、网卡多队列与巨型帧

吞吐测试里,网络环境经常是那个“看不见的瓶颈”。

你机器性能再强,网卡参数没调对,数据一样上不去。我见过太多团队,花大价钱买硬件,结果被几个内核参数卡死。说白了,网络调优就是让数据包走得快、走得稳。

这一章,咱们把TCP/IP参数、网卡多队列、巨型帧这三个核心点讲透。

4.1 TCP/IP参数调优:别让内核拖后腿

Linux内核默认的TCP参数,是为通用场景设计的。吞吐测试这种高并发、大流量的场景,必须手动调。我习惯先改这几个关键参数:

参数名 默认值 推荐值 作用
tcp_tw_reuse 0 1 允许将TIME_WAIT状态的socket用于新连接
tcp_fin_timeout 60 15-30 减少FIN_WAIT2状态的等待时间
tcp_tw_recycle 0 0(已废弃,不建议开启) 快速回收TIME_WAIT(NAT环境下有坑)
net.ipv4.ip_local_port_range 32768 60999 1024 65535 扩大可用端口范围
tcp_max_syn_backlog 128 65536 增大半连接队列长度

4.1.1 tcp_tw_reuse:复用TIME_WAIT连接

高并发场景下,客户端主动关闭连接后,会进入TIME_WAIT状态。默认要等2MSL(约60秒)才能释放。你想想看,每秒几万个请求,端口很快就耗尽了。

tcp_tw_reuse 允许内核在安全前提下,把TIME_WAIT状态的socket分配给新连接。我在压测短连接服务时,这个参数几乎是必开的。

核心逻辑: 开启后,内核会检查TIME_WAIT socket的时间戳,如果新连接的初始序列号比旧连接大,就直接复用。不会影响数据完整性。

4.1.2 tcp_fin_timeout:缩短FIN_WAIT2等待

这个参数控制的是被动关闭方进入FIN_WAIT2后的超时时间。默认60秒,太长了。我一般调到15秒,极端场景下调到5秒也行。

但要注意,调得太低可能导致正常慢速连接被误杀。嗯,这里要结合业务场景权衡。

避坑指南: 我曾经在NAT环境下误开了 tcp_tw_recycle,结果导致部分客户端连接失败。因为NAT后面多个客户端共享同一个公网IP,时间戳混乱。记住:tcp_tw_recycle 在Linux 4.12之后已被移除,别再用它。

4.1.3 其他关键参数

  • net.core.somaxconn:listen队列长度,默认128,建议调大到65535。
  • net.ipv4.tcp_keepalive_time:TCP保活探测间隔,默认7200秒,压测时可调小到300秒。
  • net.core.rmem_max / wmem_max:socket接收/发送缓冲区最大值,建议调大到16MB以上。

调优命令示例:

# 临时生效
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=15
sysctl -w net.ipv4.ip_local_port_range="1024 65535"

# 永久生效(写入/etc/sysctl.conf)
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_fin_timeout = 15" >> /etc/sysctl.conf
sysctl -p

4.2 网卡多队列配置:让CPU不再排队

传统网卡只有一个队列,所有中断都打到同一个CPU核心上。高吞吐时,那个核心直接跑满,其他核心在围观。说白了,就是资源浪费。

网卡多队列(RSS / RPS)把中断分散到多个CPU核心,实现并行处理。我测试过,开启多队列后,吞吐量能提升30%-50%。

4.2.1 检查当前队列数

# 查看网卡支持的最大队列数
ethtool -l eth0

# 查看当前生效的队列数
ethtool -g eth0

4.2.2 配置多队列

如果硬件支持,直接设置:

# 设置队列数为CPU核心数(假设是8核)
ethtool -L eth0 combined 8

硬件不支持?别急,用RPS(Receive Packet Steering)软件模拟:

# 为每个队列设置CPU亲和性
echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo "f" > /sys/class/net/eth0/queues/rx-1/rps_cpus

个人经验: 队列数最好等于物理CPU核心数,不要超过。超了反而因为上下文切换导致性能下降。我习惯用 lscpu 先确认核心拓扑。

4.3 巨型帧设置:一次多拉快跑

标准以太网帧最大1518字节,其中有效载荷只有1460字节左右。巨型帧(Jumbo Frame)把MTU提到9000字节,有效载荷能到8960字节。

你想想看,传输1GB数据,标准帧要拆成约68万个包,巨型帧只要约11万个。包头开销少了,CPU中断也少了。

4.3.1 设置方法

# 临时设置MTU为9000
ifconfig eth0 mtu 9000

# 永久设置(CentOS/RHEL)
echo "MTU=9000" >> /etc/sysconfig/network-scripts/ifcfg-eth0

# 永久设置(Ubuntu)
echo "mtu 9000" >> /etc/network/interfaces

4.3.2 注意事项

  • 全路径支持:从源端到目的端,所有交换机、路由器都必须支持巨型帧。我曾经在项目中只配了服务器端,结果中间交换机不支持,导致丢包严重。
  • 延迟敏感场景慎用:巨型帧会增加单包传输时间,对实时性要求高的场景(如高频交易)反而有害。
  • 测试方法:用 ping -M do -s 8972 测试路径MTU,如果通说明支持。

最佳实践: 内网吞吐测试,巨型帧几乎是必开的。但公网环境别用,互联网设备大多不支持。我一般在内网压测集群里统一设置MTU 9000,配合多队列和TCP参数调优,效果立竿见影。

4.4 知识体系总览

下面这张图,把本章三个核心模块的关系串起来了:

网络环境调优知识体系 网络环境调优核心模块 TCP/IP参数调优 网卡多队列配置 巨型帧设置 tcp_tw_reuse tcp_fin_timeout 端口范围 backlog队列 RSS硬件队列 RPS软件队列 CPU亲和性 MTU 9000 全路径支持 ping测试 调优效果对比(实测数据) • TCP参数调优 + 多队列 + 巨型帧:吞吐量提升 60% - 120% • 仅开启多队列:吞吐量提升 30% - 50% • 仅开启巨型帧:吞吐量提升 15% - 25%

4.5 调优验证:别光调不测

参数改完了,怎么知道有没有用?我一般用这三板斧:

  1. netstat -s:查看TCP重传率、丢包率。重传率超过0.1%就要警惕。
  2. sar -n DEV 1:实时监控网卡吞吐量和错误包。
  3. iperf3:双向打流测试,对比调优前后的吞吐差异。

我的习惯: 每次只改一个参数,测完再改下一个。这样出了问题能快速回滚。别一次性全改,否则出了问题你都不知道是哪个参数惹的祸。

网络调优不是玄学,是科学。参数摆在那里,效果测出来就知道。把这章的内容吃透,你的吞吐测试至少能少踩一半的坑。