什么是 Octane
Laravel Octane 是一个通过高性能应用服务器让 Laravel 应用性能大幅提升的扩展包。
在传统的 PHP-FPM 下,每个请求都会启动并销毁一次应用。Octane 只启动应用一次并常驻在内存中,用来极快地处理后续请求。
与 PHP-FPM 最大的差别在于,服务提供者注册、Bootstrap 等启动逻辑不会在每个请求中重复执行。启动一次后,后续的请求都能以极快的速度处理。
支持的服务器
Octane 支持以下三种服务器。
| 服务器 | 语言 | 安装 | 并发任务 | 备注 |
|---|
| FrankenPHP | Go | 自动(二进制) | — | 推荐,支持 HTTP/3 和 Brotli |
| RoadRunner | Go | 自动(二进制) | — | 简单,配置容易 |
| Swoole | PHP 扩展 | 通过 PECL 手动安装 | ✅ | 支持并发任务和 Octane 缓存 |
在 Laravel Cloud 上推荐使用 FrankenPHP 运行 Octane,完全托管。
安装与配置
安装扩展包
composer require laravel/octane
Octane 初始化
php artisan octane:install
执行后会提示选择服务器。选择后会生成 config/octane.php。
FrankenPHP
选择 FrankenPHP 后,Octane 会自动下载二进制。无需额外操作。
RoadRunner
选择 RoadRunner 后,Octane 会自动下载二进制。
Swoole
Swoole 是 PHP 扩展,通过 PECL 安装。
若使用 Open Swoole,请使用如下命令。
启动方式
启动服务器
默认监听 8000 端口。访问 http://localhost:8000 即可。
指定服务器
php artisan octane:start --server=frankenphp
php artisan octane:start --server=roadrunner
php artisan octane:start --server=swoole
指定 worker 数
php artisan octane:start --workers=4
Swoole 下如需指定 task worker:
php artisan octane:start --workers=4 --task-workers=6
监听文件变化
开发时如果不重启服务器,文件更改不会生效。加上 --watch 参数可以自动重启。
php artisan octane:start --watch
--watch 需要 Node.js 与 Chokidar。npm install --save-dev chokidar
其他管理命令
# 重新加载 worker(部署后执行)
php artisan octane:reload
# 停止服务器
php artisan octane:stop
# 查看服务器状态
php artisan octane:status
依赖注入的注意事项
Octane 将应用常驻内存,所以服务提供者的 register 和 boot 只在服务器启动时执行一次。同一个应用实例会在多次请求间被复用,因此把容器或请求注入到对象的构造函数中需要格外小心。
注入容器
如果直接把容器注入到单例的构造函数,会一直复用旧容器。
// ❌ 有问题 — 复用了旧的容器
$this->app->singleton(Service::class, function (Application $app) {
return new Service($app);
});
// ✅ 安全 — 用闭包每次获取最新容器
$this->app->singleton(Service::class, function () {
return new Service(fn () => Container::getInstance());
});
全局辅助函数 app() 和 Container::getInstance() 始终返回最新容器,是安全的。
注入请求
// ❌ 有问题 — 复用了旧的请求
$this->app->singleton(Service::class, function (Application $app) {
return new Service($app['request']);
});
// ✅ 安全 — 用闭包每次获取最新请求
$this->app->singleton(Service::class, function (Application $app) {
return new Service(fn () => $app['request']);
});
// ✅ 更推荐 — 只把需要的值作为参数传给方法
$service->method($request->input('name'));
在控制器方法或路由闭包中用类型提示注入 Illuminate\Http\Request 是安全的。全局辅助函数 request() 也始终返回当前请求。
注入配置仓库
// ❌ 有问题 — 配置改变了也仍在用旧的仓库
$this->app->singleton(Service::class, function (Application $app) {
return new Service($app->make('config'));
});
// ✅ 安全
$this->app->singleton(Service::class, function () {
return new Service(fn () => Container::getInstance()->make('config'));
});
全局辅助函数 config() 始终返回最新的配置仓库,是安全的。
应对内存泄漏
由于 Octane 会把应用保持在内存中,向静态属性等地方持续累积数据会导致内存泄漏。
// ❌ 内存泄漏示例 — 每个请求都会向 $data 追加数据
class Service
{
public static array $data = [];
}
public function index(Request $request): array
{
Service::$data[] = Str::random(10);
return [];
}
通过 max-requests 回收 worker
worker 处理一定次数请求后自动重启,可以缓解内存泄漏。默认是 500 次。
php artisan octane:start --max-requests=250
设置最大执行时间
config/octane.php 中可以设置单个请求的最大执行时间,默认是 30 秒。
'max_execution_time' => 30,
修改 max_execution_time 后请重启 Octane 服务器。
并发任务(仅限 Swoole)
在使用 Swoole 时,可以通过 Octane::concurrently() 并发执行多个任务。
use App\Models\User;
use App\Models\Server;
use Laravel\Octane\Facades\Octane;
[$users, $servers] = Octane::concurrently([
fn () => User::all(),
fn () => Server::all(),
]);
并发任务会作为 Swoole 的“task worker”以独立进程运行,task worker 数量通过 --task-workers 指定。
php artisan octane:start --workers=4 --task-workers=6
concurrently 传入的任务最多 1024 个(Swoole 的限制)。
Tick 与 Interval(仅限 Swoole)
Swoole 下可以注册按指定间隔定期执行的任务。在服务提供者的 boot 方法中注册。
use Laravel\Octane\Facades\Octane;
// 每 10 秒执行一次
Octane::tick('delayed-ticker', fn () => ray('Ticking...'))
->seconds(10);
// 服务器启动后立即执行一次
Octane::tick('immediate-ticker', fn () => ray('Ticking...'))
->seconds(10)
->immediate();
Octane 缓存(仅限 Swoole)
基于 Swoole 的 Swoole Table 的高速内存缓存,每秒可完成最多 200 万次读写。
use Illuminate\Support\Facades\Cache;
Cache::store('octane')->put('framework', 'Laravel', 30);
Interval 缓存
按指定时间间隔自动刷新的缓存。
use Illuminate\Support\Str;
Cache::store('octane')->interval('random', function () {
return Str::random(10);
}, seconds: 5);
Octane 缓存中的数据在服务器重启后会全部丢失。
Swoole 表(仅限 Swoole)
你可以定义任意 worker 都可访问的共享内存表。在 config/octane.php 的 tables 中配置。
'tables' => [
'example:1000' => [
'name' => 'string:1000',
'votes' => 'int',
],
],
通过 Octane::table() 方法访问表。
use Laravel\Octane\Facades\Octane;
Octane::table('example')->set('uuid', [
'name' => 'Nuno Maduro',
'votes' => 1000,
]);
$row = Octane::table('example')->get('uuid');
Swoole 表只支持 string、int、float 列类型。数据在服务器重启后丢失。
生产环境部署
Nginx + Octane 架构
生产环境通常在 Nginx 后面运行 Octane。Nginx 负责静态资源和 SSL 终端,把动态请求代理给 Octane。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name example.com;
root /home/forge/example.com/public;
location /index.php {
try_files /not_exists @octane;
}
location / {
try_files $uri $uri/ @octane;
}
location @octane {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://127.0.0.1:8000$suffix;
}
}
使用 Supervisor 常驻
在生产环境用 Supervisor 让 Octane 常驻运行。
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/example.com/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/storage/logs/octane.log
stopwaitsecs=3600
启用 HTTPS
若要让 Octane 生成 HTTPS 链接,请在 .env 中设置:
与 Laravel Cloud 结合
Laravel Cloud 完全托管地支持 FrankenPHP 版 Octane。无需配置 Nginx 或 Supervisor,只需两步即可启用 Octane。
安装扩展包
安装 Octane。octane:install 命令可以执行,但不是必需的。composer require laravel/octane
在 Laravel Cloud 中启用 Octane
打开环境的 App 计算集群设置,打开 “Use Octane as runtime” 保存并部署即可。Laravel Cloud 会自动使用 FrankenPHP + Octane 构建并启动应用。
详情请参考 Laravel Cloud 文档。
部署后重新加载 worker
部署后需要重新加载 worker 才能让新代码进入内存。
php artisan octane:reload