Hyperf 3.0 异常处理需严格区分协程异常与同步异常:协程异常须用 try-catch 或 CoroutineExceptionHandler 在协程内捕获,否则被静默吞掉;同步异常由 RequestExceptionHandler 统一处理,不可混用或在其中调用挂起函数。

Hyperf 3.0 中的异常处理需明确区分两类异常来源:协程内未捕获的 协程异常(如挂起函数中抛出的 RuntimeException、IO 超时等),以及传统 PHP 执行流中的 同步异常(如控制器构造失败、路由解析前的语法错误、依赖注入异常等)。二者触发时机、传播路径和捕获机制完全不同,混用处理逻辑会导致静默丢失或重复捕获。
协程异常:靠 CoroutineExceptionHandler + try-catch 组合拦截
协程异常不会自动冒泡到 HTTP 请求生命周期顶层,必须在协程内部或作用域边界显式处理:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 使用
try-catch包裹挂起操作是最直接方式,例如在go()或co()启动的协程体中捕获 -
CoroutineExceptionHandler仅对go()/co()启动的协程生效,且只捕获“协程自动抛出”的异常(非await()延迟异常) -
async类协程(如Hyperf\Utils\Parallel)的异常必须在wait()或collect()时显式触发并捕获,CoroutineExceptionHandler对其无效 - 注意:Swoole 协程中
throw出的异常若未被任何协程上下文捕获,会被调度器静默吞掉——这不是 bug,是协程隔离设计使然
同步异常:由全局 RequestExceptionHandler 统一接管
HTTP 请求进入 Hyperf 生命周期后,在协程尚未启动前发生的异常(如中间件初始化失败、参数验证器构造异常、容器解析失败),走的是标准 PSR-15 异常链路:
- 通过
config/autoload/exceptions.php配置的RequestExceptionHandler实现类处理 - 该处理器继承自
Hyperf\HttpServer\Exception\HttpExceptionHandler,能拿到完整的RequestInterface和ResponseInterface - 所有同步异常都会终止当前请求,但不会影响其他协程或 worker 进程
- 务必在
isValid()方法中精准判断异常类型,避免把协程异常也误交到这里处理(比如Hyperf\Contract\StdoutLoggerInterface抛出的异常不该进 HTTP 响应流)
混合场景下的推荐实践
真实业务中,同步流程常会启动协程,此时异常可能来自不同层级:
- 控制器方法本身是同步的,但调用了
go()启动后台任务 → 主流程异常走RequestExceptionHandler,子协程异常需独立捕获 - 使用
Hyperf\Utils\Coroutine::create()时,建议统一包装一层安全启动器,内置try-catch + 日志记录 + recover,防止静默退出 - 不要在
RequestExceptionHandler中尝试await或调用挂起函数,它运行在非协程上下文中,会触发致命错误 - 对关键异步任务(如发短信、写日志),建议搭配
supervisorScope思路手动实现失败重试+降级,而非依赖异常传播

















