Octane不是装上就快的开关,需配置warm预热高频路径、禁用有状态中间件、改用Redis会话、配置Swoole连接池,并验证driver与扩展是否正确启用。

Octane 不是装上就快的“开关”,它让 Laravel 常驻内存,但默认只预加载最基础部分;没做适配时,首请求慢、中间件错乱、数据库连接爆炸、$_SERVER 冻住不更新——这些才是你实际会撞上的墙。
php artisan octane:start 启动后页面空白或 500?先查 driver 和扩展
启动日志里没出现 Starting Swoole Server 或 Starting RoadRunner Server,说明根本没走 Octane 流程,而是 fallback 到了内置 HTTP 服务器(性能无提升)。
- 检查
config/octane.php中'server' => 'swoole'拼写是否正确('sw00le'这类错误不会报错,只会静默降级) - 运行
php --ri swoole(Swoole 场景)或which rr(RoadRunner),确认扩展/二进制真实可用 - PHP 版本必须 ≥ 8.2(Laravel 11+ 强制),
php -v必须亲眼看到 - 启动前务必执行
php artisan config:clear && php artisan route:clear,否则 Octane 会加载过期缓存导致 404
首请求巨慢、后续才快?warm 和 preload 没配对
Octane 默认只预热 bootstrap/app.php 和核心服务提供者,App\Models\User、routes/api.php 这些业务关键路径全靠首次请求触发加载——这就是“首字节延迟高”的根源。
- 在
config/octane.php的warm数组里显式加高频路径:['/api/users', '/health'] - 执行
php artisan octane:preload生成预加载脚本,并确认php.ini中已启用opcache.preload指向该文件 - 运行
composer dump-autoload --classmap-authoritative --no-dev,强制跳过 PSR-4 动态查找 -
--watch模式下 warm 是单次生效,改完代码要手动php artisan octane:reload,不是自动重跑
API 返回上一个用户的数据?中间件状态污染
Octane 复用中间件实例,$this->user = auth()->user() 这种赋值会让下一个请求直接读到残留属性——这不是 Bug,是常驻内存模型下的必然行为。
- 所有中间件必须无状态:禁止在
__construct()、handle()外部或属性里保存请求相关数据 - 移除
VerifyCsrfToken、ShareErrorsFromSession等仅 Web 表单需要的中间件(API 场景纯属负担) - 调试类中间件(如
LogRequests)必须用app()->environment('local')包裹,否则日志文件会指数级膨胀 -
php artisan octane:reload不会清空中间件实例缓存,彻底重置需php artisan octane:stop && php artisan octane:start
数据库连接数爆满、CPU 持续 100%?PDO 持久化失效
PDO::ATTR_PERSISTENT => true 在 Swoole 协程下完全无效,还可能引发连接错乱;每个请求新建 MySQL 连接,很快耗尽 max_connections。
- 不要依赖 PDO 持久化,改用协程兼容方案:安装
hyperf/database或配置 Swoole 连接池 - 在
config/database.php的mysql驱动下加'pool' => ['min_connections' => 4, 'max_connections' => 32] - 检查日志中是否频繁出现
SQLSTATE[HY000] [2002] Connection refused,这是连接池未生效或配置过小的明确信号 - SESSION_DRIVER=file 必须改为
redis或database,否则多 worker 间会话冲突或文件锁阻塞
真正卡住人的从来不是“怎么启动”,而是“启动之后为什么没变快”——warm 没覆盖业务类、中间件带状态、连接池没配、$_SERVER 被当真,这些点漏掉任何一个,Octane 就只是个更贵的 FPM。


















