龙空技术网

Alibaba.com买家性能优化经验阶段性总结

阿里开发者 378

前言:

此时咱们对“javaweb个人总结”可能比较看重,兄弟们都想要分析一些“javaweb个人总结”的相关内容。那么小编也在网上搜集了一些有关“javaweb个人总结””的相关内容,希望兄弟们能喜欢,各位老铁们一起来学习一下吧!

简介: 结合业务国际化的背景,来讲述如何在复杂网络场景下的性能优化。

背景为什么要做性能优化

对绝大多数网站来说,从宏观视角上看主要有两个因素影响最终的网站业务效益:

用户的整体规模用户在网站内的转化率

业务效益 = 用户规模 * 转化率

所以为了提升业务效益,需要提升用户规模以及转化率。

用户规模

用户主要由新用户和老用户组成,新老用户也有各自的流量组成,但无论新老用户进入网站,都要经过从用户的客户端也就是站外落地到我们网站也就是站内这个过程。

尤其我们 Alibaba.com 是一个全球化的网站,从网络设施发达的欧美到欠发达的第三世界国家,都有我们的用户通过电脑或者手机等设备访问我们的网站。

而复杂网络状况以及技术现状,会导致网页加载的缓慢,用户很可能无法忍受漫长的白屏等待而选择关闭网站,造成用户流失。

很多案例也说明了加载性能对用户规模的影响:

At the BBC we’ve noticed that, for every additional second a page takes to load, 10 per cent of users leave.The result of rebuilding our pages for performance led to a 40 percent decrease in Pinner wait time, a 15 percent increase in SEO traffic and a 15 percent increase in conversion rate to signup.

所以网站的加载性能会直接影响到最终落地站内的用户规模。

转化率

影响转化率的因素非常多:网站提供的价值、用户的意愿度以及页面的用户体验都是重要的影响因素。而网站的交互性能,则是用户体验的一大影响因素。

如果一个网站打开过程中,页面元素各种抖动、滚动页面时卡顿掉帧,或者鼠标点击一个按钮时需要一秒钟才能响应用户的交互,都会极大地损害用户体验,直接影响用户的点击率和蹦失率,最终对转化率造成影响。

所以我们要做性能优化。

为什么总是做性能优化

每隔一段时间就要重新提性能优化,为什么:

性能腐化:随着业务的发展和功能迭代,越来越多的功能会逐步添加到现有的业务中,功能复杂度的增加也会导致性能现状逐步恶化指标的迭代:随着技术的发展以及对用户极致体验的追求,会有更加准确和贴合用户体感的性能评价指标被提出和使用,老的性能评价指标指导下的优化结果在新的指标下并不一定适用

由于这些原因,我们现有的页面性能并不是很理想。

目标

我们将性能优化的目标定为买家前台核心浏览链路页面满足 Core Web Vitials 衡量指标下的 Good Url 标准。

什么是 Core Web Vitials

Core Web Vitials(后面简称为 cwv) 是 Google 为了衡量页面性能而提出的有多个指标组成的一套页面体验衡量标准,目前主要包含三个指标:LCP, FID, CLS。

LCP: 最大内容绘制,测量加载性能。FID: 首次输入延迟,测量交互性能。CLS: 累计布局偏移,测量视觉稳定性。为什么采用 Core Web Vitials 衡量指标

从上面对 cwv 的解释可以看到,核心指标从页面加载速度、用户输入性能以及页面的视觉稳定性三个方向衡量了一个好的页面性能应该具备的特点,这三个指标也是用户体验的核心要素。 相较于我们以前的衡量方式 hero element time ,即由每个业务线的开发自己定义一个关键页面元素,以它的渲染完成时间来衡量页面的性能,cwv 的指标明显要更加全面,而且更加通用,不易作弊且经受了整个行业的考验。

下面是 Google 官方对于真实网站在 cwv 指标优化下的性能提升情况的统计:

Why page performance matters Studies show that better Core Web Vitals improves user engagement and business metrics. For example:

When a site meets the Core Web Vitals thresholds, research showed that users were 24% less likely to abandon page load.With each 100ms reduction in Largest Contentful Paint (LCP), web conversion rate for Farfetch increased by 1.3%.Reducing Cumulative Layout Shift (CLS) by 0.2 led Yahoo! JAPAN to a 15% increase in page views per session, 13% longer session durations, and a 1.72 percentage point decrease in bounce rate.Netzwelt improved Core Web Vitals and saw advertising revenues increase by 18% and page views by 27%.Reducing CLS from 1.65 to 0 significantly uplifted domain rankings globally for redBus.

可以看到无论是 LCP,FID 还是 CLS ,他们的提升都能实实在在的带来业务的提升,这也是我们要做性能优化的原因以及选择 cwv 作为衡量指标的原因。

更多选择 cwv 作为衡量指标的原因,可以参考:

Why Google chose Core Web Vitals as the new page experience ranking factor全球化的前端性能度量

所以我们将性能的衡量指标定为 Core Web Vitials,并将目标定为满足 Good Url 标准,即:

LCP < 2500msFID < 100msCLS < 0.1

优化方法

性能优化是一个老生常谈的课题,网上有很多现成的方案和方法。当我们直接照搬这些方案或方法时,可能并不一定能快速达到我们的目标。

比如著名的雅虎军规里面说:静态资源尽量分散在多个域名下,以提高浏览器并发请求的数量。但随着技术的发展 HTTP2 的普及,这条方案已经并不适用了。又比如有文章说 js 里面的数组遍历方法 for 比 forEach 要快很多,所以为了更好的性能我们要用 for 来代替 forEach,你花了几天时间把所有 for 改成了 forEach 结果 cwv 指标根本没有任何变化。

所以我们要做性能优化,不能单纯的照搬别人的方案,而是要掌握性能优化的方法,正所谓理论指导实践。对于性能优化来说,方法就是:度量、分析和验证。

度量

如果我们不能衡量页面现状,那么优化也就无从谈起。

所以性能优化的首要事情就是要有度量页面的性能现状的方案,为后面的分析和优化提供数据支持。

前面提到我们选择 cwv 作为我们的性能衡量指标,Google 提供了很多 cwv 的检测方式,包括 PageSpeed Insights、Chrome 开发者工具、搜索控制台、web.dev 测量工具等测试工具和平台。

但它们都有一个问题,不能够实时检测线上实际用户的总体统计值,要么是只能本地单次通过类似 PSI(PageSpeed Insights)的测试来看单次评估结果,要么是类似 Google Search Console 这样只能在滞后一段时间以后才能看到大量用户的实际统计值。

而实时的性能数据对我们非常重要,如果没有实时数据,那么会有一下问题:

无法快速验证实验方案,每上一个方案等两周再看效果,这效率难以接受对于一些大的改造,如果造成了性能的严重下跌,却没有实时数据的反馈,两周后再看数据时可能已经对业务造成了很大的损失

所以我们必须有一套实时观测性能数据的方案,来指导我们优化的策略或者优化方向是否正确。

最终我们选择 web-vitals来获取 cwv 的值,并在 ICBU 统一性能监控脚本 big-brother 中添加了相应的打点来上报每个用户的性能数据并建立了相应的性能监控和报表来实时观测页面的性能数据,详细可以参考:Google Core Web-Vitals 统计&监控。

PS:现在可以直接接入 agado来快速获取更加详细的性能数据。

分析

结合上一步获取的性能数据,我们可以系统性的分析当前每一个页面的性能现状。知道它现在到底慢不慢,为什么慢,具体哪里慢,这样的话我们也可以针对性的进行优化。

拿一个典型的前后端分离的页面来看,LCP 的组成部分如下:

可以看到,从用户打开浏览器到页面的 LCP 出现需要经过:建联、后端响应,HTML 传输下载,前端资源下载再到最后的解析渲染,链路非常长,导致最终的 LCP 往往离 2500ms 相去甚远。

如何减少 LCP 的时间,不考虑技术细节的情况下我们不难想到,就是缩短每个耗时组成或者尽可能让他们并行,这也就是我们优化 LCP 的核心宗旨:能减少的减少,不能减少的并行

从 LCP 的组成上来看,其中重定向、DNS 解析以及建联和网络传输的时间主要受三方或者用户自身的网络状况限制,我们能做的并不多。

所以核心的优化方向应该聚焦在我们能控制的网络耗时以外的地方,即:

LCP 的时间线组成排布优化:即在现有的 LCP 时间线中,哪些可以去掉,哪些可以并行;LCP 的时间线组成中每一个步骤本身的耗时优化:即除了网络耗时以外,后端 RT 以及前端资源下载解析执行时间的优化;

对这两个方向的优化我们分别通过:渲染架构优化和关键渲染路径优化来进行分析优化,对于后端 RT 的优化本文暂不涉及。

渲染架构上的优化

从宏观视角上来看,渲染架构的选择是非常重要的,合理的架构选择可以提高系统的性能下限,为后续进一步优化打下基础。

按照 LCP 优化的核心宗旨:能减少的减少,不能减少的并行。从前面 LCP 构成图上不难看出:

传统的页面渲染是不依赖 js 加载的,也就是说这部分时间是有可能省掉的前端资源的加载和后端响应两个大的耗时组成之间是串行的关系,有没有可能让它们并行

这两个优化方向对应了我们渲染架构上的优化方案:同构改造以及流式渲染。

同构改造

渲染架构下性价比最高的优化就是同构改造,在有基建支持的情况下可以以较少的人力投入获取有确定性的比较大的性能提升,一般来说,同构改造可以带来 500~800ms 的性能提升。

前面提到,我们现在绝大部分业务都是前后端分离的架构。这种架构的优势是降低了前后端沟通以及发布维护的成本,两端可以并行开发独立维护自己的代码库,稳定性也更高。但这种架构的问题是,由于前后端分离了,后端输出的 HTML 中只有骨架而没有内容,到了前端需要再进行一次渲染,这次前端渲染又依赖 js 的下载以及首屏数据的获取,导致渲染链路变长。

能不能把这次额外的渲染的时间省掉呢?答案是可以的,同构直出就是为了解决这个问题。同样是前后端分离的架构,可以在不损失开发效率以及合作效率的情况下,通过一套 js 代码同时跑在前端和后端来实现页面的直出。

这样就可以省去前端额外的 js 下载以及解析执行渲染的时间,节省下来的时间一般是 500~800ms ,但它的代价就是需要额外维护一个同构服务。

同构服务的话,现在主要有通用同构服务 silkworm-engine(内部自建服务),店铺自建的同构服务,以及营销导购的接入集团天马平台所提供的同构服务。对于一般业务来说,对接 silkworm-engine 就可以了,对接本身成本也不高。

流式渲染

早在 2010 年,Facebook 的工程师就提出了 bigpipe 的页面渲染方案。通过将一个大的页面划分为多个 pagelet 来将渐进式的完成页面的渲染,核心是为了解决一次性渲染一个大的页面后端耗时过长的问题。

这个方案思路非常超前,但有一个缺点就是侵入性较大,以我们现有的技术架构下来说不太可能做这样的改造。 但它背后的原理即:http1.1分块传输编码的特性,可以指导我们来进行成本更低的优化,也就是流式渲染,将后端一次性的业务处理 vm 模板渲染并返回分为两步:

先返回是不依赖任何业务逻辑的 HTML 部分,浏览器拿到后可以先开始进行静态资源的下载在返回第一段后,同步的去做业务逻辑处理,比如商品数据请求计算等,然后渲染 vm 并返回 HTML 剩余的 部分

可以看到在流式渲染的方案下,蓝框中 的下载解析以及首屏 css 等资源的下载和后端的取数计算并行了。

那么我们就可以节省 Min(前端首屏资源下载时间,后端 RT) 的时间,一般情况下可以有 300~500ms 左右的优化,优化后的时间线如下:

流式渲染的对接也有了工程化的方案:

Java 应用参考 流式渲染- Java 端接入文档来进行对接NodeJs 下的 Egg 应用可以参考:Spark:五分钟接入流式渲染

渲染架构总结

通过同构改造和流式渲染两个渲染架构的上优化,一般情况下都能有 1s 以上的提升。而且不挑业务场景,只要按部就班的做,几乎所有页面都可以进行这两项改造并获得肉眼可见的增益。

同时除非做了其他渲染架构上的优化,一般情况下这 1s 以上的提升不会随着页面所在项目的功能迭代而腐化,确保了性能下限。

点击查看原文,获取更多福利!

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

标签: #javaweb个人总结 #css世界下载