
“凌晨两点,流量洪峰突然飙到 120 K QPS。”
这是我在香港新建的撮合撮合交易平台第一次遇到的“砸站”现场——业务层面毫无异常,Linux 内核却频繁抛出 tcp: time wait bucket table overflow。平均 RTT 抬升一倍,订单撮合延迟从 2 ms 飙到 20 ms,服务器依旧有空闲 CPU,却跑不出带宽。为彻底解决这个瓶颈,我花了整整三天两夜,结合网络栈理论与实测数据,对 Linux 内核参数 与 TCP 连接数配置 做了系统级调优,最终把单机并发处理能力提升了 3.4 ×。本文完整复盘这段实战流程,力求每一步都有可复现的配置与量化指标,供各位同样部署在香港节点、面临跨境高并发流量的同仁参考。
1. 环境与基准线
| 组件 | 版本 / 规格 |
|---|---|
| 物理机 | A5数据 HK-EPYC 9554 × 1、DDR5 256 GB、Samsung PM9A3 NVMe 1.6 TB |
| 内核 | 6.8.9 (自编译,开启 BPF & BBR3) |
| OS | AlmaLinux 9.4 |
| NIC | Intel E810-XXV 25 GbE,开启 RSS/RPS/XDP |
| 业务模型 | gRPC + HTTP/2,4 K 长连接 / 微服务 Pod |
基准压测结果(wrk2,8 × 客户端,均衡到单机)
- 最大吞吐:146 k req/s
- 95 th 延迟:18.7 ms
- CPU 利用率:58 %
- 显示大量 TCP: out_of_window packets 与 TIME_WAIT overflow
2. 瓶颈诊断思路
- 队列耗尽:net.ipv4.tcp_max_syn_backlog 与 net.core.somaxconn 默认仅 128 / 4096,远小于实际并发。
- TIME_WAIT 风暴:跨境短连流导致 TIME_WAIT 表溢出,占用端口与内存。
- 发送/接收缓冲不足:25 GbE 带宽下默认 rmem_default/wmem_default 只有 128 KiB。
- 拥塞控制与调度器不匹配:CUBIC + fq_codel 在高 RTT 场景回收过慢。
- ephemeral port 枯竭:net.ipv4.ip_local_port_range 过窄(32768–60999)。
3. 内核参数调优
以下所有参数放入 /etc/sysctl.d/99-hk-tcp-tuning.conf,并即时 sysctl -p。调整后需重启网络栈或重启机器才能让 XDP/RSS 全量生效。
# 3.1 队列容量
net.core.somaxconn = 131072
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_syncookies = 1 # 防半开消耗
# 3.2 缓冲区大小 (单位 Byte)
net.core.rmem_default = 1048576 # 1 MiB
net.core.wmem_default = 1048576
net.core.rmem_max = 16777216 # 16 MiB
net.core.wmem_max = 16777216
# 3.3 吞吐相关
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_mtu_probing = 1 # 自动探测 MSS
# 3.4 TIME_WAIT 优化
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1 # 仅在内核>=5.10 安全可用
net.ipv4.tcp_tw_recycle = 0 # 已废弃,勿启
# 3.5 端口与散列
net.ipv4.ip_local_port_range = 1024 65000
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
# 3.6 拥塞控制 & 队列算法
net.core.default_qdisc = fq # 配合 BBR3
net.ipv4.tcp_congestion_control = bbr
内核 6.8+ 的 BBR3 在高 BDP 场景效果显著;如果仍使用 5.x,可退回 BBR v2。
4. 提高用户态并发上限
4.1 ulimit 及 systemd Overrides
# /etc/security/limits.d/99-nofile.conf
* soft nofile 1048576
* hard nofile 1048576
# /etc/systemd/system/myservice.service.d/override.conf
[Service]
LimitNOFILE=1048576
重载后 systemctl daemon-reload && systemctl restart myservice.
4.2 EPOLL 负载均衡
- 确保业务使用 EPOLLEXCLUSIVE 接口 (Linux 4.5+) 避免惊群。
- 多实例时在同一核绑定 SO_REUSEPORT 提升 LSQ 分片。
5. NIC 队列与 CPU 亲和
- RSS:为 25 GbE 分配 16 queues (ethtool -L <iface> combined 16)。
- IRQ 亲和:irqbalance –oneshot 或手动写 /proc/irq/*/smp_affinity_list 把队列绑到对应 NUMA 节点。
- RPS/RFS:
echo 16 > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
6. 快速回收 TIME_WAIT
高 QPS 场景常被 TIME_WAIT 吞噬端口,我的做法:
- 优先长连接:gRPC/HTTP-keepalive 默认 30 s;压测发现改成 120 s 总吞吐最高;
- 端口复用:启用 SO_REUSEPORT + net.ipv4.tcp_tw_reuse=1;
- 低延迟 FIN:tcp_fin_timeout=10 足以保证对端收到 ACK。
7. 验证与监控
| 指标 | 调优前 | 调优后 |
|---|---|---|
| 峰值吞吐 | 146 k req/s | 500 k req/s |
| 95 th 延迟 | 18.7 ms | 5.4 ms |
| TIME_WAIT 数 | ~580 k | 52 k |
| CPU 利用率 | 58 % | 82 %(网络栈饱和率更高,业务仍余裕) |
工具链
- ss -s: 监控连接状态
- bpftrace -e ‘kprobe:tcp_v4_connect { @[comm] = count(); }’
- perf top -e cycles -C <cpu-list>:确保热点在 XDP/BBR,而非软中断抢占
8. 常见坑 & 排错手册
| 现象 | 排查要点 |
|---|---|
大量 TCP: time wait bucket table overflow |
nf_conntrack_tcp_timeout_time_wait 未同步,或业务未启长连接 |
| 吞吐上不去,CPU 仍闲 | 检查 NIC 队列映射 / ethtool -S <iface> 中的 rx_no_buffer、xdp_drop |
| BBR RTT 波动大 | 升级到内核 ≥ 6.8,或临时切换到 cubic 并打开 fq_codel |
端口耗尽 (bind: address in use) |
扩大 ip_local_port_range,或使用 PROXY 协议下的多源 IP |
我经过上述系统级调优,把香港节点在跨境高并发流量下的吞吐能力提升到了 原来的 3.4 倍,并确保延迟稳定在亚毫秒级别。更重要的是,这套参数已在后续五次“双十一”流量洪峰中反复验证,较少需要频繁手动干预。如果你也在运营面向全球的实时业务,不妨动手试试——只有深入理解 Linux 网络栈,才能真正把硬件潜力榨干。
Tips:调优永远是动态过程。建议将关键参数写入 Git 并绑定 CI,在每次新内核或新业务上线时自动压测、对比并回滚。这样才能让“最佳实践”真正落地,而不只是贴在 Wiki 上的老配方。











