必须设为 SWOOLE_HOOK_ALL,因Hyperf协程依赖Swoole Hook机制,仅部分Hook会导致Redis、文件等调用阻塞协程;需在入口文件顶部、Runtime启用前定义,且不可重复或滞后。

Hyperf 3.1 中开启 SWOOLE_HOOK_ALL 是启用协程自动化的关键一步,它让传统同步 PHP 扩展(如 curl、PDO、Redis、MySQLi、file_get_contents 等)在协程环境下也能无感切换为异步非阻塞调用,无需改写业务逻辑。
为什么必须设为 SWOOLE_HOOK_ALL?
Hyperf 的协程能力高度依赖 Swoole 的 Hook 机制。若只启用部分 Hook(如仅 SWOOLE_HOOK_TCP),遇到 Redis::get() 或 file_put_contents() 这类调用时,协程仍会因底层同步阻塞而“卡住”,导致整个协程调度器停滞,高并发下极易出现超时或连接堆积。
官方推荐且 Hyperf 测试/生产环境默认采用的就是 SWOOLE_HOOK_ALL,覆盖全部 I/O 相关函数,确保协程上下文全程不中断。
正确开启位置与时机
该常量需在 Swoole Runtime 启用前定义,且只能定义一次。典型位置是项目入口文件(如 bin/hyperf.php 或 public/index.php)最顶部:
defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
Swoole\Runtime::enableCoroutine(true);
require BASE_PATH . '/vendor/autoload.php';
注意:
• 不可放在 autoload.php 之后,否则无效;
• 不可在多个文件中重复定义,否则触发 PHP 警告;
• 若使用 Docker 或多环境部署,确保该配置在所有启动路径(如 HTTP Server、WebSocket Server、Task Worker)中均生效。
验证是否生效
运行以下代码检查当前 Hook 状态:
var_dump(Swoole\Runtime::getHookFlags() & SWOOLE_HOOK_ALL); // 应输出 int(1)
更直观的方式是启动服务后执行一个混合 I/O 操作(如同时发 HTTP 请求 + 读文件 + 查 Redis),观察是否无阻塞并行完成。也可通过 swoole_info() 查看 hook_flags 字段值是否包含全部位标识。
常见误区与避坑点
- 误以为只要
enableCoroutine(true)就够了——其实没设SWOOLE_HOOK_FLAGS,大部分扩展仍走同步路径 - 在
bootstrap.php(测试环境)里设置,但忘记在主入口也设置——导致 CLI 命令或 Worker 进程未 Hook - 使用宝塔或旧版 Swoole(如 4.x)时,
SWOOLE_HOOK_ALL不被支持或行为异常,务必确认php --ri swoole输出中 support coroutines: enabled 且版本 ≥ 5.0 - 开启后遇到个别扩展异常(如某些老版本 memcached 扩展),可临时排除:用
SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_MEMCACHED,但应优先升级扩展而非妥协 Hook 范围











