2025年12月27日 星期六

Laravel 12 WebSocket (Reverb) 容器化全攻略:Nginx 反向代理實戰

Laravel 12 WebSocket (Reverb) 容器化全攻略:Nginx 反向代理實戰

1. 目標 (Objective)

Laravel 12 中,官方推出了由 PHP 原生驅動的極速 WebSocket 伺服器 —— Reverb。但在容器化環境下,如何協調 NginxPHP-FPM 與 Reverb 之間的流量轉發,是開發者面臨的首要挑戰。

本文旨在建立一套穩定的 Docker 化架構,透過 Nginx 統一入口,實現 HTTP (PHP-FPM)WS (Reverb) 的精準分流,並確保在高併發連線下的穩定性。


2. 技術亮點 (Technical Highlights)

  • PHP 8.4 常駐監聽:利用 PHP 8.4 的非阻塞特性,讓 Reverb 處理萬級併發連線。

  • Nginx 協議升級 (101 Switching Protocols):精確配置 Upgrade 標頭,實現從 HTTP 到 WebSocket 的無縫切換。

  • 服務解耦:將 Web 應用與 WebSocket 伺服器拆分為獨立容器,提升系統可擴展性。

  • pcntl 併發控制:在 Dockerfile 中強化進程管理擴充,確保 Reverb 具備處理多工任務的能力。


3. 架構圖描述 (Architecture Diagram)

Nginx 作為反向代理,根據 URL 路徑將請求分發至不同的容器:

Plaintext
[ Client Browser ]
       │
       ▼ (Port 80 / 443)
[ Nginx (Reverse Proxy) ]
       │
       ├─── [ / ] ──▶ (FastCGI) ──▶ [ App Container (PHP 8.4-FPM) ]
       │
       └─── [ /app ] ── (WS) ───▶ [ Reverb Container (Port 8080) ]

4. Nginx 配置:關鍵的協議升級

nginx/default.conf 中,必須特別處理 Reverb 的專屬路徑。請注意,Reverb 預設使用 /app 作為連接端點。

Nginx
server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;
    index index.php;

    # WebSocket 核心轉發邏輯
    location /app {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 必須包含以下兩行以實現 WebSocket 握手
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_read_timeout 86400s; # 避免長連線因逾時中斷
        proxy_pass http://reverb:8080;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass app:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

5. Docker 編排實戰 (docker-compose.yml)

我們使用同一個 PHP 8.4 鏡像來啟動兩個不同的服務:一個負責處理 Web 請求,另一個負責 Reverb 守護進程。

YAML
services:
  app:
    build: .
    container_name: laravel-app
    volumes:
      - .:/var/www/html
    depends_on:
      - redis

  reverb:
    build: .
    container_name: laravel-reverb
    # 核心指令:啟動 Reverb 並監聽所有網路介面
    command: php artisan reverb:start --host=0.0.0.0 --port=8080
    volumes:
      - .:/var/www/html
    depends_on:
      - app

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - .:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - reverb

6. 流程圖描述 (Flowchart)

  1. 事件觸發:Laravel 後端觸發 MessageSent 事件。

  2. 佇列分發:事件被推送到 Redis 佇列(建議生產環境必備)。

  3. 廣播推播Reverb 容器 監聽到事件,透過 WebSocket 持久連線將資料推至前端。

  4. 前端接收:瀏覽器端的 Laravel Echo 接收資料,透過 Vue 3 響應式更新介面。


7. 重要排錯與優化 (Troubleshooting)

  • PHP 8.4 擴充要求:

    確保 Dockerfile 中包含 pcntl。Reverb 依賴此擴充來管理進程訊號與併發處理。

    Dockerfile
    RUN docker-php-ext-install pcntl bcmath pdo_mysql
    
  • 環境變數對齊:

    在 .env 中,VITE_REVERB_HOST 應設定為用戶瀏覽器可存取的位址(如 localhost),而 REVERB_HOST(後端通訊用)則應設定為容器名稱 reverb。

  • Queue Worker 運作:

    若前端遲遲收不到訊息,請確認是否有容器正在執行 php artisan queue:work


8. 結論 (Conclusion)

透過 Laravel 12 ReverbDocker 的整合,我們徹底擺脫了對 Pusher 或第三方服務的依賴,實現了真正的「即時通訊自主」。這套架構不僅部署簡單,且在 Nginx 的反向代理下,具備了極佳的安全性與效能表現。

沒有留言:

張貼留言

AI 浪潮下的軟體業轉型:從「程式碼產出」到「價值驗證」的權力移轉

  前言:消失的「碼農」,崛起的「編排者」 過去兩年,媒體熱衷於討論 AI 是否會取代體力勞動者。然而,身處風暴中心的軟體從業人員心知肚明: 衝擊最深、速度最快的,其實是軟體產業。 AI 改變的不只是 IDE 裡的自動補全,它正在重塑軟體生產的「價值公式」。我們必須認清一個現實...