JavaScript實(shí)現(xiàn)網(wǎng)絡(luò)測(cè)速的方法詳解
一、背景知識(shí)
在我們的日常生活中離不開網(wǎng)絡(luò),而網(wǎng)絡(luò)的快慢直接決定了用戶的產(chǎn)品使用體驗(yàn)。最近我們的 WMS 系統(tǒng)在倉(cāng)庫(kù)使用過(guò)程中出現(xiàn)了網(wǎng)絡(luò)卡頓導(dǎo)致的異常情況,因此需要提供一個(gè)網(wǎng)絡(luò)檢測(cè)功能,當(dāng)倉(cāng)庫(kù)再遇到類似問(wèn)題時(shí)可以先通過(guò)測(cè)量網(wǎng)速來(lái)排查是否網(wǎng)絡(luò)出現(xiàn)了異常。
名詞解釋:
1.ping:給目標(biāo) IP 地址發(fā)送一個(gè) ICMP 報(bào)文,再要求對(duì)方返回一個(gè)大小相同的數(shù)據(jù)包來(lái)確定兩臺(tái)網(wǎng)絡(luò)機(jī)器是否能正常通信以及有多少時(shí)延。我們 ping 一下 github 試試:
這里的 time 指標(biāo)就是時(shí)延數(shù)值。ping 可以作為網(wǎng)絡(luò)情況的首要參考指標(biāo);
2.jitter:抖動(dòng),用來(lái)描述網(wǎng)絡(luò)的波動(dòng)情況。比如每秒測(cè)量一次 ping 值,5s 后取五次測(cè)量結(jié)果的最大最小值求差,可以看出網(wǎng)絡(luò)的波動(dòng)情況,差值越小代表網(wǎng)絡(luò)越穩(wěn)定;
3.bandwidth:帶寬,用來(lái)描述理論上單位時(shí)間內(nèi)網(wǎng)絡(luò)傳輸數(shù)據(jù)的最高速率,它只是一個(gè)理論上的最大值。通常我們所說(shuō)的 1 兆帶寬就是 1Mb/s = 1000Kb/s = (1000/8)KB/s = 125KB/s。帶寬越大自然越好,但是受用戶計(jì)算機(jī)性能、網(wǎng)絡(luò)設(shè)備質(zhì)量、資源使用情況、網(wǎng)絡(luò)高峰期、網(wǎng)站服務(wù)能力、線路衰耗,信號(hào)衰減等多因素的影響,它并不能直接反映當(dāng)前的網(wǎng)絡(luò)環(huán)境;
4.throughput:吞吐量,用來(lái)描述單位時(shí)間內(nèi)網(wǎng)絡(luò)傳輸數(shù)據(jù)的實(shí)際速率。受多方面影響,吞吐量一般都小于真正的帶寬值;
5.上傳速度與下載速度:上傳速度就是從本地上傳一個(gè)文件的速度,相反,下載速度就是從網(wǎng)絡(luò)上下載一個(gè)文件的速度,使用迅雷等下載軟件的時(shí)候看到的那個(gè)數(shù)值就是下載速度,通常下載速度會(huì)大于上傳速度。由于下載場(chǎng)景較多,我們更關(guān)心下載速度數(shù)值。
在網(wǎng)絡(luò)檢測(cè)中,沒有單獨(dú)哪一個(gè)指標(biāo)可以說(shuō)明問(wèn)題,應(yīng)盡可能多的結(jié)合各種指標(biāo)來(lái)全面評(píng)估網(wǎng)絡(luò)情況。接下來(lái)介紹幾種測(cè)速方法。
二、Network Information API
瀏覽器為我們提供了網(wǎng)絡(luò)相關(guān)的 API ,NetworkInformation 提供了設(shè)備與網(wǎng)絡(luò)進(jìn)行通信的信息和鏈接類型變更時(shí)的有關(guān)事件,它是通過(guò) Navigator
的 connection
屬性進(jìn)行訪問(wèn)的。connection
對(duì)象有一個(gè) downlink
屬性,返回以 Mb/s 為單位的有效帶寬,MDN 上官方解釋說(shuō)該值是基于最近監(jiān)測(cè)的保持活躍連接的應(yīng)用層吞吐量,因此吞吐量的查詢并不是實(shí)時(shí)的,如果距離上一個(gè) http 請(qǐng)求間隔較長(zhǎng),這個(gè)數(shù)值并不準(zhǔn)確。因此 downlink
值只具備有限的參考意義,且該功能還在實(shí)驗(yàn)中,不同瀏覽器兼容性也較差,因此不推薦使用這種方式來(lái)檢測(cè)網(wǎng)絡(luò)情況。
補(bǔ)充一下,connection
對(duì)象還有一個(gè) type
屬性和 onChange
方法,type
屬性返回的是當(dāng)前設(shè)備聯(lián)網(wǎng)的類型,枚舉值有如下幾種:
- bluetooth
- cellular
- ethernet
- none
- wifi
- wimax
- other
- unknown
當(dāng)聯(lián)網(wǎng)類型 type
發(fā)生改變時(shí),會(huì)觸發(fā) change 事件,通過(guò) onChange
回調(diào)函數(shù)能做一些事情:比如我們?cè)诓シ乓曨l時(shí),從 wifi 環(huán)境切換為使用流量時(shí),可以暫停視頻并提示用戶選擇是否用流量繼續(xù)播放。
三、測(cè)量 ping 和 jitter 值
由于 JS 無(wú)法真正原生地測(cè)量 ping 值,因此需要提供一種替代方案來(lái)模擬。為了盡可能準(zhǔn)確地得到 ping 值,可以通過(guò)請(qǐng)求一個(gè)盡量小的資源來(lái)模擬發(fā)送 ICMP 報(bào)文,記錄發(fā)起請(qǐng)求到收到返回值的時(shí)間差。請(qǐng)求的內(nèi)容可以是網(wǎng)站的 favicon.ico ,一個(gè)空文件,甚至是一個(gè)空接口(注意需要配置跨域)。但是這些方案都依賴于圖片資源、文件以及接口的穩(wěn)定性,如果服務(wù)掛掉的話,得到的 ping 值是有問(wèn)題的。接下來(lái)通過(guò)多次測(cè)量 ping 值就可以計(jì)算代表網(wǎng)絡(luò)波動(dòng)情況的 jitter 值了。代碼如下:
const Dashboard = React.memo(() => { const [ping, setPing] = useState<number>(0); const [count, setCount] = useState<number>(0); const [pingList, setPingList] = useState<number[]>([]); const [jitter, setJitter] = useState<number>(0); useEffect(() => { const timer = setInterval(() => { const img = new Image(); const startTime = new Date().getTime(); // 此處選擇加載 github 的 favicon,大小為2.2kB img.src = `https://github.com/favicon.ico?d=${startTime}`; img.onload = () => { const endTime = new Date().getTime(); const delta = endTime - startTime; if ((count + 1) % 5 === 0) { const maxPing = Math.max(delta, ...pingList); const minPing = Math.min(delta, ...pingList); setJitter(maxPing - minPing); setPingList([]); } else { setPingList(lastList => [...lastList, delta]); } setCount(count + 1); setPing(delta); }; img.onerror = err => { console.log('error', err); }; }, 3000); return () => clearInterval(timer); }, [count, pingList]); return ( <PageContainer className={styles.dashboard}> <div className="text-center"> <h1>歡迎使用 倉(cāng)儲(chǔ)管理系統(tǒng)</h1> <h1>PING: {ping}ms</h1> <h1>抖動(dòng): {jitter}ms</h1> </div> </PageContainer> ); });
以上代碼是采用測(cè)量加載 github favicon 的時(shí)間來(lái)模擬 ping 值的,圖片大小為 2.2kB,可以獲得更準(zhǔn)確的 ping 值。注意在 img.src 的 url 最后拼接上一個(gè)時(shí)間戳,保證每次都會(huì)重新發(fā)起請(qǐng)求,而不是使用第一次加載的圖片緩存。動(dòng)圖效果如下,3 秒測(cè)量一次 ping 值,拿到最近 5 次 ping 值后計(jì)算一次抖動(dòng)值:
四、測(cè)量下載速度
下載速度測(cè)量與上述 ping 值測(cè)量原理相同,只不過(guò)需要將下載的對(duì)象換成一個(gè)更大的資源,通過(guò)計(jì)算單位時(shí)間內(nèi)下載資源的大小來(lái)測(cè)量下載速度。像下載軟件迅雷,我們??吹降哪莻€(gè)數(shù)字就是下載速度。另外迅雷還有一個(gè)很好的功能可以選擇全速下載模式和不影響正常上網(wǎng)的模式,因?yàn)橄螺d時(shí)可能會(huì)擠占帶寬影響用戶正常瀏覽網(wǎng)頁(yè)。其中的原理就是迅雷在下載的時(shí)候在不停做 ping,如果發(fā)現(xiàn) ping 的延遲增加,就限制下載速度,如果 ping 還高,就繼續(xù)降到 ping 回歸期望值。
五、總結(jié)
如果用戶感到訪問(wèn)的網(wǎng)站反應(yīng)過(guò)慢,有可能是各種原因?qū)е碌?,大致可以遵循以下流程進(jìn)行簡(jiǎn)單排查:
1.打開百度等常用網(wǎng)站,查看是否仍然存在網(wǎng)速慢的情況。如果其他網(wǎng)站訪問(wèn)正常,可以確定是當(dāng)前站點(diǎn)的問(wèn)題,需要繼續(xù)排查:
可能是 DNS 解析問(wèn)題,可以在終端輸入 nslookup + 當(dāng)前網(wǎng)站域名來(lái)檢查:
如果 DNS 解析正常,那么有可能是網(wǎng)站訪問(wèn)量過(guò)高等原因,具體情況還需排查;
2.如果其他網(wǎng)站速度也比較慢,可以檢查是否在下載文件,如果在下載文件也是會(huì)占用帶寬的,可以選擇下載軟件的限制帶寬功能來(lái)確保正常上網(wǎng)網(wǎng)速;
3.如果確實(shí)網(wǎng)絡(luò)有問(wèn)題,那就需要運(yùn)營(yíng)商維修人員來(lái)排查了,有可能是各種原因:用戶計(jì)算機(jī)性能、網(wǎng)絡(luò)設(shè)備質(zhì)量、網(wǎng)絡(luò)高峰期、線路衰耗、信號(hào)衰減等等。
注意事項(xiàng):
1.不要在頁(yè)面加載的初始階段就去測(cè)速,否則會(huì)影響 LCP 時(shí)間,建議等組件 mounted 后再測(cè)速;
2.根據(jù)業(yè)務(wù)場(chǎng)景合理設(shè)計(jì)測(cè)速方案,比如根據(jù)測(cè)速時(shí)機(jī)的不同分為兩種方案:
- 實(shí)時(shí)檢測(cè):設(shè)置時(shí)間間隔來(lái)實(shí)時(shí)檢測(cè)網(wǎng)絡(luò)狀況,優(yōu)點(diǎn)是當(dāng)網(wǎng)絡(luò)出現(xiàn)異常時(shí)可以提前告警,缺點(diǎn)是會(huì)浪費(fèi)網(wǎng)絡(luò)請(qǐng)求;
- 人為觸發(fā)檢測(cè):用戶察覺網(wǎng)絡(luò)出現(xiàn)異常時(shí),再手動(dòng)觸發(fā)檢測(cè)優(yōu)點(diǎn)是節(jié)省網(wǎng)絡(luò)資源,缺點(diǎn)是缺乏預(yù)警性;
3.若使用加載圖片的方式測(cè)量,圖片 url 應(yīng)拼接時(shí)間戳,防止請(qǐng)求時(shí)直接使用緩存。
到此這篇關(guān)于JavaScript實(shí)現(xiàn)網(wǎng)絡(luò)測(cè)速的方法詳解的文章就介紹到這了,更多相關(guān)JavaScript網(wǎng)絡(luò)測(cè)速內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
dedecms頁(yè)面如何獲取會(huì)員狀態(tài)的實(shí)例代碼
下面小編就為大家?guī)?lái)一篇dedecms頁(yè)面如何獲取會(huì)員狀態(tài)的實(shí)例代碼。一起跟隨小編過(guò)來(lái)看看吧,希望對(duì)大家有所幫助。2016-03-03JavaScript ECMA-262-3 深入解析(一):執(zhí)行上下文實(shí)例分析
這篇文章主要介紹了JavaScript ECMA-262-3 執(zhí)行上下文,結(jié)合實(shí)例形式詳細(xì)分析JavaScript ECMA執(zhí)行上下文相關(guān)概念、原理與操作注意事項(xiàng),需要的朋友可以參考下2020-04-04JavaScript蒙板(model)功能的簡(jiǎn)單實(shí)現(xiàn)代碼
本文給大家介紹JavaScript蒙板(model)功能的簡(jiǎn)單實(shí)現(xiàn)代碼,創(chuàng)建一個(gè)蒙板, 設(shè)置蒙板的堆疊順序保證能將其它元素蓋住,感興趣的朋友可以參考下實(shí)現(xiàn)代碼2016-08-08JavaScript實(shí)現(xiàn)區(qū)塊鏈
很多朋友都聽說(shuō)過(guò)比特幣和以太幣這樣的加密貨幣,但是只有極少數(shù)人懂得隱藏在它們背后的技術(shù),接下來(lái)通過(guò)本文給大家介紹用JavaScript來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的區(qū)塊鏈來(lái)演示它們的內(nèi)部究竟是如何工作的,感興趣的朋友一起看看吧2018-03-03使用JavaScript實(shí)現(xiàn)文本收起展開(省略)功能
省略號(hào),作為一種常見的文本處理方式,在很多情況下都十分常見,特別是當(dāng)我們需要在省略號(hào)后面添加額外文字時(shí),本文為大家介紹了使用JavaScript實(shí)現(xiàn)文本收起展開功能的相關(guān)方法,希望對(duì)大家有所幫助2024-04-04微信小程序?qū)W習(xí)筆記之函數(shù)定義、頁(yè)面渲染圖文詳解
這篇文章主要介紹了微信小程序?qū)W習(xí)筆記之函數(shù)定義、頁(yè)面渲染,結(jié)合實(shí)例形式較為詳細(xì)的分析了微信小程序中函數(shù)的定義、生命周期、模板調(diào)用、樣式控制等操作技巧,并配合圖文形式進(jìn)行了詳細(xì)說(shuō)明,需要的朋友可以參考下2019-03-03通過(guò)隱藏iframe實(shí)現(xiàn)無(wú)刷新上傳文件操作
本文給大家介紹iframe無(wú)刷新上傳文件,通過(guò)一個(gè)隱藏的iframe來(lái)處理上傳操作我采用的是ReactJS,amazeui,nodejs1.html target指向iframe的name,就是把上傳后的操作交給iframe來(lái)處理2016-03-03