為啥要寫這篇文章呢?
最近在做websocket的項(xiàng)目,踩到的坑做一個(gè)總結(jié)。
1.ws和wss問題
2.代理設(shè)置問題
3.域名開啟DNS后在使用代理出現(xiàn)的問題
1.配置Nginx支持WSS(WebSocket)
簡單了解一下 WebSocket
? 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)閉請(qǐng)求,同時(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/websocket
wss://example.com/websocket
默認(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ì)報(bào)協(xié)議錯(cuò)誤,那怎么辦呢?
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)碼,鏈接成功
2.Nginx實(shí)戰(zhàn)之反向代理WebSocket的配置實(shí)例
NGINX偵聽端口8020,并向后端WebSocket服務(wù)器發(fā)送代理請(qǐng)求。該proxy_set_header指令使NGINX妥善處理WebSocket協(xié)議。
ws.conf文件內(nèi)容如下:
upstream websocket {
? ? server 192.168.100.10:8010;
}
server {
? ? listen 8020;
? ? location / {
? ? ? ? proxy_pass http://websocket;
? ? ? ? proxy_http_version 1.1;
? ? ? ? proxy_set_header Upgrade $http_upgrade;
? ? ? ? proxy_set_header Connection $connection_upgrade;
? ? }
}
WebSocket集群
在實(shí)際的生產(chǎn)環(huán)境中,要求多個(gè)WebSocket服務(wù)器必須具有高性能和高可用,那么WebSocket協(xié)議就需要一個(gè)負(fù)載均衡層,NGINX從1.3開始支持WebSocket,其可以作為一個(gè)反向代理和為WebSocket程序做負(fù)載均衡。
Nginx配置
注:看官方文檔說 Nginx 在 1.3 以后的版本才支持 websocket 反向代理,所以要想使用支持 websocket 的功能,必須升級(jí)到 1.3 以后的版本
NGINX通過允許一個(gè)在客戶端和后端服務(wù)器之間建立的隧道來支持WebSocket。為了NGINX發(fā)送來至于客戶端Upgrade請(qǐng)求到后端服務(wù)器,Upgrade和Connection頭部必須被設(shè)置明確。
upstream wsbackend {
? server 127.0.0.1:8080;
? server 127.0.0.1:8081;
}
server {
? listen? 80;
? server_name ws.52itstyle.com;
? location / {
? proxy_pass http://wsbackend;? proxy_http_version 1.1;
? proxy_set_header Upgrade $http_upgrade;
? proxy_set_header Connection "upgrade";
? }
}
前端配置:
$(function(){
socket.init();
});//Nginx反向代理實(shí)現(xiàn)websocketvar basePath = "ws://ws.52itstyle.com//acts_competition/";
socket = {
webSocket : "",
init : function() {
? if ('WebSocket' in window) {
? webSocket = new WebSocket(basePath+'webSocketServer');
? }
? else if ('MozWebSocket' in window) {
? webSocket = new MozWebSocket(basePath+"webSocketServer");
? }
? else {
? webSocket = new SockJS(basePath+"sockjs/webSocketServer");
? }
? webSocket.onerror = function(event) {
? //alert("websockt連接發(fā)生錯(cuò)誤,請(qǐng)刷新頁面重試!")? };
? webSocket.onopen = function(event) {
? };
? webSocket.onmessage = function(event) {
? ? };
},
sendData : function(data) {
? webSocket.send(data);
},
}
最后,重啟下Nginx即可。
反向代理服務(wù)器在支持WebSocket時(shí)面臨的挑戰(zhàn)
WebSocket是端對(duì)端的,所以當(dāng)一個(gè)代理服務(wù)器從客戶端攔截一個(gè)Upgrade請(qǐng)求,它需要去發(fā)送它自己的Upgrade請(qǐng)求到后端服務(wù)器,也包括合適的頭。
因?yàn)閃ebSocket是一個(gè)長連接,不像HTTP那樣是典型的短連接,所以反向代理服務(wù)器需要允許連接保持著打開,而不是在它們看起來空閑時(shí)就將它們關(guān)閉。
3.使用CDN加速后,websocket對(duì)象無法訪問
很簡單的原因,CDN加速的是靜態(tài)資源。
目前CDN還不支持websocket,建議將這類動(dòng)態(tài)內(nèi)容用一個(gè)單獨(dú)的域名拆出來單獨(dú)訪問,不使用CDN訪問。
使用阿里云的全站加速