Nginx代理WebSocket失敗的完整排查過程
問題現(xiàn)象
- 后端服務(wù)運(yùn)行在
192.168.1.10:8080,提供 WebSocket 接口/ws/xxx - 使用
wscat或?yàn)g覽器直連ws://192.168.1.10:8080/ws/xxx? 成功 - 配置 Nginx 反向代理后,前端連接
ws://localhost/ws/xxx? 失敗 - 瀏覽器 Network 面板顯示 WebSocket 請求失?。o 101 響應(yīng))
- 關(guān)鍵線索:Nginx 的
access_log中 沒有任何 WebSocket 請求日志
初步懷疑:Nginx 配置錯(cuò)誤?
首先檢查 Nginx 配置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream webservers {
server 192.168.1.10:8080;
}
server {
listen 80;
server_name localhost;
location /ws/ {
proxy_pass http://webservers/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade"; # ?? 這里有坑!
proxy_read_timeout 3600s;
}
}
常見錯(cuò)誤包括:
Connection頭加了雙引號 → 變成字面量map沒放在http塊頂層- 缺少
proxy_buffering off
但即使修正這些,日志依然為空,說明:請求根本沒到 Nginx!
關(guān)鍵轉(zhuǎn)折:前端頁面來源被忽略
通過 docker ps 確認(rèn)端口映射正常:
nginx 0.0.0.0:80->80/tcp
但發(fā)現(xiàn)一個(gè)致命細(xì)節(jié):
前端頁面是通過虛擬機(jī) IP 打開的:http://192.168.228.128/
而 WebSocket 地址寫的是:ws://localhost/ws/xxx
問題本質(zhì)
- 瀏覽器中的
localhost永遠(yuǎn)指向客戶端本機(jī)(Windows 電腦) - 而我的 Nginx 運(yùn)行在 虛擬機(jī)中
- 所以
ws://localhost/...實(shí)際請求的是 我 Windows 的 80 端口,而非虛擬機(jī)!
→ 請求壓根沒發(fā)給 Nginx,自然沒有日志!
解決方案
方法 1:顯式指定虛擬機(jī) IP(臨時(shí)可用)
// 前端 JS
const ws = new WebSocket('ws://192.168.228.128/ws/xxx');
立即生效!
方法 2:使用相對路徑(推薦 ?)
// 自動繼承當(dāng)前頁面的 host
const ws = new WebSocket('/ws/xxx');
優(yōu)勢:
- 頁面在
http://localhost→ 連ws://localhost - 頁面在
http://192.168.228.128→ 連ws://192.168.228.128 - 部署到域名也無需修改代碼
附:正確的 Nginx 配置模板
http {
# 必須在 http 塊頂層!
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream backend {
server host.docker.internal:8080; # Docker Desktop 推薦
# 或 server 192.168.1.10:8080;
}
server {
listen 80;
server_name _; # 匹配任意 Host
location / {
root /usr/share/nginx/html;
index index.html;
}
location /ws/ {
access_log /var/log/nginx/ws_access.log;
proxy_pass http://backend/ws/;
proxy_http_version 1.1;
proxy_buffering off; # 必須關(guān)閉
proxy_cache off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; # 無引號!
proxy_read_timeout 3600s;
}
}
}
經(jīng)驗(yàn)總結(jié)
| 問題類型 | 排查要點(diǎn) |
|---|---|
| Nginx 無日志 | 先確認(rèn)請求是否真的發(fā)到了 Nginx(檢查前端地址、端口映射) |
| WebSocket 426 | 檢查 Upgrade 和 Connection 頭是否正確傳遞 |
| 前端連接失敗 | 確保 WebSocket 地址與頁面同源(避免硬編碼 localhost) |
| Docker 環(huán)境 | 用 host.docker.internal 代替 IP 更可靠 |
最后提醒
localhost 在前端代碼中 ≠ 你的服務(wù)器!
它永遠(yuǎn)指向用戶瀏覽器所在的機(jī)器。
開發(fā)時(shí)務(wù)必注意頁面來源與 WebSocket 目標(biāo)的匹配關(guān)系,這是 WebSocket 代理失敗的最高頻原因。
結(jié)語
從“426 Upgrade Required”到“連接成功”,看似是配置問題,實(shí)則是網(wǎng)絡(luò)拓?fù)淅斫馄?/strong>。希望本文能幫你少走彎路!
到此這篇關(guān)于Nginx代理WebSocket失敗的完整排查過程的文章就介紹到這了,更多相關(guān)Nginx代理WebSocket失敗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nginx http模塊數(shù)據(jù)存儲結(jié)構(gòu)小結(jié)
這篇文章主要介紹了nginx http模塊數(shù)據(jù)存儲結(jié)構(gòu)小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
使用nginx配置基于域名的虛擬主機(jī)實(shí)現(xiàn)
這篇文章主要介紹了nginx配置基于域名的虛擬主機(jī)實(shí)現(xiàn)​,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Nginx配置統(tǒng)計(jì)流量帶寬請求及記錄實(shí)時(shí)請求狀態(tài)的方法
這篇文章主要介紹了Nginx中配置統(tǒng)計(jì)流量帶寬請求及記錄實(shí)時(shí)請求狀態(tài)的方法,分別用到了ngx_req_status和ngx_realtime_request模塊,需要的朋友可以參考下2016-01-01
Linux部署Nginx實(shí)現(xiàn)反向代理的方法步驟
Nginx 是一種常用、輕型且快速的 Web 服務(wù)器, 它可以在 Linux 和 Windows 上運(yùn)行,并且可以配置為反向代理服務(wù)器,本文主要介紹了Linux部署Nginx實(shí)現(xiàn)反向代理的方法步驟,感興趣的可以了解一下2023-08-08
Nginx出現(xiàn)403錯(cuò)誤,應(yīng)該如何解決
這篇文章主要介紹了Nginx出現(xiàn)403錯(cuò)誤,應(yīng)該如何解決?具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

