codeigniter需运行在swoole上才能实现3000+ rps,因其同步模型依赖php-fpm;控制器内用go()会导致db连接异常、日志错乱、类加载竞争;正确做法是剥离http入口,由swoole托管核心逻辑,改用协程mysql/redis连接池,并弃用session改用jwt。

CodeIgniter 本身是同步阻塞框架,原生无法承载高并发;要真正提升到每秒 3000+ RPS,必须脱离 PHP-FPM 模式,用 Swoole 替换底层运行时——不是“在 CI 中用 Swoole”,而是“让 CI 运行在 Swoole 上”。
为什么不能直接在 CI 控制器里调用 go()
CI 的生命周期(Request→Router→Controller→Response)强依赖 PHP-FPM 的请求-响应模型。一旦你在控制器中写 go(function() { ... }),协程会异步启动,但 CI 的 Response 对象早已完成输出、资源被释放,导致:
- 协程中调用
cache()或db()->query()可能因 DB 连接未初始化或已关闭而报Call to a member function query() on null - CI 的
Logger、Session等服务非协程安全,多协程并发写入日志文件会错乱或丢数据 - CI 的自动加载器(
Autoloader)未适配协程上下文,类加载可能竞争失败
正确做法:用 Swoole Server 托管 CI 的核心逻辑
把 CI 当作一个“业务逻辑包”,剥离其 HTTP 入口,由 Swoole 主动调用。关键步骤如下:
- 禁用 CI 的自动路由和输出机制:在
app/Config/App.php中设$baseURL = '',并确保不调用exit()或die() - 创建独立入口文件(如
server.php),手动加载 CI 核心服务:Services::request()、Services::response()、Services::router(),但不执行$router->handle()自动分发 - 在 Swoole
on('receive')或on('request')回调中,解析 URL 和参数,手动调用对应控制器方法,并用$response->setBody()收集结果 - 所有数据库操作必须改用 Swoole 协程 MySQL 客户端(如
Swoole\Coroutine\MySQL),而非 CI 默认的MySQLi驱动
缓存与连接池必须脱离 CI 配置独立管理
CI 的 cache() 辅助函数底层仍走 FileHandler 或 RedisHandler 同步驱动,无法并发复用连接。必须绕过它:
- Redis 连接必须用
Swoole\Coroutine\Redis实例,且通过Channel构建连接池,例如:$pool = new Channel(16),每次pop()获取连接,push()归还 - 数据库连接池同理,用
Swoole\Coroutine\MySQL+Channel,避免每个协程新建连接导致Too many connections - CI 的
.env中cache.handler设置无效,Swoole 环境下应完全忽略该配置
最易被忽略的致命点:Session 和 Cookie 处理
CI 的 Session 类基于文件或数据库存储,且内部使用 session_start(),该函数在协程中会阻塞整个 worker 进程。必须替换为无状态方案:
- 放弃
$session->set(),改用 JWT 或自定义 token 存储在 Redis 中,key 为随机字符串,value 为用户数据序列化内容 - Cookie 写入不能依赖
setcookie(),需手动拼接Set-Cookie响应头:$response->setHeader('Set-Cookie', 'token=xxx; path=/; httponly; secure') - 所有中间件(如权限校验)必须重写为纯函数,不依赖 CI 的
BaseController生命周期钩子











