:Nginx 與 Gateway 協(xié)同部署指南)
1. 項目概述為什么 WSS 配置成了 GatewayWorker 項目上線前的“最后一道關卡”GatewayWorker 是國內 PHP 社區(qū)廣泛采用的長連接服務解決方案它用 Swoole 實現(xiàn)了 Gateway、BusinessWorker、Register 三進程模型把 WebSocket 連接管理、業(yè)務邏輯處理、服務注冊發(fā)現(xiàn)做了清晰分層。很多團隊在開發(fā)實時通知、在線客服、協(xié)同編輯、IoT 設備心跳上報這類功能時第一反應就是上 GatewayWorker——因為它文檔齊、生態(tài)熟、配合 ThinkPHP 或 Laravel 做業(yè)務層非常順手。但真正走到部署階段90% 的人會卡在同一個地方本地ws://跑得飛起一上生產環(huán)境切到wss://就連不上控制臺報錯net::ERR_CONNECTION_CLOSED或WebSocket connection to wss://... failedGateway 日志里卻安靜得像沒這回事。這個問題不是偶發(fā)而是有明確技術動因的WSS 不是簡單給 WebSocket 加個 SSL它是建立在 TLS 協(xié)議之上的完整加密通道要求從客戶端發(fā)起請求到反向代理如 Nginx再到 GatewayWorker 的 Worker 進程每一環(huán)都必須正確識別、透傳、終止或協(xié)商 TLS。而 GatewayWorker 本身不內置 HTTPS 服務能力——它的 Worker 進程只監(jiān)聽純 TCP 端口比如 2121所有 TLS 解密工作必須由前置組件完成。這就引出了最典型的配置失配Nginx 配置了 SSL但沒正確轉發(fā) WebSocket 升級頭或者 Nginx 轉發(fā)了但 GatewayWorker 的gateway.php配置里ssl相關參數(shù)全為 false又或者證書路徑寫錯、權限不足、Swoole 版本不支持 TLS 1.3……每一個看似微小的疏漏都會讓整個 WSS 鏈路在握手階段就靜默失敗。我最近在一個在線教育平臺的直播互動模塊中復現(xiàn)了全部典型問題。這個項目需要支撐 5000 并發(fā)學生端實時接收答題倒計時、教師端廣播白板操作、后臺監(jiān)控連接健康度——對連接穩(wěn)定性、首包延遲、斷線重連成功率要求極高。我們前期在測試環(huán)境用ws://跑通了全部邏輯但正式灰度前切換 WSS 時花了整整三天才定位到根源Nginx 的proxy_set_header Upgrade $http_upgrade;這一行被注釋掉了而開發(fā)同學誤以為“SSL 配好了WebSocket 就自動好了”。這種認知偏差在中小團隊中極其普遍。所以這篇紀實不講原理推導也不堆砌 RFC 文檔只聚焦真實生產環(huán)境里你馬上會遇到的配置項、報錯日志、驗證命令和繞過陷阱的實操路徑。無論你是剛接觸 GatewayWorker 的 PHP 開發(fā)者還是負責部署的運維同學只要你的項目需要對外提供wss://接口這篇內容就能幫你省下至少 8 小時排查時間。2. 整體架構與配置思路三層解耦是 WSS 可靠性的底層前提要理解 GatewayWorker 的 WSS 配置為什么容易出錯必須先厘清它的標準生產部署結構。這不是一個單體服務而是一個典型的“前端卸載 后端專注”的三層協(xié)作模型最外層反向代理Nginx / Apache / Caddy它是用戶直接訪問的入口承擔 SSL 證書加載、HTTP/HTTPS 請求終止、WebSocket 協(xié)議升級協(xié)商、負載均衡、靜態(tài)資源托管等職責。它不處理任何業(yè)務邏輯只做“流量翻譯官”。中間層Gateway 進程它運行在獨立端口如 8282負責維持與所有客戶端的長連接做心跳檢測、連接數(shù)統(tǒng)計、IP 黑白名單、消息廣播等網(wǎng)關級功能。它通過register進程與 BusinessWorker 通信但自身不解析業(yè)務數(shù)據(jù)。最內層BusinessWorker 進程它監(jiān)聽另一個端口如 2121只接收來自 Gateway 的已認證、已解包的業(yè)務消息例如{type:submit_answer,data:{...}}執(zhí)行數(shù)據(jù)庫操作、調用第三方 API、觸發(fā)事件總線等。它完全不知道 TLS 是什么只認 TCP 流。WSS 的核心難點就在于這三層之間存在兩個關鍵“協(xié)議轉換點”客戶端 ? Nginx這是標準的 HTTPS WebSocket Upgrade 流程。客戶端發(fā)送GET /websocket HTTP/1.1Upgrade: websocketSec-WebSocket-Key頭Nginx 必須原樣透傳這些頭并返回101 Switching Protocols同時將后續(xù)二進制幀流持續(xù)轉發(fā)給后端。Nginx ? GatewayWorker這里必須是明文 TCP 連接。Nginx 解密完 TLS 后把原始的 HTTP Upgrade 請求不含 TLS 層以明文形式發(fā)給 Gateway 進程監(jiān)聽的端口。Gateway 進程收到的是干凈的 WebSocket 握手請求它再按標準流程響應101并升級為 WebSocket 連接。提示很多人誤以為 GatewayWorker 也要開 TLS 端口于是去改gateway.php里的ssl true并填證書路徑。這是根本性錯誤。GatewayWorker 的 SSL 配置僅在一種場景下有效當你跳過 Nginx讓客戶端直連 Gateway 進程即wss://your-domain.com:8282。但生產環(huán)境絕不能這么做——沒有反向代理你就失去了證書自動續(xù)期、DDoS 緩沖、HTTP/2 支持、日志審計等關鍵能力。所以ssl true在標準架構中應永遠為false。那么正確的配置責任劃分就非常清晰了Nginx 全權負責 TLS 終止、證書管理、Upgrade 頭透傳GatewayWorker 專注 WebSocket 協(xié)議處理只與 Nginx 建立明文連接BusinessWorker 完全無感照常收發(fā) JSON 消息這種解耦帶來的最大好處是可維護性換證書只需改 Nginx 配置調優(yōu) WebSocket 參數(shù)只需改 Gateway 配置升級業(yè)務邏輯只需重啟 BusinessWorker——三者互不影響。而所有“踩坑”幾乎都源于打破了這個邊界比如在 Nginx 里忘了加Upgrade頭導致 Gateway 收到的是普通 HTTP 請求而非 WebSocket 握手或者在 Gateway 配置里誤啟了 SSL結果它試圖用明文端口去讀取證書文件啟動直接報錯。3. 核心配置項逐項拆解Nginx 與 GatewayWorker 的 7 個關鍵開關WSS 配置的成敗取決于 7 個具體配置項是否全部正確。少一個連接就建立不了錯一個日志里就找不到線索。下面我按實際部署順序把每個開關的作用、常見錯誤、驗證方法、修復方案說透。3.1 Nginx Server 塊SSL 證書與基礎 HTTPS 啟用這是整個 WSS 的起點。Nginx 必須能正常響應https://your-domain.com的普通 HTTPS 請求否則 WebSocket 根本沒機會發(fā)起。server { listen 443 ssl http2; server_name your-domain.com; # 證書路徑必須絕對準確且 Nginx 用戶通常是 www-data 或 nginx有讀取權限 ssl_certificate /etc/nginx/ssl/your-domain.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/your-domain.com/privkey.pem; # 強烈建議啟用 OCSP Stapling提升 TLS 握手速度 ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/your-domain.com/chain.pem; # TLS 版本與加密套件兼顧安全與兼容性 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # 其他常規(guī)配置... root /var/www/html; index index.php; }常見錯誤與排查證書路徑錯誤ls -l /etc/nginx/ssl/your-domain.com/看文件是否存在sudo -u www-data cat /etc/nginx/ssl/your-domain.com/fullchain.pem | head -n 1測試 Nginx 用戶能否讀取。如果報Permission denied執(zhí)行sudo chmod 644 /etc/nginx/ssl/your-domain.com/*.pem。證書鏈不完整用openssl s_client -connect your-domain.com:443 -servername your-domain.com 2/dev/null | openssl x509 -noout -text | grep CA Issuers檢查是否包含中間證書。若缺失fullchain.pem應為cert.pemchain.pem拼接。Nginx 未重載改完配置必須sudo nginx -t sudo systemctl reload nginx只reload不restart避免連接中斷。注意不要在ssl_certificate路徑里用相對路徑或~符號Nginx 啟動時工作目錄不固定必須用絕對路徑。3.2 Nginx Location 塊WebSocket 升級頭的精準透傳這是 WSS 失敗率最高的環(huán)節(jié)。Nginx 默認不會透傳Upgrade和Connection這兩個關鍵頭必須顯式聲明。location /websocket { # 關鍵必須開啟代理緩沖否則大消息會截斷 proxy_buffering off; # 關鍵透傳 WebSocket 升級所需的兩個頭 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 關鍵告訴后端這是 WebSocket 請求不是普通 HTTP proxy_http_version 1.1; # 后端 Gateway 進程地址必須是明文 HTTP非 HTTPS proxy_pass http://127.0.0.1:8282; # 超時設置WebSocket 是長連接不能沿用默認的 60s proxy_read_timeout 86400; proxy_send_timeout 86400; # 其他可選優(yōu)化 proxy_set_header Host $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; }為什么這三行缺一不可proxy_http_version 1.1WebSocket Upgrade 協(xié)議要求 HTTP/1.1HTTP/1.0 不支持。proxy_set_header Upgrade $http_upgrade$http_upgrade是 Nginx 內置變量值為客戶端發(fā)來的Upgrade頭內容通常是websocket。如果寫死成websocket當客戶端不帶此頭時會出錯如果省略后端收不到升級指令。proxy_set_header Connection upgradeConnection: upgrade是 HTTP/1.1 協(xié)議規(guī)定的升級觸發(fā)頭必須原樣傳遞。常見錯誤與排查忘記proxy_buffering offGatewayWorker 發(fā)送大消息如初始同步數(shù)據(jù)時Nginx 緩沖區(qū)滿會導致連接被靜默關閉?,F(xiàn)象是客戶端能連上但收不到第一條消息。tail -f /var/log/nginx/error.log會看到upstream sent too big header類似錯誤。proxy_pass寫成https://proxy_pass https://127.0.0.1:8282是致命錯誤。Gateway 進程監(jiān)聽的是明文端口Nginx 會嘗試用 HTTPS 去連它必然失敗。必須是http://。proxy_read_timeout過短設為 60 秒是常見錯誤。WebSocket 連接空閑時Nginx 會在 60 秒后主動斷開導致客戶端頻繁重連。設為8640024 小時是穩(wěn)妥選擇實際超時由 Gateway 的心跳機制控制。3.3 GatewayWorker 配置gateway.php中的 4 個核心參數(shù)GatewayWorker 的配置文件Applications/YourApp/Config/gateway.php是第二道防線。這里不需要開 SSL但必須確保與 Nginx 的通信方式完全匹配。return [ gateway [ class \GatewayWorker\Gateway, transport tcp, // 必須是 tcp不是 ssl ip 127.0.0.1, port 8282, count 4, lan_ip 127.0.0.1, start_port 2900, ping_interval 30, ping_not_response_limit 0, ping_data {type:ping}, // 關鍵必須為 false表示不啟用內置 SSL ssl false, // 關鍵必須與 Nginx 的 proxy_pass 地址一致 registerAddress 127.0.0.1:1238, ], businessWorker [ class \GatewayWorker\BusinessWorker, count 4, // 關鍵監(jiān)聽端口必須與 gateway.php 中 registerAddress 的端口一致 registerAddress 127.0.0.1:1238, ], register [ class \GatewayWorker\Register, ip 127.0.0.1, port 1238, ] ];關鍵參數(shù)詳解transport tcp明確指定傳輸層為 TCP。雖然默認就是 TCP但顯式寫出可避免歧義。ssl true時 transport 才是ssl。ssl false再次強調這是標準架構下的鐵律。設為true會導致 Gateway 啟動時報failed to open stream: No such file or directory找不到證書或SSL operation failed with code 1證書格式錯誤。registerAddressGateway 和 BusinessWorker 都必須指向同一個 Register 進程地址。這是三進程通信的“電話總機”地址不一致會導致業(yè)務消息無法送達。ping_interval心跳間隔。設為 30 秒是經驗值太短增加無效流量太長如 120 秒可能導致 Nginxproxy_read_timeout先于心跳觸發(fā)斷連。驗證方法啟動 GatewayWorker 后執(zhí)行netstat -tuln | grep :8282確認有tcp6 0 0 *:8282 *:* LISTEN。再執(zhí)行curl -i -N -H Connection: upgrade -H Upgrade: websocket http://127.0.0.1:8282/websocket如果返回HTTP/1.1 101 Switching Protocols說明 Gateway 本身 WebSocket 握手正常問題一定出在 Nginx 層。3.4 Swoole 版本與 OpenSSL 支持被忽視的底層依賴GatewayWorker 依賴 Swoole 擴展而 Swoole 的 WebSocket 服務器能力與 OpenSSL 版本強相關。很多“配置全對卻連不上”的案例根源在此。Swoole 4.5.0開始支持 TLS 1.3推薦使用 4.8.x 或 5.x 系列。OpenSSL 版本必須 ≥ 1.1.1。Ubuntu 18.04 自帶 OpenSSL 1.1.1但 CentOS 7 默認是 1.0.2k不支持 TLS 1.3會導致 Nginx 與 Gateway 通信異常。驗證命令# 查看 Swoole 版本與編譯參數(shù) php --ri swoole | grep -E (Version|OpenSSL) # 查看系統(tǒng) OpenSSL 版本 openssl version # 檢查 Swoole 是否鏈接了正確的 OpenSSL ldd $(php-config --extension-dir)/swoole.so | grep ssl輸出示例正確swoole support enabled Version 5.0.3 OpenSSL OpenSSL 1.1.1w 11 Sep 2023 ...錯誤場景與修復如果php --ri swoole顯示OpenSSL Disabled說明編譯 Swoole 時沒找到 OpenSSL 開發(fā)庫。Ubuntu 上執(zhí)行sudo apt install libssl-devCentOS 上執(zhí)行sudo yum install openssl-devel然后重新編譯安裝 Swoole。如果OpenSSL版本是1.0.2k必須升級系統(tǒng) OpenSSL 或更換發(fā)行版。強行用舊版 OpenSSL 會導致 TLS 握手失敗Nginx 錯誤日志出現(xiàn)upstream prematurely closed connection while reading response header from upstream。3.5 客戶端連接 URL協(xié)議、域名、端口的三位一體校驗客戶端代碼里的一行new WebSocket(wss://...)是整個鏈條的發(fā)起點也是最容易寫錯的地方。// ? 正確協(xié)議 wss域名與 Nginx server_name 一致路徑與 location 匹配 const ws new WebSocket(wss://your-domain.com/websocket); // ? 錯誤1協(xié)議寫成 ws本地調試可用生產必須 wss const ws new WebSocket(ws://your-domain.com/websocket); // ? 錯誤2域名不匹配如用了 IP 或子域名但 Nginx 沒配 server_name const ws new WebSocket(wss://192.168.1.100/websocket); // ? 錯誤3路徑不匹配Nginx location 是 /ws客戶端寫了 /websocket const ws new WebSocket(wss://your-domain.com/ws);驗證方法在瀏覽器開發(fā)者工具 Network 標簽頁過濾WS點擊連接看 Initiator 列是否顯示wss://your-domain.com/websocket。如果顯示ws://檢查前端構建配置如 Vue CLI 的devServer.proxy或 Webpack 的resolve.alias是否在生產環(huán)境注入了錯誤的協(xié)議。3.6 防火墻與安全組云服務器的隱形攔路虎本地curl能通但線上連不上90% 是防火墻擋的。云服務器阿里云、騰訊云、AWS的安全組默認只放行 80/443而 GatewayWorker 的 8282 端口是內部通信端口絕對不能開放給公網(wǎng)。但很多人誤操作把 8282 加到了安全組白名單結果 Nginx 無法訪問本地 8282因為流量被安全組規(guī)則攔截了。正確做法Nginx 與 GatewayWorker 在同一臺機器無需開放 8282 端口127.0.0.1訪問走本地回環(huán)不受安全組影響。Nginx 與 GatewayWorker 在不同機器如 Nginx 在 LBGateway 在應用服務器必須在應用服務器的安全組中僅允許 Nginx 服務器的內網(wǎng) IP 訪問 8282 端口禁止0.0.0.0/0。驗證命令在 Nginx 服務器上執(zhí)行# 測試能否 telnet 通 Gateway 服務器的 8282 端口 telnet gateway-server-ip 8282 # 如果不通檢查 Gateway 服務器防火墻 sudo ufw status verbose # Ubuntu sudo firewall-cmd --list-all # CentOS 8 # 確保有類似 allow 8282/tcp from nginx-ip 的規(guī)則3.7 日志分級與關聯(lián)快速定位故障環(huán)節(jié)的黃金法則WSS 故障排查本質是日志串聯(lián)。必須養(yǎng)成習慣一次連接失敗同時查看三處日志。日志位置查看命令關鍵線索Nginx error.logsudo tail -f /var/log/nginx/error.logupstream timed out超時、upstream refused端口拒絕、no live upstreams后端宕機GatewayWorker logstail -f Applications/YourApp/Logs/gateway-worker.logGateway started啟動成功、onConnect連接建立、onClose連接關閉、SSL handshake failed如果誤啟了 SSL瀏覽器 ConsoleF12 → ConsoleWebSocket connection to wss://... failed客戶端層面、Failed to construct WebSocket: An insecure WebSocket connection may not be initiated from a page loaded over HTTPS協(xié)議混用實戰(zhàn)技巧在 GatewayWorker 的Events.php中加入詳細日志public static function onConnect($client_id) { \GatewayWorker\Lib\Gateway::log(Client {$client_id} connected from {$_SERVER[REMOTE_ADDR]}); // 記錄 User-Agent判斷是否是爬蟲或異常客戶端 \GatewayWorker\Lib\Gateway::log(User-Agent: {$_SERVER[HTTP_USER_AGENT]}); }在 Nginx 配置中添加自定義日志格式記錄 WebSocket 升級狀態(tài)log_format websocket $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_upgrade $http_connection; access_log /var/log/nginx/websocket.log websocket;4. 實操過程全記錄從零部署一個可驗證的 WSS 服務現(xiàn)在我們把前面所有知識點串起來走一遍完整的、可立即復現(xiàn)的部署流程。以下步驟基于 Ubuntu 22.04 PHP 8.1 Swoole 5.0.3 Nginx 1.18 環(huán)境所有命令均可復制粘貼執(zhí)行。4.1 環(huán)境準備安裝基礎依賴與 Swoole# 更新系統(tǒng) sudo apt update sudo apt upgrade -y # 安裝 PHP 及常用擴展 sudo apt install -y php8.1-cli php8.1-mbstring php8.1-curl php8.1-xml php8.1-zip # 安裝 OpenSSL 開發(fā)庫編譯 Swoole 必需 sudo apt install -y libssl-dev # 安裝 Composer curl -sS https://getcomposer.org/installer | sudo php -- --install-dir/usr/local/bin --filenamecomposer # 安裝 Swoole推薦 PECL自動處理依賴 sudo pecl install swoole # 安裝過程中如果提示 Enable OpenSSL support? [no] :輸入 yes 并回車 # 啟用 Swoole 擴展 echo extensionswoole.so | sudo tee /etc/php/8.1/cli/conf.d/20-swoole.ini echo extensionswoole.so | sudo tee /etc/php/8.1/fpm/conf.d/20-swoole.ini # 重啟 PHP-FPM sudo systemctl restart php8.1-fpm驗證 Swoolephp --ri swoole | grep -E (Version|OpenSSL) # 輸出應包含 Version 5.0.3 和 OpenSSL OpenSSL 1.1.1w4.2 下載并初始化 GatewayWorker 項目# 創(chuàng)建項目目錄 mkdir -p /var/www/gateway-demo cd /var/www/gateway-demo # 使用 Composer 創(chuàng)建 GatewayWorker 項目官方推薦方式 composer create-project workerman/gatewayworker:4.1.0 . # 初始化應用結構 php start.php start -d # 此時應看到 Gateway start success但這是臨時啟動我們馬上要配置 # 停止臨時服務 php start.php stop4.3 配置 Nginx生成可直接使用的 server 塊創(chuàng)建/etc/nginx/sites-available/gateway-demoupstream gateway_backend { server 127.0.0.1:8282; } server { listen 80; server_name gateway-demo.local; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name gateway-demo.local; # 為本地測試生成自簽名證書生產環(huán)境請用 Lets Encrypt ssl_certificate /etc/nginx/ssl/gateway-demo.local.crt; ssl_certificate_key /etc/nginx/ssl/gateway-demo.local.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers off; # WebSocket 專用 location location /websocket { proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_pass http://gateway_backend; proxy_read_timeout 86400; proxy_send_timeout 86400; proxy_set_header Host $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; } # 其他靜態(tài)資源 root /var/www/gateway-demo/Web; index index.html; }生成自簽名證書僅用于本地測試sudo mkdir -p /etc/nginx/ssl sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/nginx/ssl/gateway-demo.local.key \ -out /etc/nginx/ssl/gateway-demo.local.crt \ -subj /CCN/STBeijing/LBeijing/ODemo/CNgateway-demo.local啟用站點sudo ln -sf /etc/nginx/sites-available/gateway-demo /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx4.4 配置 GatewayWorker修改gateway.php與start.php編輯/var/www/gateway-demo/Applications/GatewayDemo/Config/gateway.phpreturn [ gateway [ class \GatewayWorker\Gateway, transport tcp, ip 127.0.0.1, port 8282, count 2, lan_ip 127.0.0.1, start_port 2900, ping_interval 30, ping_not_response_limit 0, ping_data {type:ping}, // 關鍵必須為 false ssl false, registerAddress 127.0.0.1:1238, ], businessWorker [ class \GatewayWorker\BusinessWorker, count 2, registerAddress 127.0.0.1:1238, ], register [ class \GatewayWorker\Register, ip 127.0.0.1, port 1238, ] ];編輯/var/www/gateway-demo/start.php確保use GatewayWorker\Autoloader;在頂部并在start()函數(shù)前添加// 設置時區(qū)避免日志時間錯亂 date_default_timezone_set(Asia/Shanghai);4.5 啟動服務并驗證連接# 啟動 GatewayWorker守護進程模式 cd /var/www/gateway-demo php start.php start -d # 查看進程是否運行 ps aux | grep GatewayWorker # 查看 Gateway 日志 tail -f /var/www/gateway-demo/Applications/GatewayDemo/Logs/gateway-worker.log # 應看到 Gateway started 和 Register started # 測試 Nginx 到 Gateway 的連通性在服務器本地執(zhí)行 curl -i -N -H Connection: upgrade -H Upgrade: websocket http://127.0.0.1:8282/websocket # 應返回 HTTP/1.1 101 Switching Protocols # 測試 WSS 連接在另一臺機器或瀏覽器中 # 訪問 https://gateway-demo.local打開開發(fā)者工具 Console執(zhí)行 # const ws new WebSocket(wss://gateway-demo.local/websocket); # ws.onopen () console.log(Connected!); # ws.onerror (e) console.error(Error:, e);如果瀏覽器報錯ERR_CONNECTION_REFUSED檢查sudo netstat -tuln | grep :8282確認 Gateway 進程在監(jiān)聽。檢查sudo nginx -t確認 Nginx 配置語法正確。檢查/var/log/nginx/error.log看是否有connect() failed (111: Connection refused)說明 Nginx 連不上 8282。如果瀏覽器報錯ERR_SSL_PROTOCOL_ERROR檢查curl -I https://gateway-demo.local確認 HTTPS 基礎服務正常。檢查證書路徑是否正確ls -l /etc/nginx/ssl/看文件是否存在。4.6 前端驗證頁面一個最小可運行的 HTML在/var/www/gateway-demo/Web/index.html中寫入!DOCTYPE html html head titleGatewayWorker WSS Test/title /head body h1GatewayWorker WSS 連接測試/h1 div idstatus等待連接.../div button onclickconnect()連接/button button onclicksend() disabled idsendBtn發(fā)送消息/button divtextarea idmsg rows2 cols50Hello from browser!/textarea/div script let ws; function connect() { const url wss://gateway-demo.local/websocket; ws new WebSocket(url); ws.onopen function() { document.getElementById(status).innerText ? 已連接; document.getElementById(sendBtn).disabled false; }; ws.onmessage function(event) { console.log(收到:, event.data); document.getElementById(status).innerText 收到: event.data; }; ws.onclose function() { document.getElementById(status).innerText ? 連接已關閉; document.getElementById(sendBtn).disabled true; }; ws.onerror function(error) { console.error(WebSocket 錯誤:, error); document.getElementById(status).innerText ? 連接錯誤: error; }; } function send() { const msg document.getElementById(msg).value; if (ws ws.readyState WebSocket.OPEN) { ws.send(msg); document.getElementById(status).innerText 已發(fā)送: msg; } } /script /body /html訪問https://gateway-demo.local點擊“連接”即可看到實時連接狀態(tài)和消息收發(fā)。5. 常見問題與排查技巧實錄那些讓你抓狂的“幽靈錯誤”在多個項目的 WSS 部署中我整理出一份高頻問題速查表。這些問題往往沒有明確報錯或者報錯信息極具誤導性必須結合上下文才能定位。5.1 問題速查表癥狀、原因、驗證命令、修復方案癥狀可能原因驗證命令修復方案瀏覽器控制臺報net::ERR_CONNECTION_CLOSEDNginx error.log 為空Nginx 的proxy_pass指向了錯誤的端口如 2121 而非 8282或 Gateway 進程未啟動sudo netstat -tuln | grep :8282curl -i http://127.0.0.1:8282/websocket確認gateway.php中port與 Nginxproxy_pass端口一致執(zhí)行php start.php start -d啟動 Gateway連接能建立但 30 秒后自動斷開onClose日志頻繁出現(xiàn)Nginxproxy_read_timeout過短或 Gatewayping_interval與 Nginx timeout 不匹配grep proxy_read_timeout /etc/nginx/sites-available/*grep ping_interval /var/www/gateway-demo/Applications/*/Config/gateway.php將 Nginxproxy_read_timeout設為86400Gatewayping_interval設為30確保 Nginx timeout 3 × ping_intervalNginx error.log 報upstream prematurely closed connectionGatewayWorker 進程崩潰退出或 Swoole 版本與 OpenSSL 不兼容sudo systemctl status php8.1-fpmphp --ri swoole | grep OpenSSL升級 Swoole 至 5.x確保 OpenSSL ≥ 1.1.1檢查 Gateway 日志是否有 Segmentation fault