
1. 项目背景与挑战去年在做一个物联网消息推送服务时我们遇到了单机TCP连接数的瓶颈。当时使用的Ubuntu 18.04服务器在连接数达到12万左右时新连接就开始大量失败。经过两周的调优最终实现了单机100万TCP连接的稳定保持。这个过程中积累的经验值得分享给面临类似挑战的同行。2. 基础环境准备2.1 硬件配置选择我们使用了戴尔R740xd服务器配置如下CPU: 2颗Intel Xeon Gold 6248R (24核48线程)内存: 384GB DDR4网卡: Mellanox ConnectX-5 25Gbps * 2存储: Intel P4510 2TB NVMe * 2关键点网卡的选择至关重要。普通千兆网卡在50万连接时就会出现严重瓶颈建议至少使用10Gbps及以上带宽的优质网卡。2.2 操作系统优化安装Ubuntu 20.04 LTS Server版并进行以下基础优化# 关闭不必要的服务 sudo systemctl disable --now avahi-daemon cups chrony # 调整内核参数 echo fs.file-max 2097152 | sudo tee -a /etc/sysctl.conf echo net.ipv4.ip_local_port_range 1024 65535 | sudo tee -a /etc/sysctl.conf echo net.ipv4.tcp_tw_reuse 1 | sudo tee -a /etc/sysctl.conf sudo sysctl -p3. TCP协议栈深度调优3.1 关键内核参数解析在/etc/sysctl.conf中添加以下参数# 最大文件描述符数 fs.file-max 2097152 # TCP内存分配 net.ipv4.tcp_mem 8388608 12582912 16777216 net.ipv4.tcp_rmem 4096 87380 16777216 net.ipv4.tcp_wmem 4096 65536 16777216 # TCP连接回收 net.ipv4.tcp_fin_timeout 30 net.ipv4.tcp_max_tw_buckets 2000000 # 连接跟踪 net.netfilter.nf_conntrack_max 1048576参数说明tcp_mem三个值分别表示最小压力、中等压力、最大压力时的内存分配增大tcp_rmem/wmem可以提升大并发下的吞吐量调整fin_timeout可以加速连接回收3.2 中断亲和性优化对于多队列网卡需要正确配置中断亲和性# 查看中断分布 cat /proc/interrupts | grep eth # 设置CPU亲和性 sudo apt install irqbalance sudo systemctl enable --now irqbalance4. 应用层优化策略4.1 连接管理架构我们采用了多线程epoll模型关键设计点主线程负责accept新连接每个工作线程管理约5万连接使用SO_REUSEPORT实现端口复用示例代码片段int sockfd socket(AF_INET, SOCK_STREAM, 0); int optval 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, optval, sizeof(optval)); setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, optval, sizeof(optval));4.2 内存管理技巧为每个连接预分配读写缓冲区使用内存池避免频繁malloc/free禁用透明大页(THP)echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled5. 压测方法与结果5.1 测试工具选型我们使用了自己开发的压测工具主要特点支持分布式发起连接可模拟真实心跳包交互提供详细的连接状态统计也可以使用wrk2进行基础测试wrk -t12 -c1000000 -d60s --latency http://target:80805.2 性能指标监控关键监控项及工具连接数ss -s内存使用free -hCPU负载top -H网络流量iftop6. 典型问题与解决方案6.1 连接建立失败症状达到12万连接后无法建立新连接 排查检查ulimit -n查看dmesg是否有OOM日志检查nf_conntrack是否满解决方案echo 1048576 /proc/sys/net/netfilter/nf_conntrack_max6.2 吞吐量下降症状连接数增加后吞吐显著降低 可能原因网卡中断集中在单个CPU内存带宽瓶颈TCP缓冲区不足优化方法# 调整网卡多队列 ethtool -L eth0 combined 327. 进阶优化方向当连接数超过50万后还需要考虑使用DPDK绕过内核协议栈采用RSS(Receive Side Scaling)技术优化NUMA内存访问考虑使用Kernel bypass技术在实际测试中我们发现每个TCP连接在空闲状态下约占用3KB内存。因此100万连接至少需要3GB内存专门用于连接维护这还不包括应用层的内存需求。