
目录一.前言1.目标2.边界说明二.i/o模型1.阻塞i/o简介特点2.非阻塞i/o简介特点3.信号驱动i/o简介特点4.异步i/o简介特点5.多路转接i/o简介特点三.高并发服务器设计1.架构模型选择主从 Reactor 多线程模型核心架构2.设计初衷与解决的痛点为什么要引入多 Reactor 模式为什么要引入线程池3.扩展一.前言1.目标深入剖析常见的网络 I/O 模型底层原理此为基础设计出高并发、高性能的网络服务器。2.边界说明本篇内容聚焦于操作系统层面的用户态与内核态交互重点分析系统调用、进程调度与缓冲区管理暂不展开讨论网卡 DMA、硬中断等底层硬件细节。二.i/o模型1.阻塞i/o简介这是 Linux 系统中最基础、最传统的 I/O 模型。一次完整的输入或输出操作通常包含两个核心阶段等待数据就绪和数据拷贝。在阻塞 I/O 模型中调用进程在这两个阶段都会被迫挂起交出 CPU 控制权。特点代码逻辑呈纯线性顺序执行符合人类直觉开发与维护成本极低。非忙轮询进程会被挂载到等待队列不消耗 CPU 算力。直到对应的 I/O 事件真正就绪内核才会唤醒该进程继续执行。由于由于无需引入额外的事件监听和分发机制其系统调用链路最短面对单连接环境具有极致的性能和低延迟。由于存在多次阻塞执行速度完全受制于外部网络延迟、对端处理速度若要支持高并发只能采用“one thread one loop”模式线程多次切换导致开销暴涨性能低下。2.非阻塞i/o简介发起系统调用时如果内核缓冲区中的数据尚未就绪系统调用不会挂起当前进程而是立即返回一个特定的错误码用户还可以继续调用。相比于阻塞i/o在等待数据就绪阶段不再阻塞但数据拷贝阶段依然阻塞执行。特点轮流探测多个连接不会因为某个连接没有输入而被彻底死锁挂起可以实现低连接并发服务但面对高并发环境吞吐极差延时极高。等待数据间隙交替执行各种任务提升利用率。但忙轮询状态严重消耗CPU容易造成CPU空转等情况。3.信号驱动i/o简介利用内核信号机制通知数据就绪的模型预先注册信号处理函数数据准备完毕后发送信号触发信号信号回调处理执行数据拷贝操作。特点避免了非阻塞 I/O 中高频调用带来的 CPU 空转与内核态/用户态频繁切换开销。但信号产生、传递以及处理仍然具有较高成本并且存在信号机制带来的延迟。单线程可专心处理计算密集型任务无需显式管理轮询循环。4.异步i/o简介遵循“通知完成”机制用户进程向操作系统发起读写请求并直接把目标缓冲区地址和大小交给内核然后调用立即返回内核在后台自主完成等待数据与将数据拷贝到用户缓冲区这两个阶段全部搞定后才通知应用程序直接消费数据。相比于上面两种i/o等待数据就绪与数据拷贝阶段都不会阻塞。特点用户进程完全摆脱了所有阻塞等待可以做到单核心百万级的高并发。架构复杂代码维护成本高。5.多路转接i/o简介单线程下依赖操作系统内核同时监控多个文件描述符的就绪状态。当描述符准备好读写事件时不会优先读写而是根据接口返回做判断对事件就继续的文件描述符发起真正的读写操作。特点单线程/单进程即可高效管理数以万计甚至数十万的长连接但不适合长时间计算或死循环会降低系统响应速率等拖垮事件循环上的所有连接。三.高并发服务器设计1.架构模型选择主从 Reactor 多线程模型核心架构基于 I/O 多路复用技术采用“主从 Reactor 工作线程池”的组合设计。主反应堆专职监听服务端端口集中处理所有新客户端的连接请求并将建立好的连接分配给 Sub Reactor。从反应堆接管已被分配的连接监听这些文件描述符的读写事件负责真正的 I/O 数据接收与发送。工作线程池负责接收 Sub Reactor 读取到的数据进行协议解析、业务计算与逻辑处理最后将结果交回给 Sub Reactor 发送。2.设计初衷与解决的痛点为什么要引入多 Reactor 模式在单 Reactor 模式下接收新连接accept和处理存量连接的 I/O 读写共用同一个事件循环。当面临瞬时高并发的连接洪峰时如果 Reactor 恰好正在处理其他连接的大量 I/O 操作就会来不及执行accept。这会导致操作系统的全连接队列迅速溢出进而造成大量新客户端的连接请求被内核直接丢弃。多 Reactor 模式可以将“连接建立”与“数据读写”彻底物理隔离Main Reactor 可以极速地响应建连请求保障了服务器在极端突发流量下的高并发接入能力。为什么要引入线程池如果业务处理逻辑复杂或包含耗时操作直接在 Reactor 线程中执行会“卡死”整条流水线。这会导致其他成百上千个已经就绪的网络事件被迫排队等待引发整体系统响应的高延迟甚至假死。线程池可将重度的业务计算剥离到后台线程池执行让从反应堆继续监听和搬运下一波网络数据完美保障了网络 I/O 层的高吞吐与极低延迟。3.扩展针对网络异常或断电情况下导致的大量死连接可扩展时间轮、心跳等机制定期检查连接活跃度剔除超时未响应的存量连接保障系统资源的良性循环。对线程池业务处理频繁可修改底层内存分配机制如ptmalloc替换成tcmalloc或直接预分配足够大小的内存络收发时循环复用实现“零分配”开销。