创建自己的百万并发服务器所遇到的问题,以及对Linux内核的理解
1.单机端口耗尽问题1.1 问题背景在初次压力测试中采用单客户端、单服务端的架构。当并发请求数达到约60,000时系统报错提示“无法建立网络连接”。1.2 原因分析TCP五元组约束连接由【源ip源端口目标ip目标端口协议】唯一确定由于刚开始是单服务器和单客服端的组合所以只有源端口可变受限于TCP协议16位端口号的定义2^{16} 65536扣除系统保留端口后单机并发上限为60000。1.3 解决方案横向扩展客户端通过部署多个客户端实例引入不同的源 IP 或利用多张网卡打破单机源端口的数量瓶颈。2. 高并发下的 OOM 与系统雪崩2.1 问题现象在多客户端环境下当服务端连接数达到90 万时其中一个客户端进程被系统强制杀掉Kill。观察发现客户端内存从 2.8 GB 飙升至 4.4 GB 后突然回落至 4.1 GB随后进程消失并引发服务端雪崩。2.2 深度分析TCP 缓冲区开销海量并发连接占用了大量的内核内存rmem/wmem 缓冲区。内核回收与 OOM Killer内存达到 4.4 GB 触发了内核的页面回收机制从 4.4 GB 降至 4.1 GB 是内核尝试释放缓存但仍无法满足分配需求。最终触发OOM Killer系统根据评分杀掉了内存占用最高的压测进程。雪崩效应客户端异常退出导致 90 万连接瞬间断开产生的FIN/RST洪水和资源回收压力直接击垮了服务端。3. 服务端内存管理优化 (分段式动态数组)3.1 传统设计的缺陷刚开始为了解决100万连接的问题我直接开了一个100万连接数的静态数组。静态大数组预分配 100 万长度的数组会造成巨大的连续物理内存浪费且不具备伸缩性。3.2 分页式管理方案为了兼顾性能与内存灵活性设计了分页式动态数组结构结构设计以1024为页容量采用多级索引或链表维护多个内存页。高效索引算法利用位运算或算术运算实现 $O(1)$ 定位页索引 (Page Index)fd / 1024(定位到具体的内存块)槽位索引 (Slot Index)fd % 1024(定位到块内偏移)优势实现了内存的按需分配避免了申请大块连续内存的压力同时保持了数组级的查询速度。最后把测试代码给上大家可以区测试一下