> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Octane

> 使用 FrankenPHP、Swoole、RoadRunner 加速 Laravel 應用程式

## 什麼是 Octane

[Laravel Octane](https://github.com/laravel/octane) 是使用高效能應用程式伺服器來大幅提升 Laravel 應用程式效能的套件。

在一般的 PHP-FPM 中，每次請求都會啟動並結束應用程式。而在 Octane 中，應用程式只會啟動一次並保留在記憶體中，後續請求便能高速處理。

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Nginx
    participant Octane as Octane<br>(常駐程序)
    participant App as Laravel<br>應用程式
    Client->>Nginx: 請求
    Nginx->>Octane: Proxy
    Octane->>App: 請求處理（記憶體內）
    App->>Nginx: 回應
    Nginx->>Client: 回應
```

與 PHP-FPM 最大的差異在於，應用程式的啟動流程（服務提供者的註冊等）不會在每次請求時重複執行。只需啟動一次，後續便能以超高速處理請求。

## 支援的伺服器

Octane 支援下列三種伺服器。

```mermaid theme={null}
flowchart LR
    A["伺服器選擇"] --> B{"需要並行任務或<br>Swoole 功能?"}
    B -->|"Yes"| C["Swoole<br>（PECL 擴充）"]
    B -->|"No"| D{"需要 HTTP/3、Brotli<br>壓縮?"}
    D -->|"Yes"| E["FrankenPHP<br>（推薦）"]
    D -->|"No"| F["RoadRunner<br>（Go 製二進位）"]
```

| 伺服器        | 語言     | 安裝          | 並行任務 | 備註                  |
| ---------- | ------ | ----------- | ---- | ------------------- |
| FrankenPHP | Go     | 自動（二進位）     | —    | 推薦。支援 HTTP/3、Brotli |
| RoadRunner | Go     | 自動（二進位）     | —    | 簡潔且易於設定             |
| Swoole     | PHP 擴充 | 以 PECL 手動安裝 | ✅    | 可用並行任務、Octane 快取    |

<Info>
  在 Laravel Cloud 中，建議使用 FrankenPHP 執行 Octane，並提供完整的託管支援。
</Info>

## 安裝與設定

### 套件安裝

```bash theme={null}
composer require laravel/octane
```

### Octane 初始化設定

```bash theme={null}
php artisan octane:install
```

執行後會顯示選擇伺服器的提示。選好後會產生 `config/octane.php`。

### FrankenPHP

選擇 FrankenPHP 後，Octane 會自動下載二進位檔，無需額外步驟。

### RoadRunner

選擇 RoadRunner 後，Octane 會自動下載二進位檔。

### Swoole

Swoole 是 PHP 擴充，透過 PECL 安裝。

```bash theme={null}
pecl install swoole
```

若要使用 Open Swoole，請以下列指令安裝。

```bash theme={null}
pecl install openswoole
```

## 啟動方式

### 啟動伺服器

```bash theme={null}
php artisan octane:start
```

預設會以 `8000` 連接埠啟動，可透過 `http://localhost:8000` 存取。

### 指定伺服器

```bash theme={null}
php artisan octane:start --server=frankenphp
php artisan octane:start --server=roadrunner
php artisan octane:start --server=swoole
```

### 指定 worker 數量

```bash theme={null}
php artisan octane:start --workers=4
```

在 Swoole 中若也要指定 task worker，可如下設定。

```bash theme={null}
php artisan octane:start --workers=4 --task-workers=6
```

### 監控檔案變更

開發過程中，修改檔案後若不重啟伺服器就無法反映。使用 `--watch` 旗標可自動重啟。

```bash theme={null}
php artisan octane:start --watch
```

<Warning>
  使用 `--watch` 需要 [Node.js](https://nodejs.org) 與 Chokidar。

  ```bash theme={null}
  npm install --save-dev chokidar
  ```
</Warning>

### 其他管理指令

```bash theme={null}
# 重新載入 worker（部署後執行）
php artisan octane:reload

# 停止伺服器
php artisan octane:stop

# 檢查伺服器狀態
php artisan octane:status
```

## 依賴注入的注意事項

由於 Octane 會將應用程式保留在記憶體中，因此**服務提供者的 `register` 或 `boot` 只會在伺服器啟動時執行一次**。同一個應用程式實體會在請求之間被重複使用，所以將容器或請求注入物件建構子時需要特別留意。

```mermaid theme={null}
flowchart LR
    A["伺服器啟動<br>（僅一次）"] --> B["ServiceProvider<br>register / boot"]
    B --> C["應用程式<br>實體（記憶體）"]
    C --> D["請求 1"]
    C --> E["請求 2"]
    C --> F["請求 3..."]
```

### 容器的注入

若將容器直接注入單例的建構子，將會重複使用舊的容器。

```php theme={null}
// ❌ 有問題的範例 — 舊容器被重複使用
$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()` 一律回傳最新的容器，因此是安全的。

### Request 的注入

```php theme={null}
// ❌ 有問題的範例 — 舊的 request 被重複使用
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app['request']);
});

// ✅ 安全的範例 — 透過閉包每次取得最新的 request
$this->app->singleton(Service::class, function (Application $app) {
    return new Service(fn () => $app['request']);
});

// ✅ 最推薦 — 只傳入方法所需的值
$service->method($request->input('name'));
```

<Info>
  在 controller 方法或路由閉包中對 `Illuminate\Http\Request` 進行型別提示是安全的。全域輔助函式 `request()` 也一律回傳目前的 request。
</Info>

### 設定 repository 的注入

```php theme={null}
// ❌ 有問題的範例 — 即使設定值改變也仍使用舊的 repository
$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()` 一律回傳最新的設定 repository，因此是安全的。

## 記憶體洩漏對策

由於 Octane 會將應用程式保留在記憶體中，因此若將資料累積於靜態屬性等處，將造成記憶體洩漏。

```php theme={null}
// ❌ 記憶體洩漏的範例 — $data 會隨著每次請求持續增長
class Service
{
    public static array $data = [];
}

public function index(Request $request): array
{
    Service::$data[] = Str::random(10);
    return [];
}
```

### 以 max-requests 回收 worker

透過在 worker 處理一定數量的請求後自動重啟，可降低記憶體洩漏影響。預設為 500 個請求。

```bash theme={null}
php artisan octane:start --max-requests=250
```

### 設定最大執行時間

可在 `config/octane.php` 中設定請求的最大執行時間，預設為 30 秒。

```php theme={null}
'max_execution_time' => 30,
```

<Warning>
  變更 `max_execution_time` 後，請重啟 Octane 伺服器。
</Warning>

## 並行任務（僅 Swoole）

若使用 Swoole，可透過 `Octane::concurrently()` 並行執行多項處理。

```php theme={null}
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` 指定。

```bash theme={null}
php artisan octane:start --workers=4 --task-workers=6
```

<Warning>
  傳入 `concurrently` 的任務最多 1024 個（Swoole 限制）。
</Warning>

## Tick 與 Interval（僅 Swoole）

在 Swoole 中，可註冊以指定間隔定期執行的處理。請在服務提供者的 `boot` 方法中註冊。

```php theme={null}
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](https://www.swoole.co.uk/docs/modules/swoole-table) 的超高速記憶體內快取。每秒最多可讀寫 200 萬次。

```php theme={null}
use Illuminate\Support\Facades\Cache;

Cache::store('octane')->put('framework', 'Laravel', 30);
```

### Interval 快取

以指定間隔自動更新的快取。

```php theme={null}
use Illuminate\Support\Str;

Cache::store('octane')->interval('random', function () {
    return Str::random(10);
}, seconds: 5);
```

<Warning>
  Octane 快取的資料在伺服器重啟後會全部清除。
</Warning>

## Swoole Table（僅 Swoole）

可定義任何 worker 皆可存取的自訂記憶體內資料表。透過 `config/octane.php` 的 `tables` 進行設定。

```php theme={null}
'tables' => [
    'example:1000' => [
        'name' => 'string:1000',
        'votes' => 'int',
    ],
],
```

存取資料表時使用 `Octane::table()` 方法。

```php theme={null}
use Laravel\Octane\Facades\Octane;

Octane::table('example')->set('uuid', [
    'name' => 'Nuno Maduro',
    'votes' => 1000,
]);

$row = Octane::table('example')->get('uuid');
```

<Warning>
  Swoole table 支援的欄位型別僅有 `string`、`int`、`float`。資料會在伺服器重啟時消失。
</Warning>

## 正式環境的運作

### Nginx + Octane 的架構

正式環境中通常會在 Nginx 後方執行 Octane。Nginx 負責靜態檔案的傳遞與 SSL 終止，並將動態請求 proxy 至 Octane。

```nginx theme={null}
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 常駐啟動。

```ini theme={null}
[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` 中設定以下項目。

```ini theme={null}
OCTANE_HTTPS=true
```

### 與 Laravel Cloud 整合

[Laravel Cloud](https://cloud.laravel.com) 提供使用 FrankenPHP 的 Octane 完整託管支援。無需設定 Nginx 或 Supervisor，只需兩個步驟即可啟用 Octane。

<Steps>
  <Step title="安裝套件">
    安裝 Octane。`octane:install` 指令可以執行，但並非必要。

    ```bash theme={null}
    composer require laravel/octane
    ```
  </Step>

  <Step title="在 Laravel Cloud 啟用 Octane">
    開啟環境中 App 運算叢集的設定，將 **「Use Octane as runtime」** 開啟並儲存部署。Laravel Cloud 會自動以 FrankenPHP + Octane 建置並啟動應用程式。
  </Step>
</Steps>

詳情請參考 [Laravel Cloud 文件](https://cloud.laravel.com/docs/compute#laravel-octane)。

### 部署後重新載入 worker

部署後為了將新程式碼載入記憶體，需重新載入 worker。

```bash theme={null}
php artisan octane:reload
```


## Related topics

- [Laravel Cloud — Laravel 專用 PaaS 全貌](/zh-TW/blog/laravel-cloud.md)
- [用 Laravel 構建 MCP 伺服器](/zh-TW/advanced/mcp-server.md)
- [部署](/zh-TW/deployment.md)
- [Service Container](/zh-TW/service-container.md)
- [Laravel Telescope](/zh-TW/telescope.md)
