Swoole 5 升级需全面适配协程原生范式:改用 go() 启动协程、Co::run() 初始化环境;所有 I/O 必须使用协程客户端;上下文需显式判断;Server 改用声明式路由与 Swoole\Coroutine\Server 抽象。

Swoole 4 升级到 5 后,协程 API 不再向后兼容,旧代码直接运行会报 Fatal error: Call to undefined function 或 Call to undefined method。核心不是“写法变丑了”,而是底层模型彻底转向纯协程原生范式——同步阻塞调用被移除,协程生命周期由统一调度器接管,所有 I/O 必须走协程通道。
协程启动方式必须改:go() 替代 swoole_coroutine_create
-
swoole_coroutine_create()、Swoole\Coroutine::create()在 5.0 中已废弃(5.1+ 彻底删除) -
go()是唯一推荐的协程入口,语法简洁且自动注入上下文 -
Co\run()用于顶层协程环境初始化(如 CLI 启动脚本),避免裸写go()导致调度未就绪
// ❌ Swoole 4.x(运行即报错)
swoole_coroutine_create(function () { echo "hello"; });
// ✅ Swoole 5.x 正确写法
go(function () { echo "hello"; });
// ✅ 多协程批量启动(推荐封装在 Co\run 中)
Co\run(function () {
go(fn() => file_get_contents('https://api.example.com/user'));
go(fn() => $pdo->query('SELECT * FROM logs')->fetchAll());
});所有 I/O 操作必须用协程客户端,禁用同步函数
Swoole 5.0 默认启用全钩子(SWOOLE_HOOK_ALL),但仅钩子不等于自动协程化——file_get_contents、curl_exec、mysqli_query 等原生函数仍会阻塞当前协程,导致整个 worker 卡死。
- 必须替换为对应协程客户端:
- HTTP 请求 →
Swoole\Coroutine\Http\Client(非Swoole\Http\Client) - MySQL →
Swoole\Coroutine\MySQL(非mysqli或PDO) - Redis →
Swoole\Coroutine\Redis(非ext-redis) - DNS 查询 →
Co::gethostbyname()(非gethostbyname())
- HTTP 请求 →
// ❌ 同步调用(Swoole 5.x 下会阻塞 reactor)
$content = file_get_contents('https://api.example.com/data');
$user = $pdo->query("SELECT * FROM users WHERE id=1")->fetch();
// ✅ 协程调用(非阻塞、可并发)
$client = new Swoole\Coroutine\Http\Client('api.example.com', 443, true);
$client->set(['timeout' => 5]);
$client->get('/data');
$content = $client->body;
$mysql = new Swoole\Coroutine\MySQL();
$mysql->connect(['host' => '127.0.0.1', 'user' => 'root']);
$user = $mysql->query("SELECT * FROM users WHERE id=1");生命周期与上下文管理逻辑重写
Swoole 5.0 强制要求协程上下文显式感知,Co::getCid() 在非协程环境返回 0,不能再用于判断是否在协程中;defer 行为更严格,资源释放不能依赖它自动触发。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 判断是否处于协程内:用
Co::getContext()是否返回数组,或捕获Co::getCid() > 0 - 清理操作建议改用
finally块或显式回调,避免defer在异常路径下失效 -
on('start')、on('workerStart')等回调中禁止任何阻塞操作(包括sleep()、gethostbyname()、文件读写等)
// ❌ 错误:在 on('start') 中调用阻塞函数
$server->on('start', function ($server) {
$ip = gethostbyname('db.internal'); // ⚠️ 卡死 reactor!
});
// ✅ 正确:提前解析或改用协程 DNS
$server->on('start', function ($server) {
go(function () {
$ip = Co::gethostbyname('db.internal');
// 后续逻辑...
});
});Server 路由与事件注册方式重构
HTTP Server 不再支持 on('request') 回调,改为声明式路由 + 中间件链;WebSocket/TCP/UDP 统一抽象为 Swoole\Coroutine\Server 子类。
-
Swoole\Http\Server构造参数移除$ssl第四参数,改用set(['ssl' => true]) -
on('request')→handle('/', $handler),支持多级路由与中间件 - 自定义进程必须使用
Swoole\Coroutine\Process,swoole_process::start()已不可用
// ❌ Swoole 4.x 写法(5.x 运行失败)
$server = new Swoole\Http\Server('0.0.0.0', 9501, SWOOLE_BASE, true);
$server->on('request', function ($req, $resp) { /* ... */ });
// ✅ Swoole 5.x 标准写法
$server = new Swoole\Coroutine\Http\Server('0.0.0.0', 9501);
$server->set(['ssl' => true]); // SSL 单独配置
$server->handle('/', function ($request, $response) {
$response->header('Content-Type', 'application/json');
$response->end(json_encode(['msg' => 'ok']));
});
$server->start();不复杂但容易忽略

















