
1. 项目概述单机百万TCP连接的意义与挑战在当今互联网服务架构中单机处理能力直接决定了服务的经济性和扩展性。我最近完成了一个极具挑战性的实验在Ubuntu系统上实现单机维持100万个TCP长连接。这个数字听起来可能有些抽象但举个例子——假设每个连接代表一个在线用户这意味着单台服务器就能支撑一个中型城市的全部网民同时在线聊天。从技术角度看突破百万连接主要面临三大难关文件描述符限制默认情况下Linux系统单个进程只能打开1024个文件内存消耗每个TCP连接至少消耗3-4KB内存百万连接就需要3-4GB纯连接内存网络协议栈优化传统内核参数是为千兆网络设计的需要针对性调优2. 基础环境搭建与初始测试2.1 硬件选型与系统配置我使用的测试环境配置如下CPU: Intel Xeon E5-2680 v4 2.40GHz (14核28线程) 内存: 64GB DDR4 ECC 网卡: Intel X550-T2 10G双端口 操作系统: Ubuntu 20.04 LTS (内核版本5.4.0-135-generic)选择这套配置主要考虑Xeon处理器的大缓存适合高并发场景10G网卡确保不会成为瓶颈ECC内存避免大数据量时内存错误2.2 初始基准测试未做任何优化前使用简单的epoll服务端程序测试系统在12万连接时出现明显问题# 错误日志示例 accept: Too many open files send: Connection reset by peer此时通过ss -s命令查看Total: 120321 (kernel 0) TCP: 120300 (estab 120000, closed 200, orphaned 0)3. 关键优化步骤详解3.1 突破文件描述符限制首先需要修改系统级和用户级限制# /etc/security/limits.conf 添加 * soft nofile 1048576 * hard nofile 1048576 # /etc/sysctl.conf 添加 fs.file-max 1048576 fs.nr_open 1048576然后修改应用程序的epoll初始化代码struct rlimit rlim; rlim.rlim_cur 1000000; rlim.rlim_max 1000000; setrlimit(RLIMIT_NOFILE, rlim);重要提示修改后必须重启系统才能生效仅重启服务无效3.2 TCP协议栈深度调优3.2.1 内存参数优化# /etc/sysctl.conf net.ipv4.tcp_mem 94500000 915000000 927000000 net.ipv4.tcp_rmem 4096 4096 16777216 net.ipv4.tcp_wmem 4096 4096 16777216这些值的计算依据tcp_mem三个值分别表示最低警戒值、压力模式阈值、最大内存限制按每个连接4KB计算100万连接需要约4GB考虑其他开销设置9GB上限3.2.2 连接状态参数net.ipv4.tcp_max_tw_buckets 1000000 net.ipv4.tcp_max_syn_backlog 8192 net.ipv4.tcp_synack_retries 1 net.ipv4.tcp_syncookies 13.2.3 端口复用配置net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_tw_recycle 0 # 在NAT环境下必须设为0 net.ipv4.ip_local_port_range 1024 655353.3 应用层优化技巧3.3.1 epoll使用模式选择采用EPOLLET边缘触发模式相比水平触发减少系统调用次数struct epoll_event ev; ev.events EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, ev);3.3.2 连接管理优化使用红黑树存储连接信息O(logN)复杂度查找心跳包采用时间轮算法避免遍历全部连接批量读写操作减少系统调用次数4. 性能监控与瓶颈分析4.1 关键监控指标实现百万连接后需要监控以下核心指标watch -n 1 cat /proc/net/sockstat echo --- cat /proc/meminfo | grep MemAvailable典型输出示例sockets: used 1002142 TCP: inuse 1000000 orphan 0 tw 0 alloc 1000001 mem 3245 --- MemAvailable: 58123456 kB4.2 常见瓶颈解决方案4.2.1 连接建立速度慢症状connect()调用耗时增加 解决方案net.ipv4.tcp_slow_start_after_idle 0 net.ipv4.tcp_abort_on_overflow 04.2.2 内存不足错误症状Cannot allocate memory错误 优化方案使用SO_REUSEPORT分散连接启用内存压缩sysctl vm.zone_reclaim_mode15. 实战经验与避坑指南5.1 必须避免的配置错误错误设置tcp_tw_recycle 在NAT环境下启用会导致随机连接失败过度限制TCP缓冲区 设置过小的rmem/wmem会导致吞吐量暴跌忽略swap配置 即使内存充足也应配置适量swapswapon --show # 确认swap状态5.2 性能压测技巧使用wrk进行真实负载测试wrk -t12 -c1000000 -d60s --timeout 2s http://127.0.0.1:8080参数说明-t: 线程数建议等于CPU核心数-c: 总连接数-d: 测试时长--timeout: 必须设置合理超时5.3 生产环境部署建议分级启动连接 不要瞬间建立百万连接按批次启动for i in range(0, 1000000, 50000): start_connections(i, i50000) time.sleep(10)监控指标阈值内存使用率 70% 触发告警单CPU核心使用率 80% 持续5分钟告警连接保持策略心跳间隔建议30-60秒超时时间设为心跳间隔的3倍6. 性能对比数据优化前后关键指标对比指标优化前(12万连接)优化后(100万连接)内存占用1.2GB3.8GBCPU利用率(epoll)15%68%连接建立耗时(p99)850ms120ms网络吞吐800Mbps9.2Gbps异常断开率0.3%0.02%这个优化过程让我深刻体会到Linux网络栈的强大可塑性。通过合理的参数调整和架构设计单机百万连接不再是理论值而是可以落地的实用方案。在实际部署时建议先从小规模测试开始逐步验证各项参数的适用性。