文章分享

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

當(dāng)前位置:首頁(yè)>文章分享

Nginx代理webSocket時(shí)60s自動(dòng)斷開(kāi), 怎么保持長(zhǎng)連接

摘錄:HCTech 無(wú)錫和控電子   時(shí)間:2020-08-07   訪(fǎng)問(wèn)量:5081

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

blob.png


為了保持長(zhǎng)連接,可以采取來(lái)兩種方式.


1.nginx.conf 文件里location 中的proxy_read_timeout 默認(rèn)60s斷開(kāi),可以把他設(shè)置大一點(diǎn),你可以設(shè)置成自己需要的時(shí)間,我這里設(shè)置的是十分鐘(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; 

}

}

按照上述方法設(shè)置好后,我們可以發(fā)現(xiàn),如果在10分鐘之內(nèi)沒(méi)有數(shù)據(jù)交互的話(huà),websocket連接就會(huì)自動(dòng)斷開(kāi),所以這種方式還是有點(diǎn)問(wèn)題,如果我頁(yè)面停留時(shí)間超過(guò)十分鐘而且又沒(méi)有數(shù)據(jù)交互的話(huà),連接還是會(huì)斷開(kāi)的,所以需要同時(shí)結(jié)合第二種方法.


上面nginx配置的時(shí)候還出了一個(gè)小插曲,微改了nginx配置之后,沒(méi)有重啟nginx服務(wù),導(dǎo)致設(shè)置的過(guò)期時(shí)間一直沒(méi)有生效,所以需要用 sudo nginx -s reload  重啟nginx服務(wù)


2.在nginx延長(zhǎng)超時(shí)時(shí)間的基礎(chǔ)上,前端在超時(shí)時(shí)間內(nèi)發(fā)心跳包,刷新再讀時(shí)間,前端具體實(shí)現(xiàn)見(jiàn)如下代碼(此處代碼包含了前端整個(gè)websocket的實(shí)現(xiàn)過(guò)程,其中紅色重點(diǎn)標(biāo)注了發(fā)心跳包的內(nèi)容):


// websocket連接

var websocket_connected_count = 0;

var onclose_connected_count = 0;

function newWebSocket(){

    var websocket = null;

    // 判斷當(dāng)前環(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();   // 成功建立連接后,重置心跳檢測(cè)

        Tip("connected successfully")

    }

    // 連接發(fā)生錯(cuò)誤,連接錯(cuò)誤時(shí)會(huì)繼續(xù)嘗試發(fā)起連接(嘗試5次)

    websocket.onerror = function() {

        console.log("onerror連接發(fā)生錯(cuò)誤")

        websocket_connected_count++;

        if(websocket_connected_count <= 5){

            newWebSocket()

        }

    }

    // 接受到消息的回調(diào)方法

    websocket.onmessage = function(e){

        console.log("接受到消息了")

        heartCheck.reset().start();    // 如果獲取到消息,說(shuō)明連接是正常的,重置心跳檢測(cè)

        var message = e.data;

        if(message){

           //執(zhí)行接收到消息的操作,一般是刷新UI

        }

    }

 

    // 接受到服務(wù)端關(guān)閉連接時(shí)的回調(diào)方法

    websocket.onclose = function(){

        Tip("onclose斷開(kāi)連接");

    }

    // 監(jiān)聽(tīng)窗口事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)斷開(kāi)websocket連接,防止連接沒(méi)斷開(kāi)就關(guān)閉窗口,server端報(bào)錯(cuò)

    window.onbeforeunload = function(){

        websocket.close();

    }

 

    // 心跳檢測(cè), 每隔一段時(shí)間檢測(cè)連接狀態(tài),如果處于連接中,就向server端主動(dòng)發(fā)送消息,來(lái)重置server端與客戶(hù)端的最大連接時(shí)間,如果已經(jīng)斷開(kāi)了,發(fā)起重連。

    var heartCheck = {

        timeout: 55000,        // 9分鐘發(fā)一次心跳,比server端設(shè)置的連接時(shí)間稍微小一點(diǎn),在接近斷開(kāi)的情況下以通信的方式去重置連接時(shí)間。

        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();    // 如果獲取到消息,說(shuō)明連接是正常的,重置心跳檢測(cè)

                }else{

                    console.log("斷開(kāi)狀態(tài),嘗試重連");

                    newWebSocket();

                }

            }, this.timeout)

        }

    }

}


上述過(guò)程就是保持長(zhǎng)連接的過(guò)程,前端部分也包含了大部分websocket初始化的內(nèi)容

————————————————

版權(quán)聲明:本文為CSDN博主「晴識(shí)明月」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/cm786526/article/details/79939687


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

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

在線(xiàn)咨詢(xún)

點(diǎn)擊這里給我發(fā)消息 售前咨詢(xún)專(zhuān)員

點(diǎn)擊這里給我發(fā)消息 售后服務(wù)專(zhuān)員

在線(xiàn)咨詢(xún)

免費(fèi)通話(huà)

24小時(shí)免費(fèi)咨詢(xún)

請(qǐng)輸入您的聯(lián)系電話(huà),座機(jī)請(qǐng)加區(qū)號(hào)

免費(fèi)通話(huà)

微信掃一掃

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