為啥要寫這篇文章呢?
最近在做websocket的項目,踩到的坑做一個總結。
1.ws和wss問題
2.代理設置問題
3.域名開啟DNS后在使用代理出現的問題
1.配置Nginx支持WSS(WebSocket)
簡單了解一下 WebSocket
? WebSocket一種在單個 TCP 連接上進行全雙工通訊的協議。使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。
以上信息摘自維基百科(?https://zh.wikipedia.org/wiki/WebSocket?)
簡單點說,WebSocket 就是減小客戶端與服務器端建立連接的次數,減小系統資源開銷,只需要一次 HTTP 握手,整個通訊過程是建立在一次連接/狀態中,也就避免了HTTP的非狀態性,服務端會一直與客戶端保持連接,直到你關閉請求,同時由原本的客戶端主動詢問,轉換為服務器有信息的時候推送。當然,它還能做實時通信、更好的二進制支持、支持擴展、更好的壓縮效果等這些優點。
推薦一個知乎上叫 Ovear 的網友關于 WebSocket 原理的回答,嘻哈風格科普文,簡直不要更贊了!地址:?https://www.zhihu.com/question/20215561/answer/40316953
ws和wss是什么鬼?
Websocket使用?ws?或?wss?的統一資源標志符,類似于?HTTP?或?HTTPS?,其中?wss?表示在 TLS 之上的 Websocket ,相當于 HTTPS 了。如
ws://example.com/websocket
wss://example.com/websocket
默認情況下,Websocket 的 ws 協議使用 80 端口;運行在TLS之上時,wss 協議默認使用 443 端口。其實說白了,wss 就是 ws 基于 SSL 的安全傳輸,與 HTTPS 一樣樣的道理。
如果網站是https協議的話就不能使用ws://,會報協議錯誤,那怎么辦呢?
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";
}
接著拿域名再次連接試一下,不出意外會看 101 狀態碼,鏈接成功
2.Nginx實戰之反向代理WebSocket的配置實例
NGINX偵聽端口8020,并向后端WebSocket服務器發送代理請求。該proxy_set_header指令使NGINX妥善處理WebSocket協議。
ws.conf文件內容如下:
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集群
在實際的生產環境中,要求多個WebSocket服務器必須具有高性能和高可用,那么WebSocket協議就需要一個負載均衡層,NGINX從1.3開始支持WebSocket,其可以作為一個反向代理和為WebSocket程序做負載均衡。
Nginx配置
注:看官方文檔說 Nginx 在 1.3 以后的版本才支持 websocket 反向代理,所以要想使用支持 websocket 的功能,必須升級到 1.3 以后的版本
NGINX通過允許一個在客戶端和后端服務器之間建立的隧道來支持WebSocket。為了NGINX發送來至于客戶端Upgrade請求到后端服務器,Upgrade和Connection頭部必須被設置明確。
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反向代理實現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連接發生錯誤,請刷新頁面重試!")? };
? webSocket.onopen = function(event) {
? };
? webSocket.onmessage = function(event) {
? ? };
},
sendData : function(data) {
? webSocket.send(data);
},
}
最后,重啟下Nginx即可。
反向代理服務器在支持WebSocket時面臨的挑戰
WebSocket是端對端的,所以當一個代理服務器從客戶端攔截一個Upgrade請求,它需要去發送它自己的Upgrade請求到后端服務器,也包括合適的頭。
因為WebSocket是一個長連接,不像HTTP那樣是典型的短連接,所以反向代理服務器需要允許連接保持著打開,而不是在它們看起來空閑時就將它們關閉。
3.使用CDN加速后,websocket對象無法訪問
很簡單的原因,CDN加速的是靜態資源。
目前CDN還不支持websocket,建議將這類動態內容用一個單獨的域名拆出來單獨訪問,不使用CDN訪問。
使用阿里云的全站加速