背景
高并发网络服务里,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);
}
}
选择建议
- 现有生态以 epoll 为主:优先 Reactor
- 追求极致吞吐且能接受复杂度:考虑 Proactor/io_uring
- 团队经验不足时,别为“更先进”盲目迁移
总结
模型没有绝对优劣,只有场景匹配。
先用 profile 证明瓶颈,再决定是不是值得切换 IO 模型。
架构升级应该由瓶颈驱动,而不是由流行词驱动。