news 2026/9/3 22:05:10

深入解析主从Reactor多线程架构与epoll-ET模式:高并发网络服务的核心设计为什么epoll ET必须搭配非阻塞IO?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入解析主从Reactor多线程架构与epoll-ET模式:高并发网络服务的核心设计为什么epoll ET必须搭配非阻塞IO?

在高并发网络服务开发中,Reactor事件驱动思想是解决高并发IO问题的核心方法,配合Linux高性能IO多路复用epoll的ET模式,演进为主从Reactor多线程架构,构成了Muduo、大型网关、分布式服务的底层核心架构。今天来给大家讲讲这个主从Reactor架构+epoll-ET架构。

在Linux高并发网络编程领域,epoll是离不开的核心技术,主要是通过部分读部分写+epollET模式+阻塞非阻塞这三者来实现,先来详细讲讲这三者。

部分写部分读

read系统调用的流程为:进入内核态根据fd找到对应的文件对象,Linux读写文件几乎都走页缓存,不会直接碰磁盘,如果内核缓冲区有东西就直接用,没有东西才去磁盘读入内核缓冲区,接下来需要把数据从内核缓冲区拷贝到用户缓冲区,两块内存完全独立,一次能拷多少拷多少,这也是最需要注意的地方!read的部分读正是发生在内核缓冲区到用户buf这一步,原因是内核缓冲区和用户缓冲区大小限制,可能内核缓冲区数据不够读也可能内核缓冲区数据太多用户buf装不下。write也是一样。

epollET模式

epoll分为水平模式和边缘模式,水平模式LT简单来说就是缓冲区只要有数据就一直通知缓冲区可读或可写,边缘模式简单来说是在缓冲区状态变化的那一刻只通知一次。LT的时候就算出现部分写/部分读也没关系,下次还会通知,但是只要缓冲区状态满足内核就一直发事件,用户态/内核态切换频繁,开销大;ET由于内核只通知一次在高并发连接时比LT高效的多但是如果出现部分读没读完会出大问题!所以就引出了epollET模式的核心:循环读取!循环读取当read返回-1并且errno=EAGAIN/EWOULDBLOCK时说明内核缓冲区已经空了读完了。

阻塞+非阻塞

我们在实现高并发服务器时通常用epollET模式+非阻塞,接下来说说什么是阻塞什么是非阻塞:

阻塞就是当内核缓冲区为空的时候read不返回一直等待有数据可读了,非阻塞就是当读到内核缓冲区没有数据可读时直接返回-1不等待,阻塞和非阻塞的区别在哪?当内核缓冲区有数据的时候(不管数据够不够),行为完全一样,当内核缓冲区完全没有数据的时候二者非为等待和立刻返回。为什么说epollET模式必须搭配非阻塞fd使用?原因就在于我们要检查是否内核缓冲区已经空了,假如我们用阻塞fd,当内核缓冲区此刻为空read就不会返回了,ET+非阻塞=“卡死”,所以得用非阻塞fd,当检测到内核缓冲区为空的时候read返回-1并设置errno,只需要在while循环里检查errnobreak就可以了。

最后为大家赋上一小段核心代码:

void set_nonblock(int fd) {//设置fd为非阻塞 int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } while(1){ n = read(fd, buf, sizeof(buf)); if(n>0){ clients[fd].readbuf.append(buf, n); }else if(n==0){ close(fd); clients.erase(fd); del_epoll(fd, 0); return; }else { if(errno==EAGAIN||errno==EWOULDBLOCK){ break;//此刻内核缓冲区已经为空,读完了 }else{ close(fd); return; } } }

现在开始讲Reator,很多开发者会混淆epollReactor,epoll是系统调用,Reactor是一套事件驱动的设计思想。

Reactor核心思想

不轮询、不阻塞等待连接、由IO多路复用监听所有文件描述符,只在事件就绪的时候分发任务去处理。

核心载体是:epoll+ET,这是实现Reactor的关键工具,前面说的实现高并发服务器就是用Reactor思想。

主从Reactor架构

主线程也就是主Reactor只负责监听是否有客户端连接,只处理连接,不做读写业务处理,读写业务处理扔给子线程(子Reactor),主线程每处理一个新客户端连接事件后把客户端fd挂载到子线程的从Reactor,子线程有自己独立的epoll加事件循环,负责监听与处理已连接客户端fd的 可读 / 可写 / 异常事件。

整套服务器监听处理逻辑:

主线程epoll只注册listen_fd的ET读事件

当监听到有新客户端连接时,触发listen_fd的读事件

主线程拿到listen_fd设置为非阻塞

将新客户端fd挂载到某一个子线程

子线程内部epoll注册这个客户端fd,监听读事件

后续这个客户端的读写事件都由这个子Reactor处理

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 19:57:28

MKVToolNix v95.0 从入门到精通:无损合并视频与音轨字幕的终极指南

在视频剪辑和多媒体处理的工作流中,我们常常会遇到需要将多个视频片段、音轨或字幕文件合并成一个完整文件的需求。无论是制作个人Vlog、剪辑课程录像,还是处理从网上下载的分段视频,一款高效、稳定且功能强大的合并工具都至关重要。市面上此…

作者头像 李华
网站建设 2026/9/3 19:16:11

基于Python的车辆贷款违约预测实战:从特征工程到风控模型

简介:本资源是2021年科大讯飞主办的车辆贷款违约预测挑战赛的完整Python实现方案,面向金融风控方向的入门与进阶学习者,适用于课程设计、毕业设计、工程实训及算法竞赛备赛等场景。项目聚焦真实信贷业务中的逾期风险建模问题,提供…

作者头像 李华
网站建设 2026/9/1 8:27:20

Proteus仿真STM32:uC/OS-II任务调度与BLDC电机控制及12864显示实践

简介:面向STM32与Proteus开发者的直流无刷电机联合仿真资源,工程在Proteus 8.7中搭建,主控为STM32F103R6,移植μC/OS-II操作系统,通过MOS管驱动BLDC_STAR电机,并驱动AMPIRE128X64液晶屏显示,字库…

作者头像 李华
网站建设 2026/9/1 8:25:41

游戏手机稳定性实测指南:帧率、温控与功耗的评判标准

同价位游戏机谁更稳?iQOO Neo10 和 Z10 Turbo Pro 是两千元档里经常被放在一起比较的两台直屏机型,都有高刷屏,都强调游戏调度,价格又落在同一区间。可“稳”这个字在不同人口中含义完全不同:有人说的稳是长时间不掉帧…

作者头像 李华
网站建设 2026/9/3 19:42:26

SpringBoot+Vue构建企业经济效益评价系统:动态指标与计算引擎实战

1. 先搞清楚这个系统到底要解决什么问题 企业经济效益综合评价系统,听起来名字很大,但落到实际开发上,核心就一件事: 把一堆分散的财务、运营数据,通过一套固定的计算模型,变成一个可以横向、纵向比较的分…

作者头像 李华
网站建设 2026/9/3 20:16:21

基于MCP协议与IDA Pro构建安卓SO文件自动化逆向分析环境

在移动安全研究、漏洞挖掘和恶意软件分析领域,安卓应用的 so 动态链接库是核心战场。 so 文件承载了应用的核心算法、加密逻辑和关键业务功能,直接分析其二进制代码是理解应用行为、发现安全漏洞的必经之路。IDA Pro 作为业界标准的静态反汇编和调试…

作者头像 李华