做一个能对标阿里云的前端APM工具(下)
上篇请访问这里做一个能对标阿里云的前端APM工具(上)
样本多样性问题
上一小节中的实施方案是微观的,即单次性的、具体的。但是从宏观上看,我需要保证性能测试是公允的,符合大众预期的。为了达到这种效果,最简单的方式就是保证测试的多样性,让足够多人访问产生足够多的样本来,但这对于一个为个人服务的工具网站来说是不现实的。
于是我打算借助机器的力量,在世界各地建造机器人程序来模拟访问。机器人程序原理非常简单,借助 headless chrome 来模拟用户的访问:
const url = 'https://www.site2share.com/folder/20020507';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
await page.waitForSelector('.single-folder-container');
await page.waitForTimeout(1000 * 30);
browser.close();
注意程序会等到 .single-folder-container 元素出现之后才进入关闭流程,在关闭前会等待30秒钟来保证有足够的时间将指标数据上传到 Application Insights。
为了达到重复访问的效果,我给机器人制定的执行策略非常简单,每五分钟执行一次。这种轻量级的定时任务应用非常适用于部署在 Azure Serverless 上,同时 Azure Serverless 也支持在部署时指定区域,这样就能达到模拟全球不同地区访问的效果

虽然每一个 Serverless Function 都能配置独立的执行间隔,但考虑到可维护性,比如将来希望将5分钟执行间隔提高到2分钟时不去修改27里的每一个 function,我决定将所有 function 交给 Azure Logic App 进行管理
Azure Logic App 在我看来是一款可视化低代码工具。它能够允许非编程人员以点击拖拽的形式创建工作流。初始化变量、分支判断、循环、响应或者发送网络请求,都可以仅用鼠标办到。
我们的场景总结下来就两句话:
- 距离上次进行性能测试是不是已达五分钟
- 如果是的话再次发送性能测试请求
那么我们可以依次创建一套工作流
- 工作流的触发器为一个定时任务,每十分钟执行一次
- 定时任务执行时连带执行所有的 Azure Function

Azure Logic App 还会将每次的执行情况记录下来,甚至每个函数的输入和输出,某种意义上这也起到了监控执行的作用

审视数据,发现问题
工具开发完成之后不间断的运行了七天,这七天时间内共产生了 219613 条数据。看看我们能从这二十万数据钟能发现什么
首先我们要看一个最重要的指标:关键元素的出现时机
customMetrics
| where timestamp between (datetime(2022-02-01) .. datetime(2022-02-06))
| where name has 'folder-detail:visible'
| extend location =strcat(client_City, ":", client_StateOrProvince, ":", client_CountryOrRegion)
| summarize metric_count=count(), avg_duration=round(avg(valueMax)) by location
| where metric_count > 100
| order by avg_duration asc
指标数据我按照国家地区排序,在我看来地区会是影响速度的关键因素,最终结果如下。抱歉我使用的名称是 avg_duration 这个有误导的名称,实际上这个指标应该是一个 startTime,即从浏览器开始加载页面的开始为起点,到看到元素的时间。下面的 first-contentful-paint 同理

从肉眼上我们可以感知到,大部分用户会在3秒左右才会看到实质性内容。接下来我们要做的就是探索3秒钟的时间去哪了。
顺便也可以查询一下浏览器提供的 first-contentful-paint 数据如何。上面的查询语句在之后会频繁被用到,所以我们可以提取一个函数出来
let queryMetricByName = (inputName: string) {
customMetrics
| where timestamp between (datetime(2022-02-01) .. datetime(2022-02-06))
| where name has inputName
| extend location =strcat(client_City, ":", client_StateOrProvince, ":", client_CountryOrRegion)
| summarize metric_count=count(), avg_duration=round(avg(valueMax)) by location
| where metric_count > 100
| order by avg_duration asc
};
接着用这个函数查询 first-contentful-paint 指标
queryMetricByName('browser:first-contentful-paint')

浏览器认为用户在 1.5 秒左右就看到了一些有用的内容了,但是从我们刚刚查询到的关键元素出现时机看来并非如此
我们先看看脚本的资源加载情况,以 runtime 脚本为例,我们看看它的平均加载时间
queryMetricByName('resource:script:https://www.site2share.com/runtime-es2015.ffba78f539fb511f7b4b.js')

平均时间不过 100ms
而 http 请求指标数据呢
queryMetricByName('resource:xmlhttprequest')

相比资源加载而言,平均1s的请求时长已经是资源加载时长的好几倍了,它有很大的嫌疑。接着我们继续看后端 SQL 查询数据性能
queryMetricByName('APM:GET_SINGLE_FOLDER:FIND_BY_ID')

首先要理解一下为什么这里只有一类地理位置的数据,因为之前所有的前端数据都又不同地区的机器人感知产生。因为我的后端服务器只有一台。虽然机器人从世界各地访问,但是查询总发生在这一台服务器上
这里就很有意思了。也就是说平均请求时间我们需要花上一秒钟,但是实际的 SQL 查询时间只需要100毫秒
为了还原犯罪事实,我们不妨从选取一次具体的请求,看看从后端到前端的时间线是怎么样的。这个时候 Application Insights 的 Telementry Correlation 的功能就体现出来了,我们只需要指定一个 operation_id 即可
(requests | union dependencies | union pageViews | union customMetrics)
| where timestamp > ago(90d)
| where operation_Id == "57b7b55cda794cedb9e016cec430449e"
| extend fetchStart = customDimensions.fetchStart
| project timestamp, itemType, name, valueSum, fetchStart, id, operation_ParentId, operation_Id, customDimensions
| order by timestamp asc
我们于是得到了所有的结果

我们只需要 fetchStart 和 valueSum (也就是 duration) 就可以把整个流程图画出来

脚本资源在1s钟之内就加载完毕了。很明显,瓶颈在于接口的 RTT(Round-Trip Time)太长。抱歉没钱在世界各地部署后端节点。
总结
我自己写到这里觉得这篇文章有炫技或者是多此一举的嫌疑。因为即使没有这套工具。凭借工程师的经验,你也应该大致能猜到问题出在哪。
首先肯定不会是前端资源,一方面在多次访问的场景中浏览器的缓存机制不会让资源加载成为瓶颈;其次前端我使用的是 Azure Static Web App 服务,在 Azure CDN 的加持下即使是首次访问静态资源也不会是问题
至于 SQL 性能,你一定要相信商用的 MySQL 性能绝对比你本地开发环境的 MySQL 性能还要好。对这种体量的应用和查询来说,你的代码想把查询性能变得很差都很难。
所以问题只可能出现在接口的 RTT 上。
但我不认为这个方案无价值可言,对于我个人来说一个切实可行且能够落地的代码会比所谓摘抄自教科书上所谓的业界方案更重要;另一方面我在这个方案上看到了很多种可能性,比如它可以支持更多种类的指标采集,又比如利用 Headless Chrome 自带的开发者工具我们可以洞见更多网站潜在的性能问题,也许者几十万条数据还能够帮助我们预测某时某刻的性能状况。
对比阿里
阿里云有两个工具我们可以拿来对比,一个是阿里云的前端前端性能监控工具

我没法将整个页面截图给你,但是总体看来,统计的信息有
• JS错误信息
• API请求信息
• PV/UV
• 页面性能(首次渲染耗时,完全加载时间)
• 访问的各个维度(地理位置、网络、终端分布)
从上图的左侧子菜单可以看出,对每一类信息它都已经给出了预订制的报告详情。你可以把它理解为对于 Application Insights 数据进行加工后显得对人类更友好的产品。因为 Application Insights 是非常底层存储于表中的数据,你需要自己编写查询语句然后生成报表
另一个和我们功能很像的工具是云拨测,在这个工具内你可以选择测试发起的城市,来看看不同人群对于你网站的性能体验如何。比如我选择了美国和北京

甚至对于每一次访问,我们都能看到它的详细数据,甚至包括我们之前说的 DNS 的情况

如此强大的功能不是我个人开发出的工具能够匹敌的。
但是面对这些无所不能的工具,假设它们能把成千上百个指标准确的呈现在你面前,我想问的是,你真的需要它们吗?或者说,你关心的究竟是什么?
你可能会喜欢:
- 做一个能对标阿里云的前端APM工具(上)
- 性能指标的信仰危机
- React + Redux 性能优化(一):理论篇
- React + Redux 性能优化(二)工具篇: Immutablejs
- Mobx 与 Redux 的性能对比
- 用 100 行代码提升 10 倍的性能
- 仪表盘场景前端优化经验谈
- 让我们再聊聊浏览器资源加载优化
- Javascript高性能动画与页面渲染
做一个能对标阿里云的前端APM工具(下)的更多相关文章
- 做一个能对标阿里云的前端APM工具(上)
APM 全称是 Application Performance Monitor,即性能监控 这篇文章有三个前提: 从产品形态上看这肯定不是一个能够媲美阿里产品的竞品,所以抱歉我碰瓷了.你可以把这里的阿 ...
- 阿里云运维部署工具AppDeploy详细教程
AppDeploy是一个通过SSH实现的命令行工具,可完成应用部署和远程运维管理.当前工具实现为两个版本:普通版(伪代码描述语言)和Python版.Python版使用Python语法规则,可实现您的各 ...
- 阿里云ECS服务器Linux环境下配置php服务器(二)--phpMyAdmin篇
上一篇讲了PHP服务器的基本配置,我们安装了apache,php,还有MySQL,最后还跑通了一个非常简单的php页面,有兴趣的朋友可以看我的这篇博客: 阿里云ECS服务器Linux环境下配置php服 ...
- 一个空行引起的阿里云负载均衡上部署https证书的问题
今天在阿里云上购买了WoSign的https证书,在证书签发后,在控制台下载证书文件,一共有2个文件,一个是.key文件(私钥文件),一个是.pem文件(证书文件). 然后在阿里云负载均衡“证书管理” ...
- 阿里云Logtail 快速诊断工具
当日志采集发生异常时,您可以通过Logtail自助检测工具查看客户端是否存在异常情况,根据工具提示快速定位并解决问题. 说明 本工具目前仅支持Linux系统的服务器. 准备工作 下载检测工具脚本. ...
- 阿里云ECS服务器windows环境下配置redis
一.下载解压redis github下载地址:https://github.com/MSOpenTech/redis/tags 下载的是Redis-x64-3.2.100版本,Redis-x64-3. ...
- 阿里云ECS服务器Linux环境下配置php服务器(一)--基础配置篇
开始安装软件了,我们需要安装的软件有apache,php和MySQL. ps:如果你购买的是北京的服务器,有个安全组需要设置,我全部用的默认设置,暂时还没发现会有什么影响. 首先关闭SELINUX(S ...
- 阿里云Linux(Centos7)下搭建SVN服务器
1,使用yum安装SVN yum -y install subversion 安装完成之后,验证安装结果 svn help 2,新建仓库目录 在/usr/soft目录下面创建一个svn目录,用来作为s ...
- 阿里云服务器 ECS Ubuntu系统下PHP,MYSQL,APACHE2的安装配置
1.系统更新,必须更新,否则有些软件会找不到. apt-get update apt-get upgrade 2.安装mysql sudo apt-get install mysql-server 3 ...
随机推荐
- Web前端初级问题—ajax登录跳转登录实现
当我们的用户进行系统登录时,用户名和密码的验证都是后端验证的.而且,用户登录状态也是要后端设置的,查询数据库后,用户名和密码正确,则在session中存储一个uuid,每个页面需要根据登录状态判断展示 ...
- canvas离屏、旋转效果实践——旋转的雪花
效果展示理论基础--"常见的canvas优化--模糊问题.旋转效果" 用离屏canvas画基础部分 1.封装画线函数 function drawLine(ctx,x1,y1,x2, ...
- java中当static块和构造函数同时出现,顺序是?
静态块先于构造函数执行 class Student { int age; String name; static int count; public Student() { ...
- maven安装和配置阿里云镜像(各种详细配置)
maven安装和详细配置 提示:下面是maven3.6.3版本百度云链接,记住maven3.3以上版本必须安装jdk1.7及以上版本,否则会出错. 链接:https://pan.baidu.com/s ...
- 前端实现导出excel
结果: 将网页上拿到的数据导出成excel文件 实现: HTML代码 <div> <button type="button" onclick="expo ...
- ES 架构及基础 - 1
Elasticsearch 是一款分布式,RESTful 风格的搜索和数据分析引擎,可以从海量的数据中高效的找到相关信息.如 wiki 用 ES 进行全文检索及其高亮,Github 用其检索代码,电商 ...
- OllyDbg---比较、条件跳转指令
比较和条件跳转 CMP 比较两个操作数,相当于SUB指令,但是相减的结果不保存到第一个操作数,而是根据相减的结果来改变零标志位.当两个操作数相等时,零标志位Z置为1. 两个操作数不相等时,零标志位Z被 ...
- 异步任务-springboot
异步任务-springboot 异步:异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作.也就是说无论异步方法执行代码需要多长时间,跟主线程没有任何影响,主线程 ...
- 前端javascript之BOM、DOM操作、事件
BOM与DOM操作 BOM 浏览器对象模型>>>:使用js操作浏览器 DOM 文档对象模型>>>:使用js操作前端页面 window对象 所有浏览器都支持 wind ...
- 几个i的幂的累加公式1^2+2^2+3^2 2~5
1^2+2^2+3^2+--+n^2=n(n+1)(2n+1)/6 1^3+2^3+3^3+...+n^3=(1+2+3+...+n)^2 =[n(n+1)/2]^2 1^4+2^4+3^4+--+n ...