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


可以進入系統測試:在線聊天

 

利用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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM