Laravel Octane 并非开箱即用的性能魔法,其真实提升依赖主动适配:需停用 PHP-FPM、预热高频类、配置连接池、确保中间件无状态、规避静态变量污染,否则性能增益有限甚至更不稳定。

直接上结论:Laravel Octane 不是“开箱即用就飞”的魔法开关,它把应用常驻内存后,性能提升幅度取决于你是否主动切断传统 PHP-FPM 模式下的惯性操作——比如每次请求都重建连接、重复加载中间件、在静态属性里存状态。没做适配的 Octane 服务,跑得比 FPM 快不了多少,甚至更不稳定。
php artisan octane:start 启动后响应没变快?检查 preload 和 warm 配置
Octane 启动时默认只预加载 bootstrap/app.php 和核心服务提供者,大量业务类(如模型、策略、自定义服务)仍按需加载。这会让首几个请求明显变慢,后续才稳定。
- 打开
config/octane.php,确认warm数组包含高频使用的类路径,例如:App\Models\User::class、App\Services\PaymentService::class -
preload列表建议显式添加app/Providers/*.php和routes/*.php,避免路由解析延迟 - 开发环境加
--watch参数会禁用部分预热逻辑,上线前务必去掉 - 执行
php artisan octane:reload后,首次请求仍可能慢——这是正常现象,warm 是单次生效,不是永久驻留
数据库连接复用失败导致 CPU 升高或超时
Swoole/RoadRunner 下 PDO 连接无法跨请求复用(PHP 原生限制),若不干预,每个请求都会新建 MySQL 连接,很快耗尽 max_connections 或触发连接池饥饿。
- 不要只设
PDO::ATTR_PERSISTENT => true:Swoole 中该选项无效,还可能引发连接错乱 - 改用协程兼容方案:安装
swooletw/laravel-swoole或直接配置hyperf/database连接池(推荐) - 在
config/database.php的mysql驱动下增加'pool' => ['min_connections' => 4, 'max_connections' => 32](需配合对应扩展) - 检查日志中是否频繁出现
SQLSTATE[HY000] [2002] Connection refused—— 这大概率是连接池未生效或配置过小
中间件状态污染让 API 返回错乱数据
中间件实例在 Octane 中被复用,如果用了 $this->user = auth()->user() 这类赋值,下一个请求可能读到上一个用户的残留数据。
- 所有中间件必须无状态:禁止在
__construct或属性里保存请求相关数据 - 移除
VerifyCsrfToken、ShareErrorsFromSession等仅对 Web 表单有意义的中间件(API 场景下纯属负担) - 调试类中间件(如
LogRequests)务必用app()->environment('local')包裹,否则日志文件会爆炸增长 - 运行
php artisan octane:reload不会清空中间件实例缓存,必须octane:stop && octane:start
FrankenPHP + Sail 下 HTTPS 访问 404 或证书错误
FrankenPHP 在 Sail 容器里默认监听 HTTP,且不自动处理 TLS 终止;直接配 --https 参数而不改 Nginx 或端口映射,会导致浏览器访问 https://localhost 时请求根本没进 FrankenPHP。
- 确保
docker-compose.yml中laravel.test服务同时暴露 TCP 和 UDP 的 443 端口:- '443:443'和- '443:443/udp' -
SUPERVISOR_PHP_COMMAND必须含--https且--host=localhost(不能是0.0.0.0),否则 FrankenPHP 拒绝 HTTPS 请求 - 证书文件需挂载进容器,例如通过
volumes:添加./certs:/etc/frankenphp/certs,并在命令中指定--tls-cert-file=/etc/frankenphp/certs/fullchain.pem --tls-key-file=/etc/frankenphp/certs/privkey.pem - 浏览器必须访问
https://localhost,而非https://127.0.0.1—— FrankenPHP 对后者不返回有效证书链
最易被忽略的一点:Octane 不会自动帮你清理全局静态变量、闭包引用的大对象、或第三方 SDK 的单例状态。一次内存泄漏,可能撑爆 worker 进程并触发自动重启,反而造成请求抖动。上线前用 php artisan octane:status 观察 worker 生命周期,再用 memory_get_usage(true) 在关键位置打点,比盲目调大 memory_limit 有用得多。



















