Reactor 反应堆模式实战:从原理到代码,打造高并发网络服务架构

        在高并发网络编程中,传统的 “一连接一线程” 模型会因线程过多导致资源耗尽,而 Reactor 模式通过 “事件驱动 + IO 多路转接”,让单线程(或少量线程)高效处理数千甚至数万连接,成为 Nginx、Redis 等高性能中间件的核心架构。本文将以 “网络计算器” 为案例,从 Reactor 模式的核心思想入手,拆解 Connection 管理、事件分发、业务处理的完整流程,结合实战代码讲解如何基于 epoll 实现 Reactor 模式,帮你掌握高并发服务的设计精髓。

一、Reactor 模式核心认知:什么是反应堆?

        Reactor 模式的本质是 “事件驱动的异步 IO 架构”,它通过一个 “反应堆”(Reactor 核心)统一管理所有 IO 事件,当事件就绪时(如 socket 可读、可写),自动分发到对应的业务处理逻辑,避免主动轮询或线程阻塞。

1.1 核心思想:“反向调用”

传统 IO 模型中,应用程序主动调用 IO 函数(如read/write)并阻塞等待;Reactor 模式则相反:

        应用程序将 “IO 事件” 和 “处理逻辑” 注册到 Reactor;

        Reactor 通过 IO 多路转接(如 epoll)监控事件;

        事件就绪时,Reactor 主动调用注册的处理逻辑(回调函数),即 “反向调用”。

1.2 关键组件

一个完整的 Reactor 架构包含 4 个核心组件,协同实现事件驱动:

组件功能示例(本文实现)
Reactor 核心管理 IO 多路转接(epoll),监控事件,分发事件到处理器TcpServer类(封装 epoll 操作)
事件处理器注册事件和回调函数,处理具体 IO 事件(如读、写、异常)HandlerConnection类(处理读写逻辑)
连接管理器管理客户端连接(创建、销毁、存储),维护连接的缓冲区和状态Connection类(封装 socket、缓冲区、回调)
** acceptor**处理新连接请求(监听 socket 的可读事件),创建新连接并注册到 ReactorAccepter类(accept 新连接,初始化 Connection)

二、Reactor 模式工作流程:事件驱动的完整闭环

Reactor 模式的工作流程可概括为 “注册事件→监控事件→分发事件→处理事件”,以 “网络计算器” 为例,完整流程如下:

  1. 初始化 Reactor:创建 epoll 实例,初始化监听 socket,将 “监听事件(EPOLLIN)” 和 “新连接处理逻辑” 注册到 Reactor;
  2. 等待事件就绪:Reactor 调用epoll_wait,阻塞等待事件(如新连接请求、客户端数据到达);
  3. 新连接处理
    • 监听 socket 就绪,Accepter调用accept创建新 socket,设置为非阻塞;
    • 创建Connection对象(封装新 socket、缓冲区、回调函数),将 “读事件(EPOLLIN|EPOLLET)” 注册到 epoll;
  4. 客户端数据处理
    • 客户端 socket 可读,Reactor 触发 “读回调”,读取数据到Connection的输入缓冲区;
    • 解析输入缓冲区中的完整协议报文(解粘包),调用业务逻辑(计算表达式);
    • 将计算结果写入Connection的输出缓冲区,注册 “写事件(EPOLLOUT)”;
  5. 结果发送
    • 客户端 socket 可写,Reactor 触发 “写回调”,将输出缓冲区数据发送给客户端;
    • 若数据发送完毕,取消写事件注册;若未发送完,保留写事件监听;
  6. 异常处理:若连接出错(如客户端关闭),触发 “异常回调”,销毁Connection并从 epoll 中移除。

三、核心组件设计与实现

        基于 Reactor 模式,我们将系统拆分为Connection(连接封装)、Accepter(新连接处理)、HandlerConnection(业务逻辑)、TcpServer(Reactor 核心)四个组件,以下逐一讲解设计细节。

3.1 Connection:连接的 “全能封装器”

  Connection类是 Reactor 模式的 “最小业务单元”,它封装了 socket、输入 / 输出缓冲区、事件状态和回调函数,统一管理单个连接的生命周期。

3.1.1 核心功能

        封装 socket 文件描述符,管理连接的打开与关闭;

        维护输入缓冲区(_inbuffer)和输出缓冲区(_outbuffer),处理数据的接收与发送;

        注册回调函数(读、写、异常),关联业务处理逻辑;

        记录连接的事件状态(如关心的 epoll 事件)和客户端地址(IP + 端口)。

3.1.2 实战代码(Connection.hpp)
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 前向声明,避免循环引用
class TcpServer;

// 回调函数类型:接收、发送、异常处理(参数为Connection指针)
using func_t = std::function<void(Connection*)>;

class Connection {
public:
    // 构造:初始化socket、关心的事件、关联的TcpServer
    Connection(int sockfd, uint32_t events, TcpServer* reactor)
        : _sockfd(sockfd), _events(events), _R(reactor) {}

    // 注册回调函数(读、写、异常)
    void RegisterCallback(func_t recver, func_t sender, func_t excepter) {
        _recver = recver;
        _sender = sender;
        _excepter = excepter;
    }

    // 输入缓冲区操作:追加数据(接收数据时用)
    void AddInBuffer(const std::string& buffer) {
        _inbuffer += buffer;
    }

    // 输出缓冲区操作:追加数据(发送数据时用)
    void AddOutBuffer(const std::string& buffer) {
        _outbuffer += buffer;
    }

    // 检查输出缓冲区是否为空(判断是否需要注册写事件)
    bool OutBufferEmpty() const {
        return _outbuffer.empty();
    }

    // 获取socket文件描述符(供epoll操作)
    int SockFd() const {
        return _sockfd;
    }

    // 获取/设置关心的epoll事件(如EPOLLIN、EPOLLOUT)
    uint32_t Events() const {
        return _events;
    }
    void SetEvents(uint32_t events) {
        _events = events;
    }

    // 设置客户端地址(IP+端口)
    void SetClient(const struct sockaddr_in& client) {
        _client = client;
    }

    // 获取输入/输出缓冲区(供业务逻辑读写)
    std::string& InBuffer() {
        return _inbuffer;
    }
    std::string& OutBuffer() {
        return _outbuffer;
    }

    // 关闭连接(释放socket)
    void Close() {
        ::close(_sockfd);
    }

    ~Connection() = default;

public:
    // 回调函数:由HandlerConnection实现
    func_t _recver;   // 读事件回调
    func_t _sender;   // 写事件回调
    func_t _excepter; // 异常事件回调
    TcpServer* _R;    // 回指Reactor核心(TcpServer),用于操作epoll

private:
    int _sockfd;                  // 连接对应的socket文件描述符
    std::string _inbuffer;        // 输入缓冲区(存储客户端发送的数据)
    std::string _outbuffer;       // 输出缓冲区(存储待发送给客户端的数据)
    uint32_t _events;             // 关心的epoll事件(如EPOLLIN|EPOLLET)
    struct sockaddr_in _client;   // 客户端地址(IP+端口)
};

// Connection工厂类:统一创建连接(工厂模式,简化对象创建)
class ConnectionFactory {
public:
    // 创建监听连接(监听socket专用)
    static Connection* BuildListenConnection(int listensock, func_t recver, uint32_t events, TcpServer* reactor) {
        Connection* conn = new Connection(listensock, events, reactor);
        conn->RegisterCallback(recver, nullptr, nullptr); // 监听连接仅需读回调
        return conn;
    }

    // 创建普通客户端连接(新连接专用)
    static Connection* BuildNormalConnection(int sockfd, func_t recver, func_t sender, func_t excepter, uint32_t events, TcpServer* reactor) {
        Connection* conn = new Connection(sockfd, events, reactor);
        conn->RegisterCallback(recver, sender, excepter); // 普通连接需读、写、异常回调
        return conn;
    }
};

3.2 Accepter:新连接的 “守门人”

Accepter类专门处理 “新连接请求”—— 当监听 socket(listensock)可读时,它通过accept创建新 socket,初始化Connection并注册到 Reactor,是连接进入系统的 “入口”。

3.2.1 核心逻辑

        监听 socket 就绪时,Accepter循环调用accept(非阻塞模式,避免漏接连接);

        新 socket 设置为非阻塞(配合 epoll 的 ET 模式);

        通过ConnectionFactory创建普通连接,注册 “读回调、写回调、异常回调”;

        将新连接添加到 Reactor 的连接管理列表,并注册读事件到 epoll。

3.2.2 实战代码(Accepter.hpp)
#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cerrno>
#include "Connection.hpp"
#include "HandlerConnection.hpp"
#include "Log.hpp" // 简化日志,可自行实现

// 设置socket为非阻塞(ET模式必需)
void SetNonBlock(int sockfd) {
    int fl = fcntl(sockfd, F_GETFL);
    if (fl < 0) {
        perror("fcntl F_GETFL");
        return;
    }
    fcntl(sockfd, F_SETFL, fl | O_NONBLOCK);
}

class Accepter {
public:
    // 处理新连接(参数为监听连接的Connection)
    void AccepterConnection(Connection* listen_conn) {
        errno = 0;
        // 循环accept,避免漏接(ET模式下监听socket可读可能有多个连接)
        while (true) {
            struct sockaddr_in client_addr;
            socklen_t client_len = sizeof(client_addr);
            // 非阻塞accept(因listensock已设为非阻塞)
            int new_sockfd = ::accept(listen_conn->SockFd(), (struct sockaddr*)&client_addr, &client_len);
            
            if (new_sockfd > 0) {
                lg.LogMessage(Info, "new connection accepted, sockfd: %d", new_sockfd);
                // 1. 设置新socket为非阻塞
                SetNonBlock(new_sockfd);

                // 2. 绑定业务回调(读、写、异常由HandlerConnection实现)
                auto recver = std::bind(&HandlerConnection::Recver, std::placeholders::_1);
                auto sender = std::bind(&HandlerConnection::Sender, std::placeholders::_1);
                auto excepter = std::bind(&HandlerConnection::Excepter, std::placeholders::_1);

                // 3. 创建普通连接(ET模式,关心读事件)
                Connection* new_conn = ConnectionFactory::BuildNormalConnection(
                    new_sockfd, recver, sender, excepter, EPOLLIN | EPOLLET, listen_conn->_R
                );
                new_conn->SetClient(client_addr); // 记录客户端地址

                // 4. 将新连接添加到Reactor(注册epoll事件)
                listen_conn->_R->AddConnection(new_conn);
            } else {
                // 处理accept错误:EAGAIN表示无更多连接,EINTR表示被信号中断
                if (errno == EAGAIN) break;       // 正常退出循环
                else if (errno == EINTR) continue; // 重试
                else {
                    lg.LogMessage(Warning, "accept failed, errno: %d", errno);
                    break;
                }
            }
        }
    }

    ~Accepter() = default;
};

3.3 HandlerConnection:业务逻辑的 “执行者”

HandlerConnection类是 Reactor 模式的 “业务处理中心”,它实现了 “读、写、异常” 三大回调函数,负责将 IO 事件转化为具体业务逻辑(如解析协议、计算表达式、发送结果)。

3.3.1 核心功能
  1. Recver(读回调):从 socket 读取数据到输入缓冲区,调用HandlerRequest解析协议并处理业务;
  2. Sender(写回调):将输出缓冲区数据发送到 socket,根据发送结果决定是否保留写事件;
  3. Excepter(异常回调):处理连接异常(如客户端关闭),销毁连接并从 Reactor 中移除;
  4. HandlerRequest(业务处理):解析输入缓冲区中的完整协议报文,调用计算器业务,生成响应并写入输出缓冲区。
3.3.2 依赖组件

        Protocol:自定义应用层协议(参考前文 “应用层自定义协议”,实现Encode/Decode解粘包);

        Calculate:网络计算器业务类(实现表达式计算,如 “1+1”→“2”)。

3.3.3 实战代码(HandlerConnection.hpp)
#pragma once
#include <iostream>
#include <cerrno>
#include <string>
#include "Connection.hpp"
#include "Protocol.hpp" // 自定义协议:Encode/Decode解粘包
#include "Calculate.hpp" // 计算器业务:处理表达式计算
#include "Log.hpp"

using namespace Protocol; // 协议相关函数(Encode/Decode)
using namespace CalculateNS; // 计算器相关类(Calculate)

const static int BUFFER_SIZE = 1024; // 读取缓冲区大小

class HandlerConnection {
public:
    // 业务处理核心:解析协议,计算结果,生成响应
    static void HandlerRequest(Connection* conn) {
        std::string& inbuffer = conn->InBuffer();
        std::string message; // 存储单个完整协议报文

        // 1. 解粘包:从输入缓冲区提取完整报文(循环处理所有完整报文)
        while (Decode(inbuffer, &message)) {
            // 2. 反序列化:JSON字符串→Request结构体(操作数+运算符)
            Factory proto_factory; // 协议工厂(创建Request/Response)
            auto req = proto_factory.BuildRequest();
            if (!req->Deserialize(message)) {
                lg.LogMessage(Error, "request deserialize failed");
                continue;
            }

            // 3. 业务计算:调用计算器处理表达式
            Calculate calculator;
            auto resp = calculator.Cal(req); // resp包含计算结果和状态码

            // 4. 序列化:Response结构体→JSON字符串
            std::string resp_json;
            resp->Serialize(&resp_json);

            // 5. 封装协议:添加长度前缀(避免粘包)
            std::string resp_package = Encode(resp_json);

            // 6. 写入输出缓冲区,等待发送
            conn->AddOutBuffer(resp_package);
        }

        // 7. 触发写事件:若输出缓冲区非空,立即调用写回调发送数据
        if (!conn->OutBufferEmpty()) {
            conn->_sender(conn);
        }
    }

    // 读回调:从socket读取数据到输入缓冲区
    static void Recver(Connection* conn) {
        errno = 0;
        char buffer[BUFFER_SIZE];

        // 非阻塞循环读取(ET模式需一次读完缓冲区数据)
        while (true) {
            ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0) {
                buffer[n] = '\0';
                conn->AddInBuffer(buffer); // 追加到输入缓冲区
            } else {
                // 处理读错误:EAGAIN表示缓冲区空,EINTR表示被信号中断
                if (errno == EAGAIN) break;       // 正常退出,已读完
                else if (errno == EINTR) continue; // 重试
                else {
                    // 严重错误:触发异常回调,销毁连接
                    lg.LogMessage(Error, "recv failed, sockfd: %d, errno: %d", conn->SockFd(), errno);
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        // 打印调试信息(可选)
        lg.LogMessage(Debug, "sockfd: %d, inbuffer: %s", conn->SockFd(), conn->InBuffer().c_str());

        // 调用业务处理逻辑
        HandlerRequest(conn);
    }

    // 写回调:将输出缓冲区数据发送到socket
    static void Sender(Connection* conn) {
        errno = 0;
        std::string& outbuffer = conn->OutBuffer();

        // 非阻塞循环发送(ET模式需一次发完缓冲区数据)
        while (true) {
            ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
            if (n >= 0) {
                outbuffer.erase(0, n); // 移除已发送的数据
                if (outbuffer.empty()) break; // 数据发送完毕,退出
            } else {
                // 处理写错误:EAGAIN表示发送缓冲区满,EINTR表示被信号中断
                if (errno == EAGAIN) break;       // 正常退出,后续再发
                else if (errno == EINTR) continue; // 重试
                else {
                    // 严重错误:触发异常回调
                    lg.LogMessage(Error, "send failed, sockfd: %d, errno: %d", conn->SockFd(), errno);
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        // 调整epoll事件:若数据未发完,保留写事件;否则取消写事件
        if (!conn->OutBufferEmpty()) {
            // 仍有数据待发,开启读+写事件监听
            conn->_R->EnableReadWrite(conn->SockFd(), true, true);
        } else {
            // 数据发完,仅保留读事件监听
            conn->_R->EnableReadWrite(conn->SockFd(), true, false);
        }
    }

    // 异常回调:处理连接异常,销毁连接
    static void Excepter(Connection* conn) {
        lg.LogMessage(Info, "connection closed, sockfd: %d", conn->SockFd());
        
        // 1. 从Reactor中移除连接(删除epoll事件+删除连接列表)
        conn->_R->RemoveConnection(conn->SockFd());
        // 2. 关闭socket
        conn->Close();
        // 3. 释放Connection对象
        delete conn;
    }
};

3.4 TcpServer:Reactor 核心的 “大脑”

TcpServer类是 Reactor 模式的 “控制中心”,它封装了 epoll 操作(创建、注册事件、等待事件),管理所有连接,实现事件分发,是整个架构的 “大脑”。

3.4.1 核心功能

        初始化 epoll 实例和监听 socket;

        管理连接列表(存储Connection,支持添加、删除、查找);

        注册 / 取消 epoll 事件,控制事件监听(如开启 / 关闭读、写事件);

        事件循环:调用epoll_wait等待事件,分发事件到对应的回调函数。

3.4.2 实战代码(TcpServer.hpp)
#pragma once
#include <iostream>
#include <unordered_map>
#include <vector>
#include <sys/epoll.h>
#include <netinet/in.h>
#include "Connection.hpp"
#include "Accepter.hpp"
#include "Log.hpp"

class TcpServer {
public:
    TcpServer(uint16_t port) : _port(port), _epfd(-1), _listensock(-1) {}

    // 初始化Reactor:创建epoll、监听socket、注册监听事件
    bool Init() {
        // 1. 创建epoll实例
        _epfd = epoll_create(10); // size参数已忽略,传任意正数
        if (_epfd < 0) {
            perror("epoll_create");
            return false;
        }

        // 2. 创建监听socket
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0) {
            perror("socket");
            close(_epfd);
            return false;
        }

        // 3. 设置监听socket为非阻塞(ET模式)
        SetNonBlock(_listensock);

        // 4. 绑定端口
        struct sockaddr_in local_addr;
        memset(&local_addr, 0, sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(_port);
        local_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定所有网卡IP
        if (bind(_listensock, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
            perror("bind");
            close(_listensock);
            close(_epfd);
            return false;
        }

        // 5. 监听
        if (listen(_listensock, 5) < 0) {
            perror("listen");
            close(_listensock);
            close(_epfd);
            return false;
        }

        // 6. 创建监听连接,注册“新连接处理回调”
        auto accept_cb = std::bind(&Accepter::AccepterConnection, &_accepter, std::placeholders::_1);
        _listen_conn = ConnectionFactory::BuildListenConnection(
            _listensock, accept_cb, EPOLLIN | EPOLLET, this
        );

        // 7. 将监听连接注册到epoll
        AddConnection(_listen_conn);

        lg.LogMessage(Info, "Reactor server init success, port: %d, epfd: %d", _port, _epfd);
        return true;
    }

    // 启动Reactor事件循环
    void Start() {
        struct epoll_event events[1000]; // 就绪事件数组(支持1000个并发连接)
        while (true) {
            // 等待事件就绪(永久阻塞,直到有事件)
            int nfds = epoll_wait(_epfd, events, sizeof(events)/sizeof(events[0]), -1);
            if (nfds < 0) {
                perror("epoll_wait");
                continue;
            }

            // 遍历就绪事件,分发到对应的回调函数
            for (int i = 0; i < nfds; ++i) {
                int sockfd = events[i].data.fd;
                uint32_t revents = events[i].events; // 就绪的事件类型

                // 查找对应的Connection
                auto it = _conn_map.find(sockfd);
                if (it == _conn_map.end()) {
                    lg.LogMessage(Warning, "unknown sockfd: %d", sockfd);
                    continue;
                }
                Connection* conn = it->second;

                // 处理就绪事件:读、写、异常
                if (revents & (EPOLLIN | EPOLLPRI)) {
                    // 读事件就绪(普通数据或紧急数据)
                    conn->_recver(conn);
                }
                if (revents & EPOLLOUT) {
                    // 写事件就绪
                    conn->_sender(conn);
                }
                if (revents & (EPOLLERR | EPOLLHUP)) {
                    // 异常事件(错误或连接挂断)
                    conn->_excepter(conn);
                }
            }
        }
    }

    // 添加连接到Reactor(注册epoll事件+加入连接列表)
    void AddConnection(Connection* conn) {
        int sockfd = conn->SockFd();
        uint32_t events = conn->Events();

        // 1. 注册epoll事件
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = sockfd;
        if (epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev) < 0) {
            perror("epoll_ctl ADD");
            return;
        }

        // 2. 加入连接列表
        _conn_map.emplace(sockfd, conn);
        lg.LogMessage(Debug, "connection added, sockfd: %d, total conn: %lu", sockfd, _conn_map.size());
    }

    // 从Reactor移除连接(删除epoll事件+删除连接列表)
    void RemoveConnection(int sockfd) {
        // 1. 从epoll中删除事件
        if (epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr) < 0) {
            perror("epoll_ctl DEL");
            return;
        }

        // 2. 从连接列表中删除
        _conn_map.erase(sockfd);
        lg.LogMessage(Debug, "connection removed, sockfd: %d, total conn: %lu", sockfd, _conn_map.size());
    }

    // 开启/关闭读、写事件监听(动态调整epoll事件)
    void EnableReadWrite(int sockfd, bool enable_read, bool enable_write) {
        auto it = _conn_map.find(sockfd);
        if (it == _conn_map.end()) {
            lg.LogMessage(Warning, "EnableReadWrite: unknown sockfd: %d", sockfd);
            return;
        }
        Connection* conn = it->second;

        // 计算新的事件类型
        uint32_t new_events = 0;
        if (enable_read) new_events |= EPOLLIN | EPOLLET;
        if (enable_write) new_events |= EPOLLOUT | EPOLLET;
        conn->SetEvents(new_events);

        // 更新epoll事件
        struct epoll_event ev;
        ev.events = new_events;
        ev.data.fd = sockfd;
        if (epoll_ctl(_epfd, EPOLL_CTL_MOD, sockfd, &ev) < 0) {
            perror("epoll_ctl MOD");
            return;
        }
    }

    ~TcpServer() {
        if (_listensock != -1) close(_listensock);
        if (_epfd != -1) close(_epfd);
        // 释放所有连接
        for (auto& [sockfd, conn] : _conn_map) {
            conn->Close();
            delete conn;
        }
    }

private:
    uint16_t _port;                      // 服务端口
    int _epfd;                           // epoll实例句柄
    int _listensock;                     // 监听socket
    Connection* _listen_conn;             // 监听连接的Connection
    Accepter _accepter;                   // 新连接处理器
    std::unordered_map<int, Connection*> _conn_map; // 连接列表(sockfd→Connection)
};

四、Reactor 模式完整运行流程

结合上述组件,“网络计算器” 的完整运行流程如下,清晰展现 Reactor 的事件驱动逻辑:

  1. 启动服务

    • 创建TcpServer实例,调用Init()初始化 epoll、监听 socket、注册监听连接;
    • 调用Start()进入事件循环,epoll_wait阻塞等待事件。
  2. 新连接请求

    • 客户端发起连接,监听 socket 可读,epoll_wait返回;
    • Reactor 分发读事件到AccepterAccepterConnection
    • Accepter调用accept创建新 socket,初始化Connection并注册到 Reactor。
  3. 客户端发送计算请求

    • 客户端发送 “1+1”,新 socket 可读,epoll_wait返回;
    • Reactor 分发读事件到HandlerConnectionRecver
    • Recver读取数据到输入缓冲区,调用HandlerRequest解析协议、计算结果、写入输出缓冲区;
    • 调用Sender发送结果,若发送完毕,取消写事件。
  4. 客户端关闭连接

    • 客户端关闭 socket,新 socket 触发EPOLLHUP事件;
    • Reactor 分发异常事件到HandlerConnectionExcepter
    • Excepter销毁Connection,从 Reactor 中移除连接。

五、Reactor 模式的优势与适用场景

5.1 核心优势

  1. 高并发支持:单线程(或少量线程)处理数万连接,避免线程切换开销;
  2. 低资源消耗:无需为每个连接创建线程,内存和 CPU 资源占用低;
  3. 异步非阻塞:IO 操作非阻塞,事件驱动无主动等待,资源利用率高;
  4. 扩展性强:业务逻辑与 IO 事件解耦,新增业务只需实现新的回调函数。

5.2 适用场景

        高并发、低数据量:如聊天服务器、API 网关、物联网设备通信(连接多但单连接数据量小);

        IO 密集型服务:如 Nginx(Web 服务器)、Redis(缓存)、Memcached(分布式缓存);

        不适用 CPU 密集型:若业务逻辑耗时过长(如复杂计算),会阻塞 Reactor 线程,需配合线程池(Proactor 模式)。

六、总结与扩展

本文通过 “网络计算器” 案例,完整实现了基于 epoll 的 Reactor 模式,核心收获包括:

  1. 架构设计:理解 Reactor 模式的 “事件驱动 + 反向调用” 思想,掌握四大组件的协同逻辑;
  2. 代码实战:学会封装 Connection 管理连接状态,用 epoll 实现事件监控与分发,通过回调函数解耦 IO 与业务;
  3. 高并发要点:ET 模式配合非阻塞 IO,确保一次处理完缓冲区数据;动态调整 epoll 事件,避免无效监听。

扩展方向

  1. 多线程 Reactor:单 Reactor 负责事件分发,业务逻辑交给线程池处理,解决 CPU 密集型业务阻塞问题;
  2. 主从 Reactor:主 Reactor 处理新连接,从 Reactor 处理已连接的 IO 事件,进一步提升并发能力(如 Nginx 架构);
  3. Proactor 模式:Reactor 是 “同步 IO + 事件驱动”,Proactor 是 “异步 IO + 事件驱动”,适合 Windows(IOCP)或 Linux(io_uring)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值