背景

高并发网络服务里,Reactor 和 Proactor 是两个绕不开的模型。

很多争论其实都在混淆一个问题:

  • 你是在等“就绪事件”
  • 还是在等“异步操作完成事件”

核心差异

Reactor

  • 内核告诉你哪个 fd 就绪
  • 业务线程自己 read/write

Proactor

  • 业务先发起异步 IO
  • 内核完成后通知你结果

在 Linux 常规栈里,很多框架本质上还是 Reactor;在 io_uring 这类能力更强的接口下,Proactor 风格更容易落地。

简化示意

// Reactor 风格:事件到达后主动读
void onReadable(int fd) {
    char buf[4096];
    ssize_t n = ::read(fd, buf, sizeof(buf));
    if (n > 0) {
        handleRequest(buf, n);
    }
}
// Proactor 风格:提交后等待完成回调
void submitRead(Connection* c) {
    io_uring_prep_read(c->sqe, c->fd, c->buf, c->cap, 0);
}

void onReadComplete(Connection* c, int res) {
    if (res > 0) {
        handleRequest(c->buf, res);
    }
}

选择建议

  1. 现有生态以 epoll 为主:优先 Reactor
  2. 追求极致吞吐且能接受复杂度:考虑 Proactor/io_uring
  3. 团队经验不足时,别为“更先进”盲目迁移

总结

模型没有绝对优劣,只有场景匹配。

先用 profile 证明瓶颈,再决定是不是值得切换 IO 模型。


架构升级应该由瓶颈驱动,而不是由流行词驱动。