1. 背景知识
互联网与我们的日常生活密不可分,互联网的速度直接决定了用户的产品体验。 近期,我们的WMS系统在仓库使用过程中出现了因网络延迟导致的异常情况。 因此有延迟的测速软件,我们需要提供一个网络检测功能。 当仓库再次遇到类似问题时,我们可以先测量网络速度,检查网络是否存在异常。
词汇表:
Ping:向目标IP地址发送ICMP报文,然后要求对方返回相同大小的数据包,以确定两台网络机器是否可以正常通信以及有多少延迟。 让我们尝试 ping github:
这里的时间指标就是延迟值。 Ping可以作为网络状况的主要参考指标;
jitter:抖动,用来描述网络波动。 例如每秒测量一次ping值,5秒后取5次测量结果的最大值和最小值,计算差值。 可以看到网络的波动情况。 差异越小,网络越稳定。
带宽:带宽用来描述单位时间内网络数据传输的理论最大速率。 这只是理论上的最大值。 通常我们所说的1Mbit带宽是1Mb/s = 1000Kb/s = (1000/8)KB/s = 125KB/s。 带宽越宽越好。 但它受用户计算机性能、网络设备质量、资源使用情况、网络高峰期、网站服务能力、线路衰减、信号衰减等诸多因素的影响,不能直接反映当前的网络环境。 ;
吞吐量:吞吐量,用来描述单位时间内网络传输数据的实际速率。 受多方面影响,吞吐量普遍小于真实带宽值;
上传速度和下载速度:上传速度是指文件上传到本地的速度。 相反,下载速度是从互联网下载文件的速度。 使用迅雷等下载软件时看到的数值就是下载速度。 通常下载速度会大于上传速度。 由于下载场景较多,我们更关心的是下载速度值。
在网络检测中,没有任何单一指标可以解释问题。 应尽可能结合各种指标来综合评估网络状况。 接下来我们将介绍几种测速方法。
2. 网络信息API
浏览器为我们提供了与网络相关的API。 NetworkInformation 提供有关设备与网络之间的通信以及链路类型更改时的相关事件的信息。 它是通过Navigator的连接属性来访问的。 连接对象具有下行链路属性,该属性返回有效带宽(以 Mb/s 为单位)。 MDN 上的官方解释是,这个值是基于最近监控的保持活跃连接的应用层吞吐量。 因此,吞吐量查询不是实时的。 如果距上次 http 请求的时间间隔较长,则该值不准确。 因此,下行值的参考意义有限,而且该功能还处于实验阶段,不同浏览器的兼容性也较差,所以不建议使用该方法来检测网络状况。
补充一下,连接对象还有一个 type 属性和 onChange 方法。 type 属性返回当前设备联网的类型。 枚举值如下:
当组网类型发生变化时,会触发change事件。 onChange回调函数可以做一些事情:比如当我们在播放视频时从wifi环境切换到使用数据时,我们可以暂停视频并提示用户选择是否使用数据继续播放。 。
3. 测量 ping 和抖动值
由于 JS 本身无法真正测量 ping,因此需要提供替代方案来模拟它。 为了尽可能准确地获取 ping 值,可以通过请求尽可能小的资源来模拟发送 ICMP 报文,并记录从发起请求到收到返回值的时间差。 请求的内容可以是网站的favicon.ico,也可以是空文件,甚至可以是空界面(注意需要跨域配置)。 然而这些解决方案都依赖于图像资源、文件和接口的稳定性。 如果服务挂了,获取的ping值就会有问题。 接下来,通过多次测量Ping值,可以计算出代表网络波动的抖动值。 代码如下所示:
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 (
"text-center">
欢迎使用 仓储管理系统</h1>
PING: {ping}ms
h1>
抖动: {jitter}ms</h1>
div>
</PageContainer>
);
});
上面的代码通过测量加载 github favicon 所需的时间来模拟 ping 值。 图像大小为2.2kB,因此可以获得更准确的ping值。 注意,img.src的url末尾拼接了一个时间戳,以保证每次都会重新发起请求,而不是使用第一次加载的图片缓存。 动画效果如下。 每3秒测量一次Ping值,获取最后5个Ping值后计算抖动值:
4. 测量下载速度
下载速度测量原理与上述ping值测量相同,只不过下载对象需要更换为更大的资源,通过计算单位时间内下载资源的大小来测量下载速度。 像下载软件迅雷,我们经常看到的数字就是下载速度。 另外,迅雷还有一个不错的功能,可以让你选择全速下载模式或者不影响正常上网的模式,因为下载可能会占用带宽,影响用户正常浏览网页。 原理是迅雷下载的时候一直在ping。 如果发现ping延迟增加,就会限制下载速度。 如果 ping 仍然很高,则会继续下降到预期的 ping 返回值。
5. 总结
如果用户感觉所访问的网站响应速度太慢,可能是由多种原因造成的。 一般可以按照以下流程进行简单的故障排除:
打开百度等常用网站查看网速是否依然存在。 如果访问其他网站都正常,则可以确定问题出在当前网站,需要进一步排查:
如果其他网站也很慢,您可以检查它们是否正在下载文件。 如果下载文件也会占用带宽,可以选择下载软件的带宽限制功能,以保证正常的上网速度;
如果网络确实存在问题,就需要运营商的维护人员进行排查。 原因可能有多种:用户电脑性能、网络设备质量、网络高峰期、线路衰减、信号衰减等。
防范措施:
不要在页面加载初期测量速度,否则会影响LCP时间。 建议等到元件贴装后再测量速度;
根据业务场景合理设计测速方案。 例如有延迟的测速软件,根据测速时机的不同,可以分为两种方案:
如果使用加载图片的方式进行测量,则图片URL要拼接时间戳,防止请求时直接使用缓存。
参考
[1]
网络信息 API - Web API | 管理中心:
[2]
日常使用的 Ping 命令是什么? :
[3]
在前端网络上也可以这样玩:
[4]
探索浏览器端网络速度测试:
[5]
[6]
ping.js,使用 Javascript Ping 网络.: #notes,下载ping.js的源码_GitHub_帮酷
[7]