Skip to content

生产接入检查清单

教程跑通只证明编译、链接和基本语义正确。真正接入服务前,还要把 Executor 放进应用的生命周期、容量和故障模型中。本页按接入顺序给出一套最小评审清单。

如果项目仍在使用 detached thread、std::async 或自建任务队列,先阅读从现有线程代码迁移;检查已完成的设计时,可用并发架构反模式从症状反查。

1. 确定运行时 owner

默认单例适合进程内共享线程池;独立 Executor 实例适合测试隔离、插件隔离或不同组件需要独立关闭的场景。不要在每次请求中创建 Executor,也不要让多个模块都认为自己可以关闭共享单例。

在设计文档中明确:

  • 谁在第一次提交前调用 initialize_ex()
  • 谁可以更新 failure callback 和监控配置;
  • 谁在停止接收新请求后发起等待与 shutdown()
  • 哪些组件只借用 Executor,绝不拥有其生命周期。

2. 用真实负载设定容量

默认配置适合开始验证,不代表适合生产。至少估算峰值到达率、任务执行时间和可接受排队时间,再确定 min_threadsmax_threadsqueue_capacity

队列容量不是越大越安全:大队列可能把过载表现从“快速拒绝”变成“长时间处理陈旧工作”。如果数据过时后没有价值,应在业务入口合并、覆盖或拒绝,而不是无限排队。

task_timeout_ms 是软超时观察机制,不会强制终止任意业务函数。网络、文件和设备 I/O 仍应配置自己的超时。

3. 给每类工作选择完成边界

工作类型推荐完成边界退出时策略
请求内计算保存 future,并在请求预算内 get()返回成功或明确错误
后台批处理保存全部 futures 或批次状态有界等待,记录未完成数量
fire-and-forgetcallback/status + 业务关联 ID明确允许完成或丢弃
软周期维护task ID + 周期状态先取消,再等待在途工作
实时控制realtime status + drop/timeout counters先停止生产者,再停实时线程

如果说不清某个 future、task ID 或实时任务名称由谁持有,生命周期设计还没有完成。

4. 建立三层失败观察

单次调用、服务趋势和诊断上下文回答的是不同问题:

text
单次结果       future.get()
服务级趋势     get_failure_status() + monitoring
最近故障上下文 set_failure_callback() + get_recent_failures()

callback 应只做短小、非阻塞的事件转交。复杂格式化、网络上报和重试应放到应用自己的日志或告警线程。最近失败缓冲是有限诊断窗口,不是审计日志。

为以下事件分别设阈值,不要只告警 total_count:任务异常、提交拒绝、等待超时、实时 drop、GPU failure 和 tuning fallback 的处理动作不同。通信组件的 drop、overwrite、stale 与 missed phase 默认属于组件本地统计,也要单独接入。

5. 所有等待都必须有预算

请求线程不要无界等待未知工作。使用 future 自身的等待能力控制单项结果;服务排空使用 wait_for_completion_ex(timeout),超时时读取 CompletionStatus 的 active、queued 和 pending 数量。

等待超时后的动作应提前决定:

  • 继续等待一小段时间并升级告警;
  • 停止接收新工作,只允许在途任务完成;
  • 进入 shutdown(false),接受未完成工作的业务后果;
  • 将未完成输入持久化后交给下次启动恢复。

库无法替应用选择数据一致性策略。

6. 按顺序关闭

推荐退出顺序:

  1. 对外标记 draining,停止接收新请求。
  2. 停止定时器、设备回调和其他任务生产者。
  3. 取消普通周期任务。
  4. 停止实时任务的上游推送,再停止实时线程。
  5. 有界等待普通异步任务,并记录状态快照。
  6. 根据等待结果调用 shutdown(true) 或明确选择快速关闭。
  7. 最后销毁任务引用的数据、日志与通信基础设施。

反过来先销毁业务对象,再等待捕获这些对象的异步任务,是典型的 use-after-free 来源。

7. 用过载测试验证设计

正常 smoke test 看不到容量问题。发布前至少构造以下情况:

  • 任务生产速度暂时高于消费速度;
  • 某个任务抛异常,callback 自身也抛异常;
  • 一个任务超过请求等待预算;
  • 关闭过程中仍有生产者尝试提交;
  • 实时队列满或对象池耗尽;
  • GPU 后端、设备或运行时不可用;
  • Linux 实时权限或亲和性配置无法应用。

验收标准不是“进程没崩溃”,而是调用方获得明确返回,计数器发生预期变化,日志能定位 executor/task,并且关闭仍在预算内完成。

最小评审结论模板

text
Executor owner:
初始化配置与依据:
任务类型与提交接口:
future / task ID owner:
过载策略:
失败告警入口与阈值:
单项等待预算 / 排空预算:
关闭顺序:
实时或 GPU 降级行为:
验证过的故障场景:

完成这些答案后,再按需阅读失败可观察性有界等待与状态快照实时与通信边界