可以進入系統測試:在線聊天
利用nginx代理websocket的時候,發現客戶端和服務器握手成功后,如果在60s時間內沒有數據交互,連接就會自動斷開,如下圖:
為了保持長連接,可以采取來兩種方式.
1.nginx.conf 文件里location 中的proxy_read_timeout 默認60s斷開,可以把他設置大一點,你可以設置成自己需要的時間,我這里設置的是十分鍾(600s).
nginx配置如下:
server { listen 80; server_name carrefourzone.senguo.cc; #error_page 502 /static/502.html; location /static/ { root /home/chenming/Carrefour/carrefour.senguo.cc/source; expires 7d; } location / { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://127.0.0.1:9887; proxy_http_version 1.1; proxy_set_header Upgrade "websocket"; proxy_set_header Connection "Upgrade"; proxy_read_timeout 600s; } }
按照上述方法設置好后,我們可以發現,如果在10分鍾之內沒有數據交互的話,websocket連接就會自動斷開,所以這種方式還是有點問題,如果我頁面停留時間超過十分鍾而且又沒有數據交互的話,連接還是會斷開的,所以需要同時結合第二種方法.
上面nginx配置的時候還出了一個小插曲,微改了nginx配置之后,沒有重啟nginx服務,導致設置的過期時間一直沒有生效,所以需要用 sudo nginx -s reload 重啟nginx服務
2.在nginx延長超時時間的基礎上,前端在超時時間內發心跳包,刷新再讀時間,前端具體實現見如下代碼(此處代碼包含了前端整個websocket的實現過程,其中紅色重點標注了發心跳包的內容):
// websocket連接 var websocket_connected_count = 0; var onclose_connected_count = 0; function newWebSocket(){ var websocket = null; // 判斷當前環境是否支持websocket if(window.WebSocket){ if(!websocket){ var ws_url ="wss://"+domain+"/updatewebsocket"; websocket = new WebSocket(ws_url); } }else{ Tip("not support websocket"); } // 連接成功建立的回調方法 websocket.onopen = function(e){ heartCheck.reset().start(); // 成功建立連接后,重置心跳檢測 Tip("connected successfully") } // 連接發生錯誤,連接錯誤時會繼續嘗試發起連接(嘗試5次) websocket.onerror = function() { console.log("onerror連接發生錯誤") websocket_connected_count++; if(websocket_connected_count <= 5){ newWebSocket() } } // 接受到消息的回調方法 websocket.onmessage = function(e){ console.log("接受到消息了") heartCheck.reset().start(); // 如果獲取到消息,說明連接是正常的,重置心跳檢測 var message = e.data; if(message){ //執行接收到消息的操作,一般是刷新UI } } // 接受到服務端關閉連接時的回調方法 websocket.onclose = function(){ Tip("onclose斷開連接"); } // 監聽窗口事件,當窗口關閉時,主動斷開websocket連接,防止連接沒斷開就關閉窗口,server端報錯 window.onbeforeunload = function(){ websocket.close(); } // 心跳檢測, 每隔一段時間檢測連接狀態,如果處於連接中,就向server端主動發送消息,來重置server端與客戶端的最大連接時間,如果已經斷開了,發起重連。 var heartCheck = { timeout: 55000, // 9分鍾發一次心跳,比server端設置的連接時間稍微小一點,在接近斷開的情況下以通信的方式去重置連接時間。 serverTimeoutObj: null, reset: function(){ clearTimeout(this.timeoutObj); clearTimeout(this.serverTimeoutObj); return this; }, start: function(){ var self = this; this.serverTimeoutObj = setInterval(function(){ if(websocket.readyState == 1){ console.log("連接狀態,發送消息保持連接"); websocket.send("ping"); heartCheck.reset().start(); // 如果獲取到消息,說明連接是正常的,重置心跳檢測 }else{ console.log("斷開狀態,嘗試重連"); newWebSocket(); } }, this.timeout) } } }
上述過程就是保持長連接的過程,前端部分也包含了大部分websocket初始化的內容.
原文地址:https://blog.csdn.net/cm786526/article/details/79939687