直接结论:easyswoole 项目中不能随意 composer require 任意 php 包,必须确认其协程安全性,否则会导致连接复用污染、超全局变量冲突、协程阻塞卡死;需优先选用官方协程生态包(如 easyswoole/pdo-mysql),并严格按协程链路初始化、获取、使用和释放资源。

直接结论:Easwoole 项目里用 composer require 加包,不是“加了就能用”,必须判断该包是否协程安全;否则极易出现连接复用污染、超全局变量冲突、阻塞协程导致整个服务卡死。
为什么不能随便 composer require 任意 PHP 包
EasySwoole 是常驻内存的协程框架,所有请求共用同一个进程、同一组全局变量(如 $_GET、$_POST、静态属性),但每个请求跑在独立协程里。普通同步阻塞式包(比如原生 PDO、file_get_contents、curl_exec)会直接让当前协程挂起,而 Swoole 不会自动切换——它只对 swoole_coroutine 系列 API(如 Co::sleep、Co::mysql)做调度。
常见后果包括:
- 数据库连接被多个协程复用,事务/字符集/连接状态错乱
- HTTP 客户端发起阻塞请求,整个 worker 进程卡住,后续请求全部排队
- 使用
date_default_timezone_set()或修改ini_set()影响其他协程
composer require 前必须确认的三件事
不是看包有没有“swoole”字样,而是看它底层是否真正适配协程调度:
- 是否封装了
swoole_mysql/swoole_redis/Co::httpClient等协程客户端,而不是调用mysqli、redis扩展或cURL - 是否避免使用
$_SERVER、$GLOBALS、静态变量缓存连接实例(协程间共享) - 是否提供连接池支持(如
easyswoole/pdo-mysql自带AbstractPool实现)
举例:composer require easyswoole/pdo-mysql 可以用,因为其内部用 Co::mysql 封装,并配套连接池;而 composer require doctrine/dbal 默认不可用,除非你手动替换其 driver 为协程实现。
协程安全的替代方案怎么选
官方生态优先级高于第三方:
- MySQL:用
easyswoole/pdo-mysql,别用medoo或illuminate/database(Laravel ORM 默认非协程安全) - Redis:用
easyswoole/redis或直接new \Swoole\Coroutine\Redis(),禁用predis/predis - HTTP 请求:用
Co::httpClient或easyswoole/http-client,不要guzzlehttp/guzzle - 日志:用
easyswoole/log,避免monolog/monolog的文件 handler(未加协程锁)
如果必须引入非协程包,只能把它隔离到子进程(Co::exec)或异步任务队列中运行,不能在主协程上下文直接调用。
容易被忽略的配置陷阱
即使用了协程包,也常因配置错失协程能力:
-
easyswoole/pdo-mysql必须在EasySwooleEvent::initialize()中注册连接池,否则MySqlPool::getInstance()->getObj()返回 null - 数据库配置里的
host写成127.0.0.1而非localhost,否则可能走 socket 连接(不支持协程) - 忘记设置
maxIdleTime和maxObjectNum,连接池耗尽后直接抛异常,而非等待可用连接 - 在控制器里 new 一个数据库连接类而不从连接池取,等于绕过协程管理,退化为传统单连接模式
协程安全不是加个包就自动生效,它是一整套调用链路的约束:从 composer require 开始,到初始化、获取、使用、释放,每一步都得落在 Swoole 协程调度的节奏里。漏掉任何一环,都可能让高并发下的行为变得不可预测。











