B/S架构,用户都是使用浏览器访问后端服务,产品在开发时需要关注用户的体验,不仅包含交互的友好,性能指标也非常重要。对于后端开发常见的性能指标,可能包含:reponse time,吞吐量等。此外,浏览器页面导航,html数据解析,生成可显示位图等待阶段的性能分析也十分重要,前端性能指标如下图所示。本篇文章,简单介绍两种获取浏览器页面展示的性能分析数据的工具。
一.Skywalking(8.2及以上)
1.安装依赖
npm install skywalking-client-js --save
本地的后台项目嵌入了前端ui的,所以安装的时候直接进入前端目录下进行安装即可。
安装成功之后如下图所示目录:
2.引入依赖
import ClientMonitor from 'skywalking-client-js';
在需要监控的页面引入 相应的依赖即可,如下图所示:
注意:skywalking追踪信息收集器有两个,一个是 gRPC的用于后端服务,一个是Http 收集客户端浏览器的采集信息 ,Http默认端口 12800,gRPC默认端口 11800,前端访问后台服务可能会存在跨域的问题,所以可在前端vue.config.js中配置相关的代理即可。
3.配置成功,访问之后结果如图
二.Chrome Performance Api 监测网页性能
chrome浏览器为我们提供了Performance性能检测调试工具。此外,W3C也定义了一套Performance标准,各个浏览器厂商基于标准提供了监控网络性能的一系列基础Api,这些Api可以提供检测白屏时间、首屏时间、用户可操作的时间节点,页面总下载的时间、DNS查询的时间、TCP链接的时间等。我们完全可以利用这个搭建一个简易的性能监控工具,当然监控系统包含了数据采集->数据存储->清洗->监控几个过程,不过目前我们这里简单运用一下Performance Api就只考虑采集阶段。
performance的所有Api&property挂载在window下面的performance属性中,可以看到目前提供的一系列属性,关于各个属性的介绍,参照网上对api的解释,有大量资料可供查询。
如上图所示,performance包含三个对象,分别为 memory、navigation、timing。
-
memory:是和内存相关的,其提供对内存使用情况的描述,我们可以使用这个属性来订阅页面内存变化情况
-
jsHeapSizeLimit:堆内存大小的限制
-
totalJSHeapSize:总堆内存的大小
-
usedJSHeapSize:已经使用的堆内存大小
-
-
navigation:含义是页面的来源信息,表述页面怎么跳转过来的,该对象有2个属性值
-
redirectCount : 记录重定向次数,如果有重定向的话,页面通过几次重定向跳转而来,默认为0
-
type : 页面打开的方式,默认为0,可取值为「0:表示正常进入该页面(非刷新、非重定向)」、「1:表示通过 window.location.reload 刷新的页面」、「2:表示通过浏览器的前进、后退按钮进入的页面」、「255:表示非以上的方式进入页面的」
-
-
timing:提供页面加载过程中一系列关键时间点的高精度测量,它包含了网络、解析、加载等一系列的时间数据,我们监控网页性能也是基于此提供的属性。为了方便理解,从网上找了一张图片来解释关键节点的含义。
-
navigationStart : 一个页面卸载结束时的时间戳。如果没有上一个页面的话,那么该值会和fetchStart的值相同
-
redirectStart : 第一个http重定向开始的时间戳,如果没有重定向,或者重定向到一个不同源的话,那么该值返回为0
-
redirectEnd : 最后一个HTTP重定向完成时的时间戳。如果没有重定向,或者重定向到一个不同的源,该值也返回为0
-
fetchStart : 浏览器准备好使用http请求抓取文档的时间(发生在检查本地缓存之前)。
-
domainLookupStart : DNS域名查询开始的时间,如果使用了本地缓存话,或持久链接,该值则与fetchStart值相同
-
domainLookupEnd : DNS域名查询完成的时间,如果使用了本地缓存话,或 持久链接,该值则与fetchStart值相同
-
connectStart : HTTP 开始建立连接的时间,如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接开始时间
-
secureConnectionStart : HTTPS 连接开始的时间,如果不是安全连接,则值为 0
-
connectEnd:HTTP完成建立连接的时间(完成握手)。如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接完成时间
-
requestStart : http请求读取真实文档开始的时间,包括从本地读取缓存,链接错误重连时
-
responseStart : 开始接收到响应的时间(获取到第一个字节的那个时候)。包括从本地读取缓存
-
responseEnd : HTTP响应全部接收完成时的时间(获取到最后一个字节)。包括从本地读取缓存
-
unloadEventStart : 前一个网页(和当前页面同域)unload的时间戳,如果没有前一个网页或前一个网页是不同的域的话,那么该值为0
-
unloadEventEnd : 和 unloadEventStart 相对应,返回是前一个网页unload事件绑定的回调函数执行完毕的时间戳。
-
domLoading : 开始解析渲染DOM树的时间
-
domInteractive : 完成解析DOM树的时间(只是DOM树解析完成,但是并没有开始加载网页的资源)
-
domContentLoadedEventStart : DOM解析完成后,网页内资源加载开始的时间
-
domContentLoadedEventEnd : DOM解析完成后,网页内资源加载完成的时间
-
domComplete : DOM树解析完成,且资源也准备就绪的时间。Document.readyState 变为 complete,并将抛出 readystatechange 相关事件
-
loadEventStart : load事件发送给文档。也即load回调函数开始执行的时间,如果没有绑定load事件,则该值为0
-
loadEventEnd : load事件的回调函数执行完毕的时间,如果没有绑定load事件,该值为0
可以通过performance api来实现我们经常关注的一些指标的计算和上报,如下图所示,主要是参考基调听云的指标:https://demo.tingyun.com/doc/browser/metric/indicator.html
//来自于用户访问时的浏览器的performance api获取
var item = performance.timing;
const dnsTime = item.domainLookupEnd - item.domainLookupStart;
const isSSL = item.name.includes("https");
const sslTime = isSSL ? item.connectEnd - item.secureConnectionStart : 0;
const tcpEnd = isSSL ? item.secureConnectionStart : item.connectEnd;
const tcpTime = tcpEnd - item.connectStart;
const stalledTime = item.requestStart - item.fetchStart - dnsTime - tcpTime - sslTime;
//Stalled:[item.fetchStart, item.fetchStart + stalledTime]
//DNS:[item.domainLookupStart, item.domainLookupEnd]
//TCP:[item.connectStart, tcpEnd]
//SSL: [tcpEnd, item.connectEnd]
//请求响应: [item.requestStart, item.responseStart]
//内容传输: [item.responseStart, item.responseEnd]