公交车上荫蒂添的好舒服的电影-公用玩物(np双xing总受)-公用小荡货芊芊-公与妇仑乱hd-攻把受做哭边走边肉楼梯play-古装一级淫片a免费播放口

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

瀏覽器節(jié)能機(jī)制導(dǎo)致Websocket斷連的坑

freeflydom
2024年4月29日 16:20 本文熱度 1781

序言

你踩過嗎?瀏覽器節(jié)能機(jī)制導(dǎo)致Websocket斷連的坑~~~

近期,在使用WebSocket(WS)連接時(shí)遇到了頻繁斷連的問題,這種情況在單個(gè)用戶上每天發(fā)生數(shù)百次。盡管利用了socket.io的自動(dòng)重連機(jī)制能夠在斷連后迅速恢復(fù)連接,但這并不保證每一次重連都能成功接收WS消息。因此,我們進(jìn)行了一些的排查和測(cè)試工作。

最終發(fā)現(xiàn)問題的根本原因:正是瀏覽器的節(jié)能機(jī)制,不經(jīng)意間成為了這一問題的幕后黑手

瀏覽器節(jié)能機(jī)制簡(jiǎn)介

瀏覽器的節(jié)能機(jī)制逐漸成為前端開發(fā)者需要關(guān)注的問題。特別是這些節(jié)能機(jī)制可能會(huì)對(duì)定時(shí)器的精度產(chǎn)生影響,這直接關(guān)系到前端應(yīng)用的用戶體驗(yàn),在某些場(chǎng)景下甚至影響到用戶的使用。

為了減少電能消耗,提高電池續(xù)航能力,現(xiàn)代瀏覽器都引入了節(jié)能機(jī)制。這些機(jī)制包括但不限于降低空閑標(biāo)簽頁的CPU使用率、減少后臺(tái)JavaScript的執(zhí)行頻率、限制定時(shí)器的精確度等。雖然這些措施顯著提高了設(shè)備的能效,但也給前端開發(fā)帶來了一些挑戰(zhàn)。

WS頻繁斷連原因分析

查閱socket.io官網(wǎng)服務(wù)端配置的pingTimeoutpingInterval兩個(gè)參數(shù)發(fā)現(xiàn)WS心跳異常時(shí)會(huì)導(dǎo)致重連,具體說明:

WS連接中服務(wù)端和客戶端兩端必須一直保持心跳。如果有一端停止,則滿足如下條件之一就會(huì)自動(dòng)斷連:

  • 服務(wù)器發(fā)送 ping,如果客戶端在毫秒內(nèi) pingTimeout 沒有用 pong 應(yīng)答,則服務(wù)器認(rèn)為連接已關(guān)閉。

  • 同樣,如果客戶端在毫秒內(nèi) pingInterval + pingTimeout 未收到來自服務(wù)器的 ping,則客戶端也會(huì)認(rèn)為連接已關(guān)閉。

看文檔發(fā)現(xiàn)其實(shí)高版本的socket.io是由服務(wù)端定時(shí)發(fā)起ping。而在socket.io 2.X的版本中內(nèi)置的心跳機(jī)制是由客戶端定時(shí)發(fā)起。而瀏覽器在后臺(tái)運(yùn)行時(shí),即使你設(shè)置了一個(gè)每秒觸發(fā)的定時(shí)器,它也只能每分鐘觸發(fā)一次,超過了pingInterval + pingTimeout設(shè)置的時(shí)間,最后看到的日志是很有規(guī)律的每分鐘重連一次。在之前寫的這篇文章中也有相關(guān)的介紹《掌握Web Workers:徹底解鎖前端多線程編程的潛力》

WS頻繁斷連解決方法

@升級(jí)socket.io到最新版本

上面的截圖其實(shí)就是最新版本(4.x)的,升級(jí)后由服務(wù)器定時(shí)發(fā)起心跳。在服務(wù)端定時(shí)運(yùn)行,避開了瀏覽器節(jié)能機(jī)制對(duì)定時(shí)器的影響

@自定義WS心跳事件

為了減小直接升級(jí)對(duì)已有業(yè)務(wù)的影響,目前使用的也是這種方案:在服務(wù)端自定義心跳事件,定時(shí)發(fā)送心跳custom-ping

// 客戶端的CODE

io.on('custom-ping', function () {

  io.emit('custom-pong', Date.now())

})


// 服務(wù)端CODE

io.on('connection', (socket) => {

  console.log('New client connected');


  // 發(fā)送自定義ping消息

  const pingInterval = setInterval(() => {

    socket.emit('custom-ping', Date.now());

  }, 10000); // 每10秒發(fā)送一次


  // 監(jiān)聽自定義pong消息

  socket.on('custom-pong', (data) => {

    console.log('Pong received:', data);

  });


  socket.on('disconnect', () => {

    clearInterval(pingInterval);

    console.log('Client disconnected');

  });

});


注意:斷連時(shí)一定要銷毀定時(shí)器

其實(shí),socket.io是有內(nèi)置心跳的(2.x版本客戶端定時(shí)發(fā)起,4.x由服務(wù)端定時(shí)發(fā)起),自定義心跳的意義主要在于保持?jǐn)?shù)據(jù)交換,在這個(gè)時(shí)間間隔內(nèi)保持?jǐn)?shù)據(jù)交換,socket就不會(huì)自動(dòng)中斷重連。

@使用setTimeout

這里要注意使用setTimeout的姿勢(shì),如果是直接這樣使用、依然會(huì)有精度問題。

setTimeout丟失精度的情況:

// 以下setTimeout仍然會(huì)丟失精度

let _cacheTs = Date.now()

const _setTimeoutFn = () => {

  console.log('setTimeout :>> ', Date.now() - _cacheTs);

  _cacheTs = Date.now()

  setTimeout(() => {

    _setTimeoutFn()

  }, 5000)

}

_setTimeoutFn()

在setTimeout里面去執(zhí)行一個(gè)函數(shù)棧會(huì)被瀏覽器監(jiān)控到,會(huì)認(rèn)為和setInterval一樣,其在后臺(tái)運(yùn)行時(shí)會(huì)降低其定時(shí)精度。  但如果這樣可以避開節(jié)能機(jī)制的限制:

setTimeout不丟失精度的情況:

// 客戶端CODE

// 監(jiān)聽服務(wù)端發(fā)送的custom-pong事件

socket.on('custom-pong', onHeart)


const onHeart = () => {

  if (timer) {

    clearTimeout(pingTime.current)

  }

  timer = window.setTimeout(() => {

    socket.emit('custom-ping', Date.now())

  }, 5000)

}


// 服務(wù)端CODE

socket.on('custom-ping', ()=>{

  socket.emit('custom-pong', Date.now())

})

@使用Web-Workers

在Web-Workers線程內(nèi)發(fā)起定時(shí)不受瀏覽器節(jié)能機(jī)制的限制,相關(guān)示例在這篇文章里也有介紹《掌握Web Workers:徹底解鎖前端多線程編程的潛力》

@頁面保活(實(shí)測(cè)無效)

在后臺(tái)運(yùn)行時(shí)也保持瀏覽器的活躍,用得最多的方式是在頁面隱藏一個(gè)循環(huán)播放的音頻 或者 使用nosleep.js


const noSleepInstance = new NoSleep();

document.addEventListener('click', function enableNoSleep() {

  document.removeEventListener('click', enableNoSleep, false);

  noSleepInstance.enable();

}, false);


實(shí)測(cè),使用這種方式時(shí),瀏覽器在后臺(tái)運(yùn)行仍然存在定時(shí)器精度降低的問題

小結(jié)

WS頻繁斷連的原因:

  1. 使用了低版本(2.x)的socket.io

  2. 客戶端每5秒定時(shí)發(fā)送 心跳

  3. 瀏覽器后臺(tái)運(yùn)行時(shí)觸發(fā)節(jié)能機(jī)制限制了定時(shí)器的精度,由每5秒變成了實(shí)際的每分鐘執(zhí)行一次

  4. 每分鐘執(zhí)行一次遠(yuǎn)大于socket.io設(shè)置的pingTimeout時(shí)間

  5. WS斷開連接

  6. socket.io內(nèi)置的重連機(jī)制,立即重連成功

  7. 查看日志發(fā)現(xiàn)每分鐘重連一次。
    在實(shí)際排查中,是從第七步倒退排查發(fā)現(xiàn)是瀏覽器節(jié)能機(jī)制所引起的問題。。。

總結(jié)


作者:tager
鏈接:https://juejin.cn/post/7362576319928008755
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。



該文章在 2024/4/29 16:20:37 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产v一区二区三区色欲 | 99久久人人爽亚洲 | 国产1区2区在线观看 | 动漫av永久无码精品每日更新 | 国产成年无码久久久免费 | 黑人一区二区三区中文字幕 | 国产欧美高日韩精品久久一区二区 | 国产午夜无码视频在线观看 | 国产欧美va天堂在线观看视频 | 国产av福利久久精品can | 91国在线啪精品一区 | 99亚洲精品高清一二区 | 国产精品丝袜久久久久久不卡 | 丰满人妻销魂娇喘呻吟 | 大尺度亚洲写真图片在线 | 国产午夜视频在线 | 91精品隔壁老王在线观看 | av在线播放免费 | 国产精品无码午夜福利 | 国产高清无码视频 | 国产另类亚洲第1 | 国产精品一区二区中文字幕 | 国产精品无码影视久久久久久久 | 国产成人午夜福利影片 | 国内精品无码视频在线 | 国产毛片一级片试看 | 激情欧美在线一区 | 91看片淫黄大片一级在线观看 | 国产门事件在线亚洲日韩欧美 | 国产a线视频播放 | 国产av无码片毛片一级流奶水 | 国产精品三级国产电影 | 国产精品va无码一区二区三区 | 国产区人妖另类精 | 精品国产91av| 国产熟人av一二三区 | 国产v欧美ⅴ日韩v | 国产午夜无码精品 | 精品国产一区二区三区高清观看 | 国产精品一区二区av麻豆 | 变态另类区sm一区 |