事件循环是异步任务的主动调度中枢,承担准入校验、生命周期管理、就绪驱动、结构化建模与并发控制五大职责。它通过元数据验证、状态跟踪、条件唤醒、DAG任务建模及runningTaskCount动态限流,保障调度稳定、可观测与可扩展。

事件循环不是“后台线程”,而是异步任务的控制平面——它不被动等待,而是主动拉取、判断、分发与驱动。它的核心职责不是加速单个任务,而是保障整体调度的稳定性、可伸缩性与可观测性。
事件循环是任务准入与生命周期的守门人
它不只是响应 I/O 就绪,更承担任务准入校验(如优先级、deadline)、状态跟踪(pending → running → done)、以及失败后自动触发补偿或重试策略。例如,一个任务携带 trace_id 和 priority 元数据进入队列,事件循环在分发前会检查是否超时、是否被高优抢占;任务执行中抛出异常时,它能依据预设策略决定是丢弃、重试还是转交错误处理器。
- 准入阶段验证任务元数据完整性(type、deadline、resource_hint)
- 运行中维护 runningTaskCount,并联动并发控制器动态限流
- 完成或失败后触发回调清理资源、上报指标、更新 DAG 状态
就绪驱动:靠条件注册,而非轮询等待
协程或回调不会“空转等待”,而是在 await 或注册时,向事件循环声明恢复条件:比如“socket 可读”“500ms 后”“某 Future 被 set_result”。事件循环底层依托 epoll/kqueue/IOCP 等系统调用,在无事件时休眠,有信号时精准唤醒对应任务,避免 CPU 空转。
- 每个 awaitable 都绑定一个 Waker 或 callback,用于被 I/O 完成或定时器触发时唤醒
- 事件循环一次 poll 耗时应控制在微秒级,否则拖慢整个 tick 节奏
- 延迟任务统一维护在最小堆中,到期时批量推入就绪队列
结构化任务建模支撑横向扩展
裸函数闭包无法适应分布式或弹性扩缩场景。理想的任务单元是结构化 payload,含明确事件类型、依赖关系与失败语义。例如将图像推理拆为 { type: "PREPROCESS", data: { id, url } } → { type: "INFERENCE", depends_on: "PREPROCESS" } → { type: "POSTPROCESS" },不同 Worker 可按 type 订阅处理,天然隔离故障、支持动态增减节点。
- 用 JSON-like 结构替代 callable,便于序列化、跨语言、审计与重放
- 依赖关系建议建模为 DAG,支持可视化追踪与运行时插拔节点
- 任务必须携带 trace_id、deadline、priority,为链路追踪与 SLO 保障提供基础
并发控制内嵌于循环生命周期
限流不能只靠外部线程池大小。真正的并发控制要落到“当前事件循环正在执行几个活跃任务”这个维度。一个 loop 实例维护 runningTaskCount,每次启动新任务前检查是否已达上限;任务结束回调里立即触发下一轮 runTask(),实现槽位“零空窗”填充。同时支持运行时 setPoolSize(),调整后立刻补位,无需中断现有任务。
- 就绪队列推荐 FIFO 数组,避免红黑树等复杂结构引入延迟
- 拒绝策略可配置:阻塞等待、快速失败、降级兜底
- runningTaskCount 也是监控关键指标,用于自动扩缩或熔断决策

















