開放、平等、協(xié)作、快速、分享
利用nginx代理websocket的時候,發(fā)現(xiàn)客戶端和服務器握手成功后,如果在60s時間內(nèi)沒有數(shù)據(jù)交互,連接就會自動斷開,如下圖:
為了保持長連接,可以采取來兩種方式.
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;
}
}
按照上述方法設置好后,我們可以發(fā)現(xiàn),如果在10分鐘之內(nèi)沒有數(shù)據(jù)交互的話,websocket連接就會自動斷開,所以這種方式還是有點問題,如果我頁面停留時間超過十分鐘而且又沒有數(shù)據(jù)交互的話,連接還是會斷開的,所以需要同時結(jié)合第二種方法.
上面nginx配置的時候還出了一個小插曲,微改了nginx配置之后,沒有重啟nginx服務,導致設置的過期時間一直沒有生效,所以需要用 sudo nginx -s reload 重啟nginx服務
2.在nginx延長超時時間的基礎上,前端在超時時間內(nèi)發(fā)心跳包,刷新再讀時間,前端具體實現(xiàn)見如下代碼(此處代碼包含了前端整個websocket的實現(xiàn)過程,其中紅色重點標注了發(fā)心跳包的內(nèi)容):
// websocket連接
var websocket_connected_count = 0;
var onclose_connected_count = 0;
function newWebSocket(){
var websocket = null;
// 判斷當前環(huán)境是否支持websocket
if(window.WebSocket){
if(!websocket){
var ws_url ="wss://"+domain+"/updatewebsocket";
websocket = new WebSocket(ws_url);
}
}else{
Tip("not support websocket");
}
// 連接成功建立的回調(diào)方法
websocket.onopen = function(e){
heartCheck.reset().start(); // 成功建立連接后,重置心跳檢測
Tip("connected successfully")
}
// 連接發(fā)生錯誤,連接錯誤時會繼續(xù)嘗試發(fā)起連接(嘗試5次)
websocket.onerror = function() {
console.log("onerror連接發(fā)生錯誤")
websocket_connected_count++;
if(websocket_connected_count <= 5){
newWebSocket()
}
}
// 接受到消息的回調(diào)方法
websocket.onmessage = function(e){
console.log("接受到消息了")
heartCheck.reset().start(); // 如果獲取到消息,說明連接是正常的,重置心跳檢測
var message = e.data;
if(message){
//執(zhí)行接收到消息的操作,一般是刷新UI
}
}
// 接受到服務端關閉連接時的回調(diào)方法
websocket.onclose = function(){
Tip("onclose斷開連接");
}
// 監(jiān)聽窗口事件,當窗口關閉時,主動斷開websocket連接,防止連接沒斷開就關閉窗口,server端報錯
window.onbeforeunload = function(){
websocket.close();
}
// 心跳檢測, 每隔一段時間檢測連接狀態(tài),如果處于連接中,就向server端主動發(fā)送消息,來重置server端與客戶端的最大連接時間,如果已經(jīng)斷開了,發(fā)起重連。
var heartCheck = {
timeout: 55000, // 9分鐘發(fā)一次心跳,比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("連接狀態(tài),發(fā)送消息保持連接");
websocket.send("ping");
heartCheck.reset().start(); // 如果獲取到消息,說明連接是正常的,重置心跳檢測
}else{
console.log("斷開狀態(tài),嘗試重連");
newWebSocket();
}
}, this.timeout)
}
}
}
上述過程就是保持長連接的過程,前端部分也包含了大部分websocket初始化的內(nèi)容
————————————————
版權(quán)聲明:本文為CSDN博主「晴識明月」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/cm786526/article/details/79939687