文章分享

開放、平等、協(xié)作、快速、分享

當(dāng)前位置:首頁>文章分享

WebSocket 結(jié)合 Nginx 實(shí)現(xiàn)域名及 WSS 協(xié)議訪問

摘錄:HCTech 無錫和控電子   時(shí)間:2020-08-07   訪問量:4270

WebSocket 結(jié)合 Nginx 實(shí)現(xiàn)域名及 WSS 協(xié)議訪問

簡單了解一下 WebSocket

現(xiàn)在,很多網(wǎng)站為了實(shí)現(xiàn)推送技術(shù),所用的技術(shù)都是輪詢。輪詢是在特定的的時(shí)間間隔(如每1秒),由瀏覽器對服務(wù)器發(fā)出HTTP請求,然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端的瀏覽器。這種傳統(tǒng)的模式帶來很明顯的缺點(diǎn),即瀏覽器需要不斷的向服務(wù)器發(fā)出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數(shù)據(jù)可能只是很小的一部分,顯然這樣會(huì)浪費(fèi)很多的帶寬等資源。
在這種情況下,HTML5定義了WebSocket協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊。
WebSocket一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。

以上信息摘自維基百科(https://zh.wikipedia.org/wiki/WebSocket

簡單點(diǎn)說,WebSocket 就是減小客戶端與服務(wù)器端建立連接的次數(shù),減小系統(tǒng)資源開銷,只需要一次 HTTP 握手,整個(gè)通訊過程是建立在一次連接/狀態(tài)中,也就避免了HTTP的非狀態(tài)性,服務(wù)端會(huì)一直與客戶端保持連接,直到你關(guān)閉請求,同時(shí)由原本的客戶端主動(dòng)詢問,轉(zhuǎn)換為服務(wù)器有信息的時(shí)候推送。當(dāng)然,它還能做實(shí)時(shí)通信、更好的二進(jìn)制支持、支持?jǐn)U展、更好的壓縮效果等這些優(yōu)點(diǎn)。

推薦一個(gè)知乎上叫 Ovear 的網(wǎng)友關(guān)于 WebSocket 原理的回答,嘻哈風(fēng)格科普文,簡直不要更贊了!地址:https://www.zhihu.com/question/20215561/answer/40316953

ws 和 wss 又是什么鬼?

Websocket使用 ws 或 wss 的統(tǒng)一資源標(biāo)志符,類似于 HTTP 或 HTTPS,其中 wss 表示在 TLS 之上的 Websocket ,相當(dāng)于 HTTPS 了。如:

ws://example.com/chatwss://example.com/chat

默認(rèn)情況下,Websocket 的 ws 協(xié)議使用 80 端口;運(yùn)行在TLS之上時(shí),wss 協(xié)議默認(rèn)使用 443 端口。其實(shí)說白了,wss 就是 ws 基于 SSL 的安全傳輸,與 HTTPS 一樣樣的道理。

如果你的網(wǎng)站是 HTTPS 協(xié)議的,那你就不能使用 ws:// 了,瀏覽器會(huì) block 掉連接,和 HTTPS 下不允許 HTTP 請求一樣,如下圖:
ws_https

Mixed Content: The page at 'https://domain.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://x.x.x.x:xxxx/'. This request has been blocked; this endpoint must be available over WSS.

這種情況,毫無疑問我們就需要使用 wss:\\ 安全協(xié)議了,我們是不是簡單的把 ws:\\ 改為 wss:\\ 就行了?那試試唄。

改好了,報(bào)錯(cuò)啦?。?!
wss_ip

VM512:35 WebSocket connection to 'wss://IP地址:端口號(hào)/websocket' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

很明顯 SSL 協(xié)議錯(cuò)誤,說明就是證書問題了。記著,這時(shí)候我們一直拿的是 IP地址 + 端口號(hào) 這種方式連接 WebSocket 的,這根本就沒有證書存在好么,況且生成環(huán)境你也要用 IP地址 + 端口號(hào) 這種方式連接 WebSocket 嗎?肯定不行阿,要用域名方式連接 WebSocket 阿。

Nginx 配置域名支持 WSS

不用廢話,直接在配置 HTTPS 域名位置加入如下配置:

location /websocket {    proxy_pass http://backend;    proxy_http_version 1.1;    proxy_set_header Upgrade $http_upgrade;    proxy_set_header Connection "upgrade";
}

接著拿域名再次連接試一下,不出意外會(huì)看 101 狀態(tài)碼:
upgrade_101

這樣就完成了,在 HTTPPS 下以域名方式連接 WebSocket ,可以開心的玩耍了。

稍微解釋一下 Nginx 配置
Nginx 自從 1.3 版本就開始支持 WebSocket 了,并且可以為 WebSocket 應(yīng)用程序做反向代理和負(fù)載均衡。
WebSocket 和 HTTP 協(xié)議不同,但是 WebSocket 中的握手和 HTTP 中的握手兼容,它使用 HTTP 中的 Upgrade 協(xié)議頭將連接從 HTTP 升級到 WebSocket,當(dāng)客戶端發(fā)過來一個(gè) Connection: Upgrade請求頭時(shí),Nginx 是不知道的,所以,當(dāng) Nginx 代理服務(wù)器攔截到一個(gè)客戶端發(fā)來的 Upgrade 請求時(shí),需要顯式來設(shè)置Connection 、Upgrade 頭信息,并使用 101(交換協(xié)議)返回響應(yīng),在客戶端和代理服務(wù)器、后端服務(wù)器之間建立隧道來支持 WebSocket。

當(dāng)然,還需要注意一下,WebSockets 仍然受到 Nginx 缺省為60秒的 proxy_read_timeout 的影響。這意味著,如果你有一個(gè)程序使用了 WebSockets,但又可能超過60秒不發(fā)送任何數(shù)據(jù)的話,那你要么需要增加超時(shí)時(shí)間,要么實(shí)現(xiàn)一個(gè) ping 的消息以保持聯(lián)系。使用 ping 的解決方法有額外的好處,可以發(fā)現(xiàn)連接是否被意外關(guān)閉。

更具體文檔詳見 Nginx 官方文檔:http://nginx.org/en/docs/http/websocket.html

總結(jié)一下

這一篇文章主要了解一下 WebSocket 基本原理和一些使用用途,并解決在實(shí)際開發(fā)使用過程中遇到的坑,HTTPS 下使用 wss 協(xié)議的問題,以及配合 Nginx 使用域名方式建立連接,不使用 IP地址 + 端口號(hào) 連接 WebSocket,因?yàn)檫@種方式不夠優(yōu)雅。

下一篇,全站升級 HTTPS 之路,并沒你想象的那么簡單。


上一篇:Nginx 作為 WebSockets 代理

下一篇:nginx反向代理webSocket配置

在線咨詢

點(diǎn)擊這里給我發(fā)消息 售前咨詢專員

點(diǎn)擊這里給我發(fā)消息 售后服務(wù)專員

在線咨詢

免費(fèi)通話

24小時(shí)免費(fèi)咨詢

請輸入您的聯(lián)系電話,座機(jī)請加區(qū)號(hào)

免費(fèi)通話

微信掃一掃

微信聯(lián)系
返回頂部