Workerman TCP性能瓶颈90%源于sysctl缓冲区参数未配对:net.core.rmem_max和net.core.wmem_max必须≥tcp_rmem/tcp_wmem第三值,且需开启tcp_window_scaling=1,否则自动扩窗失效;建议设rmem_max/wmem_max≥4194304(4MB),tcp_rmem="4096 65536 4194304",并同步调大somaxconn、启用tw_reuse等。

Workerman 的 TCP 性能瓶颈,90% 不在代码里,而在 sysctl.conf 里没配对缓冲区参数,尤其是被 net.core.rmem_max 和 net.core.wmem_max 卡死了。
查清当前缓冲区真实上限,别信默认值
Workerman 是长连接服务,依赖内核自动扩窗(tcp_rmem/tcp_wmem 的第三项),但这个“最大值”会被 net.core.rmem_max 和 net.core.wmem_max 截断——如果后者更小,前者的最大值就形同虚设。
- 运行
sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem net.core.rmem_max net.core.wmem_max,对比四组数值 - 重点看
net.core.rmem_max是否 ≥tcp_rmem的第三个值(最大接收缓冲区);同理检查发送侧 - 用
ss -i dst <client_ip>查单个连接的rcv_space和snd_space,如果长期卡在 256KB 或 512KB,说明被截断了
Workerman 场景下该设多少才合理
Workerman 常用于 IM、实时推送等长连接服务,典型特征是连接数多、单连接持续时间长、小包高频交互。盲目堆大缓冲区反而增加延迟、浪费内存。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 先估算带宽延迟积(BDP):例如上行 1Gbps + RTT 2ms → BDP ≈ 250KB;实际建议设为 BDP 的 1.2–1.5 倍,即 300–400KB
-
net.core.rmem_max和net.core.wmem_max至少设为4194304(4MB),给自动扩窗留足空间 -
net.ipv4.tcp_rmem推荐设为4096 65536 4194304(最小 4KB、默认 64KB、最大 4MB);tcp_wmem同理,可略低些如4096 32768 4194304 - 必须开启
net.ipv4.tcp_window_scaling=1,否则窗口无法突破 64KB
Workerman 还要同步调的几个关键参数
光调缓冲区不够,Workerman 的连接生命周期管理、队列堆积、保活机制都得跟上,否则缓冲区再大也白搭。
- 增大监听队列:
net.core.somaxconn = 65535(避免listen drops) - 扩大半连接队列:
net.ipv4.tcp_max_syn_backlog = 65535 - 启用 TIME_WAIT 复用:
net.ipv4.tcp_tw_reuse = 1+net.ipv4.tcp_timestamps = 1(短连接突发时防端口枯竭) - 开保活防止中间设备静默断连:
net.ipv4.tcp_keepalive_time = 600、net.ipv4.tcp_keepalive_intvl = 75、net.ipv4.tcp_keepalive_probes = 9 - 禁用空闲慢启动:
net.ipv4.tcp_slow_start_after_idle = 0(长连接静默后重传不降速)
改完必须验证,别只改不看效果
Workerman 启动后,仅靠 sysctl -p 成功不代表生效——很多参数被应用层 socket 选项覆盖,或被网卡驱动限制。
- 用
ss -i state established | head -20看多个连接的rcv_space/snd_space是否真涨到你设的上限附近 - 检查
netstat -s | grep -i "listen.*drops\|packet.*drop",确认没有队列溢出 - Workerman 进程若用了
setsockopt(SO_RCVBUF)固定缓冲区大小,会绕过内核自动调节,此时tcp_rmem设置无效 - 高并发下注意
net.core.netdev_max_backlog(网卡收包队列)是否够用,否则丢包发生在更底层
最容易被忽略的是:所有缓冲区参数调整后,ss -i 显示的 rcv_space 没变化,大概率是 net.core.rmem_max 比你设的 tcp_rmem 最大值还小,或者 tcp_window_scaling 关着——这两点不验,调半天也是白调。

















