1、心跳重連的原因
心跳和重連的目的用一句話概括就是客戶端和服務端保證彼此還活着,避免丟包發生。
websocket斷開有兩種情況:
前端斷開:
在使用websocket過程中,可能會出現網絡斷開的情況,比如信號不好,或者網絡臨時關閉,這時候websocket的連接已經斷開,而不同瀏覽器有不同的機制,觸發onclose的時機也不同,並不會理想執行websocket的onclose方法,我們無法知道是否斷開連接,也就無法進行重連操作。
後端斷開:
如果後端因爲一些情況需要斷開ws,在可控情況下,會下發一個斷連的消息通知,之後纔會斷開,我們便會重連。
如果因爲一些異常斷開了連接,我們是不會感應到的,所以如果我們發送了心跳一定時間之後,後端既沒有返回心跳響應消息,前端又沒有收到任何其他消息的話,我們就能斷定後端主動斷開了。
因此需要一種機制來檢測客戶端和服務端是否處於正常連接的狀態。通過在指定時間間隔發送心跳包來保證連接正常,如果連接出現問題,就需要手動觸發onclose事件,這時候便可進行重連操作。因此websocket心跳重連就應運而生。
2、實現代碼
1)通過createWebSocket創建連接
2)創建init方法,初始化一些監聽事件,如果希望websocket連接一直保持, 我們會在close或者error上綁定重新連接方法。
3)重連操作,通過設置lockReconnect變量避免重複連接
4)心跳檢測
<script>
const wsUrl = 'ws://127.0.0.1:9000/'
createWebSocket()
function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch (e) {
console.log('catch');
reconnect(wsUrl);
}
}
function init() {
ws.onclose = function () {
console.log('鏈接關閉');
reconnect(wsUrl);
};
ws.onerror = function () {
console.log('發生異常了');
reconnect(wsUrl);
};
ws.onopen = function () {
//心跳檢測重置
heartCheck.start();
websocket.send("<ReadIdCard>");
};
ws.onmessage = function (event) {
console.log('接收到消息');
//拿到任何消息都說明當前連接是正常的
heartCheck.start();
}
}
var lockReconnect = false;//避免重複連接
var tt = null
function reconnect(url) {
if (lockReconnect) {
return;
};
lockReconnect = true;
//沒連接上會一直重連,設置延遲避免請求過多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}
//心跳檢測
var heartCheck = {
timeout: 3000, //每隔三秒發送心跳
num: 3, //3次心跳均未響應重連
timeoutObj: null,
serverTimeoutObj: null,
start: function () {
var _this = this;
var _num = this.num;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function () {
//這裏發送一個心跳,後端收到後,返回一個心跳消息,
//onmessage拿到返回的心跳就說明連接正常
ws.send("123456789"); // 心跳包
_num--;
//計算答覆的超時次數
if (_num === 0) {
ws.colse();
}
}, this.timeout)
}
}
</script>
總結:
我們確認了後端單臺服務器的處理能力有限,因此。我們需要做集羣。其次我們爲了不讓前端關閉或回收,後端不響應。我們需要設置心跳,定時清除無關的連接。
最後,我們需要有消息確認機制,做到保證消息的100%接收。