句号-如何设计实用的性能模型与检测系统

前端早早聊

共 9198字,需浏览 19分钟

 · 2021-06-28

前端早早聊大会,前端成长的新起点,与掘金联合举办。加微信 codingdreamer 进大会专属周边群,赢在新的起跑线。


第二十八届|前端 WebGL专场,了解3D/可视化/渲染管线/动画等等的可能性,6-26 全天直播,9 位讲师(贝壳/阿里云/蚂蚁/奇安信/小米/UC/美团等等),点我上车👉 (报名地址):

所有往期都有全程录播,可以购买年票一次性解锁全部

👉更多活动


正文如下

本文是第十八届 - 前端早早聊性能优化专场,也是早早聊第 124 场,来自 阿里 政采云-句号 的分享。

个人介绍

首先做一下自我介绍,我叫陶越,花名句号,19 年加入政采云,目前主要负责商品中心以及政采云性能检测系统。

此次分享的宗旨

本次分享不会着重讲一些非常具体化的一些性能优化的方案,针对不同的性能优化点,业界其实都已经有了比较通用的一些解决方案。本次我要和大家分享的是针对不同的系统,如何设计一套与业务想匹配的性能检测模型。然后希望通过这次分享之后,小伙伴们可以自己动手实现一个属于自己的百策。

看一下本次分享的一个大纲

百策是什么

百策是政采云平台的一个性能检测系统,百策取名自历史人物魏征,因敢于直谏,被称为 “魏百策”。给性能检测平台取名为百策的意义就是希望此系统能像政采云的诤臣一样,为政采云平台提供性能上的指导与帮助。

然后我们来看下百策的是怎么样的。

百策提供了一个入口,输入 URL 后能根据页面的整体性能情况,给出综合的一个评分。最后的得分会根据不同的页面类型有不同的分数计算方式,为什么不同的页面会有不同的分数计算方式这一点我会在第二章中详细描述。

检测结束后,会进入得分详情页面,右边是百策得分详情的整个页面,左边是页面的局部放大图。可以看到在总得分面板的下方有此次评分详细的扣分原因以及改进的具体方案。

然后这是检测结果中的通过项和警告项:

除了扣分情况以外,下面还会有此页面的性能数据看板,方便查看得分走势等数据。

以上介绍的是百策的主要功能,除了性能评分以外,百策还提供了页面录入,定时检测,性能评分榜单等功能。

百策的检测功能实际上是根据合成监控这种方式来实现的。那合成监控是什么?接下来我会聊一下前端性能监控的两种方式:

  • 第一种是合成监控:合成监控就是模拟真实的页面打开场景,通过你设定的一些规格去运行页面,最后提取出的性能数据和指标,合成监控大家最熟悉的应该就是 Chrome 的 Lighthouse。

  • 第二种是用户数据监控:用户数据监控是将线上的真实数据的性能情况进行监控,对用户真实的数据进行清洗加工后,提取出性能数据和指标,此方法需要在页面中注入 SDK 以获取性能数据。

可以看下不同监控方式的具体流程图。

合成监控主要流程包括模拟打开页面,获取性能数据,性能数据审计,最后是性能数据入库。然后用户数据兼容主要是在用户打开页面后,获取性能数据,通过事先埋入的 SDK 进行数据上传,然后发送到后台进行数据审计,最后性能数据入库。

了解了两种监控方式的具体流程之后,我们分别聊一下合成监控和真实用户数据监控的优缺点是什么。

  1. 合成监控首先实现方案比较简单,只需要在后台模拟打开页面即可,不用注入 SDK 获取页面数据,而且合成监控方式可以做到变量调控,可以根据不同的情况模拟不同的硬件环境,并且性能数据比较丰富。缺点也显而易见,不能代表真实用户的性能数据,而且对于需要登录才能打开的页面,会直接跳转到登录页面,所以此监控方式还需要单独实现登录逻辑。而且合成监控的数据样本量一定是没有用户数据监控多。
  2. 然后用户数据监控首先肯定没有合成监控中需要登录的问题,打开页面即可进行性能数据获取,完全真实的真线数据,能够针对性的分析性能问题。但缺点也显而易见,无法模拟不同的硬件环境,由于使用 SDK 方式,会有流量消耗和性能消耗,数据的收集也没有合成监控那么丰富。

那为什么百策采用的是合成监控模式呢?

那要从百策存在的目的说起,百策存在的目的在于提升页面性能,并非监控线上性能数据,百策要针对页面中性能欠缺的地方,提供具体的性能修改指导建议,而且百策需要保证环境和硬件条件一致的情况下对页面做性能比对。

所以总结来说就是我们需要合成监控的所有优点,而且也不 care 合成监控的缺点。

百策的由来

为什么要性能检测呢

我们先来看一张图,该图来源于百度用户体验部的页面留存率曲线图,可以看到用户普遍能接受的页面打开时间都在3 秒以内。可以看到用户留存率和页面打开时间的一个关系趋势。

所以我们进行性能检测的目的就是为了提升用户体验,增加用户留存。如果一个页面的渲染速度非常慢,有 3 到 4 秒的白屏时间,我想大多数人可能以为网站挂了或者很多人就直接就把页面关闭,那么这个网站的用户留存率会比普通网站低很多。下面我收集了几个页面性能优化与留存率关系的案例:

  • Shopzilla 平均页面加载时间从 6 秒加速到 1.2 秒,增加了收入+ 12% 和页面浏览量+ 25%;
  • Mozilla 每年的 Firefox 下载量增加了 6,000 万,使其页面的速度提高了 2.2 秒;
  • 亚马逊和沃尔玛每减少 100 毫秒的打开时间,收入增加 1%;

接下来的 2 章是本次分享的重点内容。

首先我们来看下如何才能搭建百策

在讲如何搭建百策之前,我们先要构造自己的业务模型,要构造自己的业务模型之前就要先分析自己的业务痛点,从业务出发,才能做好百策。那我们先来聊一聊如何分析自己的业务痛点。

分析自己的业务痛点

面向的对象的特点对应的性能指标上的区别

首先需要分析自己的业务主要面向的对象是谁?他们在系统中是来干什么的。举一个例子,就拿我们系统和淘宝进行对比。

首先政府采购面向的对象是政府采购人员,淘宝面向的对象是广大消费者,首先在页面的 PV、UV 上的量级是不一样的,所以业务指标的设定上一定是不同的两套标准,在设计性能指标时,政采云的性能指标可能会略低于淘宝的。其次政府采购人员使用的电脑上的浏览器一般都是低版本 IE 浏览器,所以在浏览器兼容方面进行设计时,百策的检测力度可能会略高于淘宝。

其次政府采购人员一般在 PC 端进行采购,而淘宝消费人群主要集中在手机端,所以在性能分析时,淘宝还需要对一些极端场景,比如弱网场景做一些检测,而针对政采云的性能检测模型,网络环境上的指标就不必太过于关注。最后还可以多收集现有用户的吐槽点进行优化,比如之前就有人吐槽有部分页面出现了横向滚动条,造成页面使用困难。所以我们在检测模型上增加了一条横滚检测的指标。

总结来说,分析业务痛点的诀窍共有以下 3 点:

  1. 分析系统面向的人群特点;
  2. 分析系统面向的人员使用场景特点;
  3. 收集使用人员吐槽点;

那分析完业务痛点之后,我们再来聊一聊不同的业务是怎么检测的?

刚才在第一章中提到了一点,就是不同的页面有不同的分数计算方式,不同的分数计算方式我们称为不同的性能检测模型。那为什么有不同的检测模型呢,我们来看下下面两张图。

第一张是采购人的商品搜索页面,可以看到页面中主要都是图片相关的内容,没有非常复杂的交互,主要以浏览为主。

第二张是供应商发布运费模版的页面,可以看到页面中都是表单元素,而且里面有复杂的一些业务逻辑,随之而来的也有一些复杂的交互逻辑。

从上面两张图可以看到不同页面,检测的重点不同,模型不同,权重不同,所以不能用一套模型搞定所有的页面。这时候检测模型的概念就出来了。政采云总的来说可以分为 2 种检测模型,第一种是前台导购模型,第二种是中台表单模型。

具体业务具体分析,首先聊一下前台导购页面。

前台导购页面的话主要面向的是采购人,主要功能可以分为物品的采购、活动页面的展示等。分析这一类页面的共通点,就是展示为主,并且会伴有大量的图片信息。根据以上业务的分析结果,我从两方面来构建业务的检测模型。传统的页面加载时间往往不能直接反应页面的性能状况,因此百策采用的是渐进式的网页指标来设计的,图中除了DNS 和 TCP 耗时以外,其余时间指标都是渐进式的网页指标。然后我们来一个个分析:

  1. 首先是加载时间方面。无论什么页面,更快的加载速度一定是没错的,这一点我们可以把它定为通用检测项。我们可以定义各种时间来检测页面,可以看到百策在时间上的检测项包含了:DNS 耗时、TCP 耗时、首次内容绘制时间(简称 FCP,指的是第一个有意义的 DOM 渲染,比如图片、文本、SVG 等)、最大内容绘制时间(简称LCP,指的是可视区最大可见元素出现的时间点)、首次可交互时间(简称 TTI,指的是用户可以进行交互的时间,检测的规则是主线程任务不超过 50ms 才算可用)、阻塞总时间(TBT,指的是所有主线程任务花费时间超过 50ms 的时间总和)。

  2. 那讲完通用检测项之后,剩下的检测项就应该围绕着业务特性来。刚才我们分析过政采云前台导购页面的一些通用性之后,把目光聚焦在了图片加载优化上,所以我们会侧重于图片性能的一些检测项,比如说页面上图片加载的体积大小,图片是否使用了 CDN 压缩后缀,图片是否使用懒加载,图片是否使用了 webp 格式,是否有加载错误的图片,png 格式的图片错误地使用压缩后缀反而导致图片变大。

  3. 剩余项的话主要是一些通用性的,并且和当前导购页面有联系的指标,比如说累计位移偏移量(简称 CLS,计算规则是 500ms 内网页元素偏移的分乘以影响分)、静态资源缓存策略、重复请求、横向滚动条。

所以百策的前台导购模型,总分 100 分,时间占比 45 分,图片占比 30 分,其余项占比 25 分。

再回到我们的中台表单页面,中台表单页面主要面向的是我们的供应商和一些采购老师等角色,功能偏向于各种表单配置项,主要是由许多典型的表单页面构建,分析这一类页面的共通点,就是以表单为准,它不像前台页面有那么多的图片展示,但会有很多的页面交互方面的内容。根据以上的业务分析结果,我也从两方面来构建业务的检测模型:

  1. 加载时间方面和前台导购页面基本一致,可能有区别的就是每项的扣分情况。

  2. 那除了加载时间外,剩下的检测项目的具体指标就是侧重于表单优化的,比如说首屏 HTTP 请求、CLS,JS/CSS 压缩情况、重复请求、横滚、DOM 最大深度、DOM 节点数量、页面从开始加载到结束加载后有多少时间是丢帧的(小于60FPS)等。

所以百策的中台表单模型总分 100 分,时间占比 60 分,页面占比 40 分。

接下来我们就讲一下百策实现。

百策是怎么设计的(架构)

百策的架构图介绍

首先我先把我们百策的架构图拿出来给大家看一下,前端只是一个纯展示功能的页面,所以不多描述了。

服务端基于 nestjs (奈斯特)开发,接入了 Sentry,helmet,主要功能是用户系统的监控和保护,node-schedule用于每周定时计算已录入系统中的页面性能,一般在周五凌晨开始跑分,然后周五下午通过 nodemailer 和 ejs 服务发送性能检测邮件。

最主要的检测服务基于 Puppeteer 和 Lighthouse 开发。

以上就是百策的整体的一个架构图,接下来会说一下 Puppeteer 和 Lighthouse 的主要功能以及在百策中的使用。

  • Puppeteer

先来看下 Puppeteer 的官方说明:Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

简单来说就是在 Node 端起一个浏览器,通过 API 控制可以模拟在浏览器操作的大部分功能。Puppeteer 通过DevTools 协议生成一个 Browser 对象,Browser 可以拥有多个 BrowserContext 浏览会话,一个 BrowserContext 也可以拥有多个页面。

“百策”最关键的逻辑就是通过 Puppeteer 在 Node 端起一个浏览器,首先通过 API 打开首页,模拟用户登录,通过同一浏览器不同 Tab 页共享同域名 Session 这一特性,新开 Tab 打开待检测的页面,并在页面关闭前收集数据并入库。

再来聊一下 Lighthouse。

  • Lighthouse

先看下 Lighthouse 的官方说明:Lighthouse 是一个开源的自动化工具,用于改进网络应用的质量。Lighthouse 提供了多种运行方式,包括:内嵌于 Chrome 中、Chrome 插件,Node CLI 方式和 Node Module 方式4种。

可以先看下 Lighthouse 的架构。共分为 4 步:

  • 第一步在页面交互后发起请求调用;
  • 第二步唤起自己的 Gatherers,Gatherers 的主要功能在于数据收集功能,可以将它理解为数据收集器,不同的Gatherer 有自己的数据收集功能,最后将收集到的数据统一提交给 Audit;
  • 第三步唤起 Audit,Audit 的主要功能在于将第二步中收集到的数据按照检测模型分配为通过、失败或者得分情况;
  • 第四步将结果返回给前端。

然后我们再来看下 Lighthouse 和 Puppeteer 结合的方式,共有 2 种。关键点在于保证 Lighthouse 和 Puppeteer 启动时使用同一个端口号即可:

  1. 第一种是先启动 Puppeteer,然后将 Puppeteer 移交给 Lighthouse,具体实现方案是启动 Puppeteer,为Puppeteer 增加一个 targetchanged 的钩子函数,用于在页面关闭前收集数据。可以看到首先是使用 puppeteer.launch 启动 puppeteer,然后移交给 Lighthouse 的时候,Lighthouse 的启用端口号从 browser 中获取。
  2. 第二种是使用 Lighthouse/chrome-launcher 启动 Chrome,然后移交给 Puppeteer。可以看到首先是使用chromeLauncher.launch启动 Chrome,然后通过puppeteer.connect连接到浏览器实例,最后启动Lighthouse。

两种方法只是写法上有区别,实际使用时没有任何区别,百策采用的是方案一。

这个是一个 Demo 代码,这一块主要是启动 Lighthouse,这一块是注册钩子函数,用于页面打开后的性能数据获取,这一块就是通过 Lighthouse 打开页面获取数据。

百策的实现介绍

下面聊一下百策的一个具体实现流程图。

  1. 首先是启动 Puppeteer,创建 Browser 和空白的 Page;
  2. 其次调用 goto 方法打开政采云的首页,填充用户名和密码后,后台模拟点击提交,此时 SESSION 已经保存到Browser 中;
  3. 然后新建一个空白的 Page,通过 Puppeteer 注册一个钩子函数,钩子函数的作用是监听页面各种事件,比如页面打开事件,请求完成事件等,在不同的阶段获取不同的性能数据。举个简单的例子,我要获取 window.performance 中的各种时间指标,首先要必须等待页面加载完成,所以我需要在页面打开前注册一个页面加载完成的钩子函数,等到页面加载完成之后,自动触发此函数,获取数据;
  4. 然后将 Puppeteer 移交给 Lighthouse,打开待检测的页面;
  5. 页面全部加载完成之后,触发了 Gatherers 中的钩子函数,将收集到的数据传递给 Audit;
  6. 根据页面是前台导购页面还是中台表单页面确定模型,按照模型计算得分情况;
  7. 最后就是得分情况入库,并返回得分情况给前端展示。

登录是非必要操作,因为有的页面是不需要登录就能打开的。

中间的红框对应的就是 Lighthouse 的 Gatherers,Gatherers 包含了多个 Gatherer,每个 Gatherer 有自己的收集功能,比如百策就拥有 5 个 Gatherer,这 5 个 Gatherer 的功能分别是:收集 DOM 数据,收集图片数据,收集 Lighthouse 数据,收集网络请求数据和收集 performance 数据。Gatherer 的功能只有收集数据。

最右边的红框对应的就是 Lighthouse 的 Audit,主要用于将 Gatherers 收集到的数据按照性能检测模型定义的评分项进行扣分和梳理,最终将数据入库。每一个检测模型对应的检测指标项就是一个 Audit,每个 Audit 有自己的评分和扣分标准。最终将数据返回前台。

百策的实现的话细节代码可以参考下面这篇文章,感兴趣的小伙伴可以在掘金搜索政采云前端团队公众号。大家可以关注点赞一波。

百策的模型介绍以及百策的模型指标是如何设计的

讲完百策实现之后,在这里给大家看一下我们百策的检测模型的具体指标。还是看一下刚才的性能检测模型图片,以我们的前台导购页面检测模型来说。

在时间维度上,首先是打开页面时的一些耗时分计算,DNS 耗时和 TCP 耗时,我们系统以 100ms 为准,每超过 10ms 扣 1 分,直到所有总分 5 分扣完为止。

接下来是打开页面后时间维度的计算,主要靠 Lighthouse 提供。首次内容绘制时间 1.5 秒为准,每超过 0.5 秒扣 3分,最大内容绘制时间 2 秒为准,其他的指标我就不多描述。

然后再页面维度方面,图片大于 100K 的,每个扣 2 分,未使用 CDN 压缩后缀的,每个扣 1 分,未使用懒加载的,每个扣 1 分,其他的指标后续小伙伴可以等羽雀文字稿出来之后可以细看。

以上这些指标的扣分情况是根据我们平台平均的一个耗时来制定的。只要高于平均耗时一小部分作为满分即可。除了以平均值作为评分情况外,我们还会参考许多业界的一些页面进行对比,比如淘宝首页等,我们在制定前台页面指标时,也会看淘宝网展示的一个具体情况来完善我们的检测模型指标。

那如何构造自己的业务模型呢

构造自己的业务模型其实很简单,可以按照我下面给的四步法原则进行分析。

建议参考页面平均值来,比如说现在系统页面非常卡顿,系统中大部分页面首屏加载时间都在 2 秒到 3 秒之间,那么建议当前测评的具体指标可以将 FCP 时间定为 1.5 秒优秀,2 秒及格,3 秒基本不得分。根据当前指标推动现有页面进行整改。待大部分页面整改到能够通过优秀指标后,继续降低 FCP 检测的标准时间。直到你认为这已经是最高标准为止。

以上主要是根据我们业务分析出的性能检测模型,不同的业务之间检测模型一定有很大的差别。所以只能具体业务具体分析,可以参考四步法:

  1. 分析业务;

  2. 提取通用型的分类;

  3. 选取性能优化方向;

  4. 制定性能优化指标;

建立性能看板

构造完业务模型后,百策还提供了性能看版。

数据看板主要是方便我们查看性能的走势的最好的方法。可以从以下 5 个方面做一个性能走势的分析,时间维度报表,数量维度报表,体积维度报表,复杂度报表以及得分走势情况。

  • 时间维度报表代表性比较强的有加载时间,DNS、TCP 耗时等等。
  • 数量维度报表比如有请求数量,静态资源数量等。
  • 得分走势主要好似性能评分的一个趋势图。

性能评分有了,性能看版也有了,接下来就是要看下性能问题要如何才能解决。

怎么根据检测结果来改善页面性能

性能检测的优化方案有许多,比如加载优化包括按需加载、缓存策略、请求合并等。渲染优化包括了减少 DOM 数量和层级、避免 JS 渲染动画、高频操作节流防抖等。JS 优化包括了异步加载、减少回流和重绘、合并 DOM 操作等。

资源优化包括资源合并、资源压缩、Iconfont 等。上面说的这些只是性能优化方案中的某几个例子。我这边就不扩展开讲了,毕竟今天的主要目标是要向大家分享怎么设计百策这样的性能检测系统。

性能优化方案非常多,百策做的事情就是尽量让开发者使用百策之后能知道页面有什么性能问题,并且知道该怎么改?所以百策文档自然而然就出现了。

百策文档主要功能是收录业界性能优化方案,建立站点,供开发者根据指导修改代码优化性能。举个2个简单例子。比如说图片懒加载,百策文档会对懒加载的概念和原理解释一番供开发者理解,那对于如何优化也在文档中写明了不同框架的不同优化建议。

再说比如未开启 Gzip,针对 Node 端和 Tomcat 启用的方案也都会在文档中写明,保证即使是刚入职的小伙伴也能根据指导进行改进优化。

再聊一下百策总榜。百策总榜是百策中国呢页面收录的所有页面做一个页面评分并进行排行的功能。主要通过 node-schedule 定时跑评分,一般是一周一次。

以上就是百策实现相关的具体内容。最后在讲一下百策在公司是如何与其他基建打通的?

百策是怎么与公司的其他基建打通

之前在早早聊的页面搭建篇介绍过政采云的鲁班系统,简单来说鲁班系统就是政采云的页面搭建系统。

那百策是如何实现与鲁班系统的连接的呢?主要在两个方面:

  1. 在鲁班页面搭建完成的时候,提供一个检测按钮,调用百策性能评分接口,生成检测数据;

  2. 在鲁班的新页面上线的时候,会自动调用百策录入接口,新增的页面会被录入到百策系统中。

除了鲁班系统之外,还与 CI/CD 进行打通,云长是我们的实现云端构建时调用检测接口,对于不符合优秀分数的页面,在云端构建时阻止发布,以保证页面性能。

最后讲一下我们的浑仪,数据埋点系统。对接方式也比较简单,在百策的定时任务检测时,会调用浑仪的获取 PV、UV 接口获取本周页面的使用情况。

推荐一本书

最后推荐一本书,《代码整洁之道》,人民邮电出版社的。

政采云介绍、招聘

最后再打一波广告,政采云前端大量招人。再简单介绍下我们团队,是一个富有激情和创造力的团队,团队氛围良好,平时除了日常业务外,还包括物料、工程化、搭建、性能、数据分析等等方面的技术建设,总有一款适合你的兴趣。明年还有大量 HC,只需要你动动手,发送简历到 ZooTeam@cai-inc.com 邮箱即可。现至少还缺2位技术专家、8位资深开发工程师、8位高级开发工程师,欢迎大家猛砸简历。


别忘了 6-26(本周六) 的第二十八届|前端 WebGL专场,了解3D/可视化/渲染管线/动画等等的可能性,6-26 全天直播,9 位讲师(贝壳/阿里云/蚂蚁/奇安信/小米/UC/美团等等),点我上车👉 (报名地址):

所有往期都有全程录播,可以购买年票一次性解锁全部

👉更多活动


别忘了给文章点赞


浏览 36
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报