文章分享

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

當前位置:首頁>文章分享

Nginx代理webSocket時60s自動斷開, 怎么保持長連接

摘錄:HCTech 無錫和控電子   時間:2020-08-07   訪問量:4514

利用nginx代理websocket的時候,發(fā)現(xiàn)客戶端和服務器握手成功后,如果在60s時間內(nèi)沒有數(shù)據(jù)交互,連接就會自動斷開,如下圖:

blob.png


為了保持長連接,可以采取來兩種方式.


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


上一篇:WebSocket協(xié)議—從頂層到底層的實現(xiàn)原理

下一篇:徹底理解cookie,session,token

在線咨詢

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

點擊這里給我發(fā)消息 售后服務專員

在線咨詢

免費通話

24小時免費咨詢

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

免費通話

微信掃一掃

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