動態

詳情 返回 返回

使用swoole部署websocket服務端 - 動態 詳情

使用swoole部署websocket服務端

Swoole 支持在同一個 WebSocket 服務中監聽多個端口,併為不同端口配置不同的協議(ws 或 wss)。只需在創建 Swoole\WebSocket\Server 時通過 addListener() 方法添加額外端口,並分別配置 SSL 證書即可。

方式一:直接起兩個服務端口(不推薦)

方式一實現示例代碼:

<?php
// 創建主服務器(默認不配置 SSL,作為 ws 服務)
$ws = new Swoole\WebSocket\Server("0.0.0.0", 9501);

// 為主服務器添加 SSL 配置的端口(9502 作為 wss 服務)
// 注意:第二個參數需指定 SWOOLE_SSL 標記
$ws->addListener("0.0.0.0", 9502, SWOOLE_SOCK_TCP | SWOOLE_SSL);

// 配置 SSL 證書(僅對 9502 端口生效)
$ws->set([
    'ssl_cert_file' => __DIR__ . '/cert.pem',   // SSL 證書文件路徑
    'ssl_key_file'  => __DIR__ . '/key.pem',    // SSL 私鑰文件路徑
    'worker_num'    => 4,                       // 工作進程數
]);

// 監聽連接打開事件
$ws->on('Open', function ($ws, $request) {
    // 可以通過 $request->fd 區分不同客户端
    // 可以通過 $request->server['server_port'] 判斷客户端連接的端口
    echo "客户端 {$request->fd} 連接成功,端口:{$request->server['server_port']}\n";
});

// 監聽消息事件
$ws->on('Message', function ($ws, $frame) {
    // 向客户端回覆消息
    $ws->push($frame->fd, "服務器收到:{$frame->data}");
    echo "收到來自 fd={$frame->fd} 的消息:{$frame->data}\n";
});

// 監聽連接關閉事件
$ws->on('Close', function ($ws, $fd) {
    echo "客户端 {$fd} 斷開連接\n";
});

// 啓動服務
$ws->start();
?>

關鍵説明:

  1. 多端口監聽:

    • 主服務通過 new Swoole\WebSocket\Server("0.0.0.0", 9501) 監聽 9501 端口(默認不啓用 SSL,即 ws:// 服務)。
    • 通過 addListener() 方法添加 9502 端口,並指定 SWOOLE_SSL 標記,使其成為 wss:// 服務。
  2. SSL 配置:

    • ssl_cert_file 和 ssl_key_file 需填寫正確的證書和私鑰路徑(自簽名證書可用於測試,生產環境需用可信 CA 證書)。
    • SSL 配置會自動應用到帶有 SWOOLE_SSL 標記的端口(即 9502 端口),9501 端口不受影響。
  3. 客户端連接方式:

    • 連接 9501 端口:ws://your_domain.com:9501
    • 連接 9502 端口:wss://your_domain.com:9502
  4. 端口區分:

    • 在事件回調中,可通過 $request->server['server_port'] 判斷客户端連接的是哪個端口(9501 或 9502),便於區分處理。

注意事項:

  1. 需確保服務器防火牆開放 9501 和 9502 端口。
  2. 生產環境中,建議通過 Nginx 反向代理 wss:// 到後端的 ws:// 服務(更便於證書管理和負載均衡),直接暴露多端口的場景較少。
    這種方式可以在同一個 Swoole 服務中同時提供 ws 和 wss 兩種連接方式,適合需要同時支持明文和加密連接的場景。

方式二:通過nginx反向代理(推薦)

在生產環境中通過nginx反向代理, 可以讓後端 Swoole WebSocket 服務僅監聽 127.0.0.1:9501, 來同時實現對wss://和ws://兩種連接的支持.

具體實現方式

通過 Nginx 配置兩條代理規則,分別處理 wss://(加密)和 ws://(明文)連接,最終都轉發到後端同一個 ws://127.0.0.1:9501 服務。

示例nginx配置:

server {
    # 同時監聽 80 端口(HTTP/ws)和 443 端口(HTTPS/wss)
    listen 80;
    listen 443 ssl;
    server_name your_domain.com;

    # SSL 證書配置(僅對 443 端口生效)
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # 處理 WebSocket 代理(同時支持 ws 和 wss)
    location /ws {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        # 轉發到後端同一個 ws 服務
        proxy_pass http://127.0.0.1:9501;
    }

}

後端Swoole服務配置:

只需監聽本地 127.0.0.1:9501(不暴露公網,僅通過 Nginx 代理訪問):

$ws = new Swoole\WebSocket\Server("127.0.0.1", 9501);  // 僅監聽本地端口
// ... 事件回調配置 ...
$ws->start();

這裏nginx是通過location的/ws進行匹配的

因此如下的請求地址可以匹配到/ws中的規則並將連接進行升級
ws:/your-domain/ws
wss://your-domain/ws
http:/your-domain/ws
而直接使用下面的連接是不能直接進行匹配並升級成websocket連接的
ws://your-domain
wss://your-domain

核心原理

  1. wss://連接流程:

    • 客户端發起 wss://your_domain.com/ws 連接 → 經過 Nginx 443 端口。
    • Nginx 用 SSL 證書解密 → 將明文數據轉發到 ws://127.0.0.1:9501。
    • 後端 Swoole 服務處理明文 ws 數據,響應通過 Nginx 加密後返回給客户端。
  2. ws:// 連接流程:

    • 客户端發起 ws://your_domain.com/ws 連接 → 經過 Nginx 80 端口。
    • Nginx 直接將明文數據轉發到 ws://127.0.0.1:9501。
    • 後端 Swoole 服務直接處理並響應。

    優勢

    • 後端簡化:只需維護一個 ws 服務,無需處理 SSL 證書,降低複雜度。
    • 安全可控:後端服務僅監聽本地端口,不直接暴露公網,通過 Nginx 統一入口管理。
    • 靈活擴展:未來如需調整端口或增加負載均衡,僅需修改 Nginx 配置,無需改動後端服務。

    注意事項

    • 若需要禁止 ws:// 明文連接(僅允許 wss://),可刪除 80 端口的 Nginx 配置,或在 80 端口配置中將 ws:// 請求重定向到 wss://。
    • 確保 Nginx 的 proxy_pass 路徑與後端服務的監聽地址一致(如均為 9501 端口)。
user avatar ljc1212 頭像 chunzhendegaoshan 頭像 feichangkudechongfengyi 頭像 mengxiang_592395ab95632 頭像
點贊 4 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.