Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q76: 如何实现异步 IO?

核心结论

异步 I/O 的目标不是“API 看起来很异步”,而是让线程在等待 I/O 时不要被白白占住。

真正需要先想清楚的是:

  • 你的平台提供的是“就绪通知”还是“完成通知”
  • 事件循环如何组织
  • 结果如何回到业务逻辑
  • 阻塞操作是否真的被隔离出主线程

很多系统嘴上说异步,实际上只是把阻塞调用包进线程池里,这和真正的事件驱动模型不是一回事。

一、先区分几种 I/O 模式

实际工程里最重要的差别通常是:

  • 就绪通知:告诉你“现在可以读/写了”
  • 完成通知:告诉你“这次 I/O 已经完成了”

这个差别会直接影响:

  • 事件循环设计
  • 回调风格
  • 缓冲区管理

二、异步 I/O 真正解决什么问题

它主要解决的是线程资源浪费。

如果一个线程长期阻塞在:

  • 网络收发
  • 磁盘读取
  • 外部连接等待

那系统的并发成本会很高。

异步 I/O 的价值就是把等待时间让出去。

三、事件循环通常是核心

不管底层是 epoll、kqueue 还是 IOCP,工程上最终都需要一个清晰的事件循环来处理:

  • 注册事件
  • 等待事件
  • 分发事件
  • 驱动状态机继续执行

如果没有稳定的事件循环,异步 I/O 最后只会变成散落的回调和复杂状态机。

四、异步不等于没有状态机

很多人觉得异步写法可以像同步一样自然,但底层仍然必须处理:

  • 请求已发出但未完成
  • 部分读写
  • 超时
  • 取消

所以无论用回调、future 还是协程,本质上都绕不开状态管理。

五、网络和磁盘 I/O 要区别看待

网络 I/O 通常更适合事件驱动;磁盘 I/O 在不同平台上的支持方式差异更大。

所以实现异步 I/O 时,不要简单假设“所有 I/O 都能用同一抽象无差别处理”。

六、业务逻辑不应直接耦合底层事件细节

更稳妥的做法通常是:

  • 底层 I/O 层负责读写和事件注册
  • 上层协议层负责组包和解包
  • 业务层只接收更稳定的消息事件

这样异步复杂度不会一路泄露到业务代码里。

七、工程上更稳妥的实践

常见做法是:

  • 用事件循环驱动网络 I/O
  • 把连接状态机显式化
  • 对真正阻塞的外部调用单独隔离
  • 结果统一回投到稳定的业务执行上下文

这样系统才既异步,又可维护。

八、常见误区

1. 用了回调就是异步 I/O

不一定。底层可能仍然是线程池包阻塞调用。

2. 异步 I/O 能自动让系统更快

它主要提升资源利用率,不会自动消除业务逻辑和序列化成本。

3. 异步代码就不需要线程模型设计

恰恰相反,事件循环和业务线程边界必须更清晰。

参考资料

  • Reactor、Proactor 和事件循环实现相关资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu