jswebsocket斷開重連,js websocket重連

本文目錄一覽:

WebSocket斷開重連機制 實現demo,非採用onclose事件方式

WebSocket.onclose 事件監聽器 ,不可控性和斷網情況下不觸發問題,無法很好實現斷線重連功能。

我們解決方案是,根據服務端一定時間,自動給客戶端推送的心跳,心跳來判斷是否斷開,如果一定時間內沒有收到服務器發送的心跳,則會觸發重連。(很像醫生搶救重症病人,看心跳圖沒有波動,啟用心電復蘇)

如何避免websocket重複連接

你實現TextWebSocketHandler中的類中在 afterConnectionClosed();連接關閉後,裡面如果定義了用戶斷開連接就移除websocketsession就沒有問題。還有就是不要在多個頁面建立連接,盡量使用子夫頁面互調方法的方式實現數據傳遞。

websocket stomp連接一段時間後斷開

因為項目中存在頻繁的由服務器發起的數據交換,相比使用Ajax輪訓的方式,websocket長連接和雙向保持的特點能夠較好的提升數據交換的性能。

為了簡便,直接使用spring boot + shiro + stomp和socketJs作為構建的工具。

但是由於使用時,主要是由服務端進行數據的推送,通過stomp自行保持心跳,就會存在session過期導致連接斷開的情況,而且由於stomp本身不會提示錯誤原因,導致排查起來比較麻煩,因此記錄下整個糾錯過程以備忘。

在一開始打開時,一切正常,數據能推送成功,但是在大約10分鐘左右(時長不定)能通過chrome的前端調試工具發現stomp提示連接斷開。服務器端無任何異常提示。

因為服務器端無任何異常,且斷連時長不定,因此推測為可能是session導致的自動斷鏈或者心跳丟失導致的。因為stomp本身不會報錯誤原因,因此想要找到具體的錯誤原因比較麻煩。後來發現可以通過斷點到stomp的onclose時間就能夠獲取到具體的錯誤碼,這就為我們定位問題提供了很好的幫助(具體斷點位置如下圖所示)

最後通過錯誤碼發現,提示的錯誤碼是1008,reason部分提示的是http session被關閉,因此問題就比較清楚了,是由於session釋放導致的斷鏈。這一點就很有意思,因為在使用過程中為了避免不必要的數據傳輸就一直沒有發起websocket的send事件,只是一直在subscribe監聽服務器的推送。因此導致了服務器的session一直沒有被touch(),從而釋放。(其實個人覺得這個可能也是一個比較有意思的問題,為什麼心跳沒有被處理會觸發到session,具體沒有試驗是不是和我使用了shiro的session作為管理有關,有興趣的同學們可以嘗試一下)

這裡也順便貼上對於錯誤碼的描述和相關參考資料,便於大家解決其它的錯誤碼問題:

那麼問題找到了響應的解決方案就比較好處理了,但是究竟哪種方案比較好,還是得看具體的業務需求和對利弊的取捨。

問題本身倒是不複雜,就是對stomp不熟悉,確定具體的錯誤原因上花了很多時間,進行了很多白費的嘗試,所以希望能記錄下,做個以後的備忘,防止再走很多彎路。

Nginx websocket proxy斷連問題

由於項目中需要服務端向移動設備主動推送信令,於是引入websocket協議進行移動設備和服務端之間的通信。Demo程序很正常,服務端使用nodejs ws類庫起一個websocket服務器,android設備中使用Okhttp3-ws對接,一切都比較正常。但是集成到生產環境kong api gateway後出現了連接一段時間android設備出現java.io.EOFException錯誤,服務端ws服務器出現1006錯誤,websocket連接斷開的問題。

由於demo程序運行正常,生產環境與demo環境區別在於android設備和服務端之間使用kong api gateway工具進行了proxy,kong是基於Nginx的api管理工具,於是問題分析重點鎖定gateway轉發的過程。

首先抓包比對一下demo環境和生產環境區別。

demo環境wireshark包:

可以看到,GET請求包和協議切換響應包間隔很短。

kong 環境包:

嘗試修改了read timeout的時間,果然出現斷連的時間隨着timeout而變化,應該就是Nginx這個機制導致的。文檔中也明確說明了解決方法,在時間間隔小於read timeout的輪詢中不斷和服務器進行ping包發送來刷新timeout時間。

實際測試,用20秒的間隔不斷給服務器發送心跳,可以保持websocket連接不斷。

但是還有一個問題,http upgarde包發出去後應該要等http code 101 Switching Protocols這個包回來才算握手完成,才可以建立tcp長連接,但是在nginx環境下這個包60秒後才回來,但是中間數據交互都是正常的,讓人匪夷所思。

再仔細看下nginx轉發wireshark包,發現http code 101 Switching Protocols包是由3片TCP包組裝而成的:

第一幀序號23,找到後發現內容就是服務器響應握手的http報文內容

所以在25幀時實際已經握手完成了,並非在62秒才傳包回來。

第二幀:

傳遞的數據是connected.

這樣就和協議描述一致,先完成handshake再transfer data。但是經過nginx抓發的包一直沒有結束符,所以導致wireshark在斷連得時候才顯示該http報完成,此處不知是不是nginx websocket proxy的bug? 如果有大神知道還請指導。

websocket

建立連接(創建WebSocket對象):

var Socket =new WebSocket(url, [protocol] );// url:服務器端地址;protocol:可選,指定可接受的子協議。

WebSocket對象提供了兩個屬性、四個事件、兩個方法,分別是:

1.WebSocket.readyState屬性:表示連接狀態

    0——(連接尚未建立);1——(連接已建立);2——(連接正在關閉);3——(連接已經關閉或連接不能打開)

2.WebSocket.bufferedAmount屬性:被send()放入傳輸隊列,還未發出的UTF-8文本字節數

    ws.addEventListener(‘open’,function(event){

            ws.send(‘Hello Server!’);

    });

     ws.onopen =function(){

        ws.send(‘Hello Server!’);

    }

3.open:WebSocket.onopen():連接建立時觸發的事件

4.message:WebSocket.onmessage(): 客戶端接收服務器端發送的信息時觸發

5.error:WebSocket.onerror():通信發生錯誤時觸發

6.close:WebSocket.onclose():連接關閉時觸發

7.WebSocket.send():發送信息的方法

8.WebSocket.close():關閉連接方法

SOCKJS

SOCKJS 是一個瀏覽器使用的js庫,它提供了一個類似網絡的對象,和連貫的,跨瀏覽器的jaApi,可以在瀏覽器和服務器之間創建一個低延遲,全雙工的跨域通信通道

SOCKJS實現了對瀏覽器的兼容,spring框架提供了很多透明的,回退選項,如果遇到低版本的瀏覽器會自動降級為輪詢,支持就用websocket

sockjs-client

sockjs-client 是從SOCKJS分離出來的客戶端使用的通信模塊

stompjs

STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的簡單文本協議;

websocket只是一個消息架構,不強制使用任何的消息協議,為了更好的在瀏覽器和服務器之間傳遞消息,使用stomp協議 的stompjs

STOMP與WebSocket 的關係:就是沒使用http而使用stomp協議,在瀏覽器和服務器之間進行消息傳遞

1.HTTP協議解決了web瀏覽器發起請求以及web服務器響應請求的細節,假設HTTP協議不存在,只能使用TCP套接字來編寫web應用,你可能認為這是一件瘋狂的事情;

2.直接使用WebSocket(SockJS)就很類似於使用TCP套接字來編寫web應用,因為沒有高層協議,就需要我們定義應用間發送消息的語義,還需要確保連接的兩端都能遵循這些語義;

3同HTTP在TCP套接字上添加請求-響應模型層一樣,STOMP在WebSocket之上提供了一個基於幀的線路格式層,用來定義消息語義、

安裝

npm install sockjs-client –save

npm install stompjs –save

引入

import SockJS from ‘sockjs-client’;

import  Stomp from ‘stompjs’;

export default {

    data(){

        return {

            stompClient:”,

            timer:”,

        }

    },

    methods:{

        initWebSocket() {

            this.connection();

            let that= this;

            // 斷開重連機制,嘗試發送消息,捕獲異常發生時重連

            this.timer = setInterval(() = {

                try {

                    that.stompClient.send(“test”);

                } catch (err) {

                    console.log(“斷線了: ” + err);

                    that.connection();

                }

            }, 5000);

        }, 

        connection() {

            // 建立連接對象

            let socket = new SockJS(‘execution-progress/info?t=1593744273983’);

            var sockjs =new SockJS(url, _reserved, options);

                //server(string):添加到url的字符串,默認為隨機的4位數

                //transports (string OR array of strings):回退傳輸列表

                // sessionId (number OR function):會話標識,函數必須返回一個隨機生成的字符串

            // 獲取STOMP子協議的客戶端對象

            this.stompClient = Stomp.over(socket);

            // 定義客戶端的認證信息,按需求配置

            let headers = {

                Authorization:”

            }

            // 向服務器發起websocket連接

            this.stompClient.connect(headers,() = {

                this.stompClient.subscribe(‘/topic/public’, (msg) = { // 訂閱服務端提供的某個topic

                    console.log(‘廣播成功’)

                    console.log(msg);  // msg.body存放的是服務端發送給我們的信息

                },headers);

                this.stompClient.send(“/app/chat.addUser”,

                    headers,

                    JSON.stringify({sender: ”,chatType: ‘JOIN’}),

                )  //用戶加入接口

            }, (err) = {

                // 連接發生錯誤時的處理函數

                console.log(‘失敗’)

                console.log(err);

            });

        },    //連接 後台

        disconnect() {

            if (this.stompClient) {

                this.stompClient.disconnect();

            }

        },  // 斷開連接

    },

    mounted(){

        this.initWebSocket();

    },

    beforeDestroy: function () {

        // 頁面離開時斷開連接,清除定時器

        this.disconnect();

        clearInterval(this.timer);

    }

}

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/200677.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-05 20:02
下一篇 2024-12-05 20:02

相關推薦

  • JS Proxy(array)用法介紹

    JS Proxy(array)可以說是ES6中非常重要的一個特性,它可以代理一個數組,監聽數據變化並進行攔截、處理。在實際開發中,使用Proxy(array)可以方便地實現數據的監…

    編程 2025-04-29
  • 解析js base64並轉成unit

    本文將從多個方面詳細介紹js中如何解析base64編碼並轉成unit格式。 一、base64編碼解析 在JavaScript中解析base64編碼可以使用atob()函數,它會將b…

    編程 2025-04-29
  • Node.js使用Body-Parser處理HTTP POST請求時,特殊字符無法返回的解決方法

    本文將解決Node.js使用Body-Parser處理HTTP POST請求時,特殊字符無法返回的問題。同時,給出一些相關示例代碼,以幫助讀者更好的理解並處理這個問題。 一、問題解…

    編程 2025-04-29
  • t3.js:一個全能的JavaScript動態文本替換工具

    t3.js是一個非常流行的JavaScript動態文本替換工具,它是一個輕量級庫,能夠很容易地實現文本內容的遞增、遞減、替換、切換以及其他各種操作。在本文中,我們將從多個方面探討t…

    編程 2025-04-28
  • JS圖片沿着SVG路徑移動實現方法

    本文將為大家詳細介紹如何使用JS實現圖片沿着SVG路徑移動的效果,包括路徑製作、路徑效果、以及實現代碼等內容。 一、路徑製作 路徑的製作,我們需要使用到SVG,SVG是可縮放矢量圖…

    編程 2025-04-27
  • 如何使用JS調用Python腳本

    本文將詳細介紹通過JS調用Python腳本的方法,包括使用Node.js、Python shell、child_process等三種方法,以及在Web應用中的應用。 一、使用Nod…

    編程 2025-04-27
  • 如何反混淆美團slider.js

    本文將從多個方面詳細闡述如何反混淆美團slider.js。在開始之前,需要明確的是,混淆是一種保護JavaScript代碼的方法,其目的是使代碼難以理解和修改。因此,在進行反混淆操…

    編程 2025-04-27
  • Boost Websocket Send用法介紹

    本文將詳細闡述Boost Websocket Send的相關內容,包括Boost Websocket Send的概念、使用方法、功能特點等,以便讀者深入了解和使用。 一、概述 Bo…

    編程 2025-04-27
  • Python要學JS嗎?

    Python和JavaScript都是非常受歡迎的編程語言。然而,你可能會問,既然我已經學了Python,是不是也需要學一下JS呢?在本文中,我們將圍繞這個問題進行討論,並從多個角…

    編程 2025-04-27
  • 解決js ajax post 419問題

    對於使用ajax post請求時出現的419問題,我們需要進行以下幾個方面的闡述,包括返回碼的含義、可能出現的情況、解決方案等內容。 一、解析419返回碼 419返回碼錶示用戶超時…

    編程 2025-04-27

發表回復

登錄後才能評論