Nginx的WebSocket反向代理實(shí)踐過(guò)程
一、HTTP 協(xié)議升級(jí)機(jī)制回顧
- Upgrade/Connection 報(bào)頭
客戶端發(fā)起 WebSocket 握手時(shí),會(huì)在普通 HTTP 請(qǐng)求中加入
Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: <隨機(jī)值> Sec-WebSocket-Version: 13
服務(wù)端若接受協(xié)議切換,會(huì)以 101 Switching Protocols 響應(yīng),并同樣返回 Upgrade 和 Connection 報(bào)頭。
- Hop-by-Hop 報(bào)頭限制
HTTP/1.1 中,Upgrade 與 Connection 都屬于 Hop-by-Hop 報(bào)頭,只能在相鄰節(jié)點(diǎn)間生效,不會(huì)被普通反向代理轉(zhuǎn)發(fā)。因此,需要在 Nginx 明確地把這兩者從客戶端請(qǐng)求里取出,并再設(shè)置到轉(zhuǎn)發(fā)給后端的請(qǐng)求頭中。
二、Nginx 代理 WebSocket 的關(guān)鍵配置
1. 基本示例
location /chat/ {
# 將請(qǐng)求轉(zhuǎn)發(fā)到后端 WebSocket 服務(wù)
proxy_pass http://backend;
# 使用 HTTP/1.1 協(xié)議,以支持 Upgrade
proxy_http_version 1.1;
# 將客戶端請(qǐng)求中的 Upgrade 與 Connection 頭轉(zhuǎn)發(fā)給后端
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}proxy_http_version 1.1
強(qiáng)制使用 HTTP/1.1,否則默認(rèn)的 HTTP/1.0 無(wú)法支持協(xié)議升級(jí)。
proxy_set_header Upgrade $http_upgrade
將客戶端傳來(lái)的 Upgrade: websocket 透?jìng)鹘o后端。
proxy_set_header Connection “upgrade”
明確指定與 Upgrade 配合使用。
2. 智能化 Connection 設(shè)置
在某些場(chǎng)景下,希望僅在真有升級(jí)需求時(shí)才發(fā) "upgrade",否則保持連接關(guān)閉。
可借助 Nginx 的 map 模塊:
# 將是否存在 Upgrade 頭映射成變量
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}- 如果客戶端請(qǐng)求里沒有
Upgrade,則向后端發(fā)送Connection: close,更符合一般 HTTP 請(qǐng)求的語(yǔ)義。
三、超時(shí)與心跳優(yōu)化
默認(rèn)情況下,Nginx 在代理 WebSocket 連接時(shí),如果后端在 60 秒內(nèi)沒有任何數(shù)據(jù)回傳,會(huì)主動(dòng)關(guān)閉連接。
這對(duì)于長(zhǎng)時(shí)間空閑但后續(xù)可能仍要推送消息的場(chǎng)景并不友好。
常用的優(yōu)化方案有兩種:
1.延長(zhǎng) Nginx 的 proxy_read_timeout
在 location 或 http、server 級(jí)別添加:
proxy_read_timeout 3600s; # 將超時(shí)時(shí)間提升到 1 小時(shí)
2.后端發(fā)送 WebSocket Ping
讓后端應(yīng)用周期性地向客戶端(經(jīng)過(guò) Nginx)發(fā)送 Ping 幀,觸發(fā) Nginx 讀取數(shù)據(jù),從而重置超時(shí)計(jì)時(shí)器,同時(shí)還能檢測(cè)連接健康狀態(tài)。
四、完整示例
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream backend {
server 127.0.0.1:8080; # 后端 WebSocket 服務(wù)地址
# 可根據(jù)實(shí)際情況添加多臺(tái)服務(wù)器,實(shí)現(xiàn)負(fù)載均衡
}
server {
listen 80;
server_name example.com;
# 靜態(tài)資源處理(可選)
location /static/ {
root /var/www/html;
}
# WebSocket 代理入口
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# 轉(zhuǎn)發(fā)客戶端真實(shí) IP(可選)
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 超時(shí)配置
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
}五、實(shí)踐要點(diǎn)與注意事項(xiàng)
- HTTPS + WSS
若在前端使用 wss://(即 TLS 加密的 WebSocket),必須在 Nginx 上配置對(duì)應(yīng)的 SSL 證書,并在 server 塊中使用 ssl_certificate、ssl_certificate_key 等指令。
- 負(fù)載均衡與 Sticky Session
對(duì)于需要在多實(shí)例間保持會(huì)話一致性的業(yè)務(wù),可考慮基于 Cookie 或 IP 哈希的 Sticky Session 配置,或者將業(yè)務(wù)設(shè)計(jì)成無(wú)狀態(tài)。
- 安全加固
可以在 Nginx 中加入 limit_conn、limit_req 等限流指令,防止惡意連接耗盡資源;也可結(jié)合 lua-nginx-module 實(shí)現(xiàn)更復(fù)雜的鑒權(quán)或動(dòng)態(tài)路由。
總結(jié)
通過(guò)上述方式,Nginx 能夠高效、穩(wěn)定地將客戶端的 HTTP 升級(jí)請(qǐng)求(Upgrade)轉(zhuǎn)發(fā)到后端 WebSocket 服務(wù),實(shí)現(xiàn)反向代理與負(fù)載均衡。
在此基礎(chǔ)上,再配合合理的超時(shí)調(diào)整、心跳檢測(cè)與安全限流,即可構(gòu)建面向生產(chǎn)環(huán)境的高可用、可擴(kuò)展的實(shí)時(shí)通信平臺(tái)。
希望本文能幫助你快速上手 Nginx WebSocket 代理,并打造符合業(yè)務(wù)需求的實(shí)時(shí)架構(gòu)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
nginx控制連接數(shù)及訪問(wèn)速率的實(shí)現(xiàn)
本文主要介紹了Nginx中ngx_http_limit_conn_module和ngx_http_limit_req_module模塊的使用,用于控制連接數(shù)和請(qǐng)求速率,具有一定的參考價(jià)值,感興趣的可以了解一下2024-12-12
nginx 配置虛擬主機(jī),實(shí)現(xiàn)在一個(gè)服務(wù)器可以訪問(wèn)多個(gè)網(wǎng)站的方法
下面小編就為大家分享一篇nginx 配置虛擬主機(jī),實(shí)現(xiàn)在一個(gè)服務(wù)器可以訪問(wèn)多個(gè)網(wǎng)站的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
openssl?生成nginx自簽名證書的實(shí)現(xiàn)
本文主要介紹了openssl?生成nginx自簽名證書的實(shí)現(xiàn),主要包括openssl?req命令的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12
nginx反向代理60s超時(shí)報(bào)錯(cuò)問(wèn)題解決
本文主要介紹了Nginx反向代理時(shí)遇到60秒超時(shí)報(bào)錯(cuò)的問(wèn)題,經(jīng)過(guò)排查發(fā)現(xiàn)是由于代理服務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致的,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
nginx反向代理后無(wú)限重定向的問(wèn)題解決方法
這篇文章主要為大家介紹了nginx反向代理后無(wú)限重定向的問(wèn)題解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
詳解nginx使用ssl模塊配置支持HTTPS訪問(wèn)
這篇文章主要介紹了詳解nginx使用ssl模塊配置支持HTTPS訪問(wèn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Ubuntu環(huán)境下安裝部署Nginx詳細(xì)步驟(有網(wǎng))
Nginx是一個(gè)開源的?HTTP?網(wǎng)絡(luò)服務(wù)器,下面這篇文章主要給大家介紹了關(guān)于Ubuntu環(huán)境下安裝部署Nginx(有網(wǎng))的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
Nginx部署https網(wǎng)站并配置地址重寫的步驟詳解
今天小編就為大家分享一篇關(guān)于Nginx部署https網(wǎng)站并配置地址重寫的步驟詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
keepalived結(jié)合nginx實(shí)現(xiàn)nginx高可用的方法
這篇文章主要介紹了keepalived結(jié)合nginx實(shí)現(xiàn)nginx高可用的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03

