美国的创智赢家(Shark Tank),英国的龙穴之创业投资(Dragons’ Den),以及德国的“Die Hohle der Lowen (DHDL)”等电视节目为年轻的初创公司提供了一个在海量观众面前向商业巨头展现自己产品的机会。然而这些初创公司的主要收益通常并不在于评委提供的战略性投资,毕竟只有很少数交易最终能够完成,而在于通过电视节目获得的关注:电视上出现几分钟的画面通常就可以为网站吸引成百上千的新访客,借此可以有效提升每周、每月,甚至更长时间内的网站流量。然而前提是,网站必须要能承受一开始的负载尖峰不能掉链子……
1,仅可用性还不够—延迟更关键!
网店们通常会发现自己处于一种非常尴尬的境地,因为他们不仅仅是一些消遣性的项目(例如博客),而是通常需要由创始人背负大量投资,并且必须想方设法盈利。对企业来说,最糟糕的情况莫过于服务器超载导致无法处理用户请求,甚至整个网站彻底崩溃。这种情况其实比你想象得更常见:当季 DHDL 节目中露脸的所有网店中,约有半数因为上电视后不堪重负而崩溃。而能继续保持在线也只是走完了万里长征一半的路程,因为用户满意度直接决定了转化率,也就是说,用户满意度直接决定了最终能获得的销售额。
来源: http://infographicjournal.com/how-page-load-time-can-impact-conversions/
针对网页加载时间对客户满意度和转化率的影响已经有太多研究,这足以证明这些因素的重要性。例如Aberdeen Group 发现延迟每增加1 秒会导致页面访问量减少11%,转化率降低7%。就算你去问谷歌或者亚马逊,他们的结论也是相同的。
2,如何给网站提速
在给初创公司 Thinks 开发网店(该公司参加了 9 月 6 日的 DHDL 节目)的过程中,我们遇到了一个挑战:要求所开发的网站能在顺利迎接成千上万访客的同时实现不超过 1 秒的加载速度,这对我们而言是一个巨大的挑战。从这个项目的实施,以及在数据库和 Web 性能领域多年的研究成果中,我们获得了很多宝贵的经验。
影响 Web 应用程序页面加载速度最主要的因素有三个,如下图所示。
- 后端处理(Backend):网站服务器需要花时间从数据库载入数据并生成网页。
- 网络延迟(Network latency):每个请求需要花时间从客户端抵达服务器并再次返回客户端(请求延迟)。考虑到完整加载一个网站平均需要发出超过 100 个请求,延迟问题变得更严峻了。
- 前端处理(Frontend):前端设备渲染网页也需要时间。
为了给网店提速,需要逐个消除这些性能瓶颈。
3,前端性能
影响前端性能最重要的因素在于关键呈现路径( Critical Rendering Path,CRP )。这个概念描述了浏览器将网页呈现给用户的 5 个必要步骤,如下图所示。
关键呈现路径所涉及的步骤
- DOM:浏览器在解析 HTML 时,会以递增的方式为 HTML 标记生成一种名为文档对象模型(DOM)的树状模型,该模型描述了网页中包含的内容。
- CSSOM:浏览器收到所有 CSS 后,会对其中包含的标记和和类生成一种名为 CSS 对象模型的树状模型,并将样式信息附加在树的节点上。这个树描述了网页中所包含内容需要应用的样式。
- 呈现树(Render Tree):通过将 DOM 与 CSSOM 结合在一起,浏览器可以构造出呈现树,其中包含了页面内容以及所要应用的样式信息。
- 布局(Layout):布局这一步中需要计算网页内容在屏幕上的实际位置和大小。
- 绘制(Paint):最后一步将使用布局信息在屏幕上绘制像素。
上述每个步骤单独看都相当简单,但是不同步骤之间的依赖性使得事情变得复杂,并会对性能产生影响。DOM 和 CSSOM 的构造通常会对性能产生最大影响。
下图展示了一个关键呈现路径,箭头所指内容为需要花时间等待的依赖项。
关键呈现路径中重要的依赖项
在加载 CSS 并构造完整 CSSOM 之前,客户端上什么都不会显示。因此 CSS 也被称之为“呈现”的拦路虎。
JavaScript(JS)的情况更糟,因为无论 DOM 或 CSSOM 都可被 JavaScript 所访问并更改。这意味着一旦在 HTML 中发现 Script 标记,DOM 的构造过程将暂停,等待从服务器请求脚本。在脚本加载完之后,还需要等待取回所有 CSS 并完成 CSSOM 的构造,随后才能继续执行。例如在下面的例子中,当 CSSOM 构造完成并且 JS 执行完毕后,终于可以访问并修改 DOM 和 CSSOM 了。DOM 的构造过程直到此时才能继续处理,并将网页显示在客户端上。因此 JavaScript 也被叫做“解析”的拦路虎。
Example of JavaScript accessing CSSOM and changing DOM: <script> ... var old = elem.style.width; elem.style.width = "50px"; document.write("alter DOM"); ... </script>
JS 造成的麻烦远不止如此。例如 jQuery 插件可以访问计算完成后的 HTML 元素布局信息,随后开始反复修改 CSSOM,直到就所需布局达成共识。因此浏览器必须反复执行 JS,反复构造呈现树和布局,这一过程中用户只能看到一片惨白的屏幕。
为了对 CRP 进行优化,需要考虑三个基本概念:
- 减少关键资源的数量:关键资源是指页面首次渲染所必需的内容(HTML、CSS、JS 文件)。通过对渲染无需滚动情况下网页上所呈现内容(也叫做首屏(Above the fold))需要的 CSS 和 JS 进行内联引用(Inlining),可大幅减少此类资源的数量。其余 JS 和 CSS 可异步加载。无法异步加载的文件可以合并(Concatenated)为一个文件。
- 字节数最小化:通过对 CSS、JS 以及图片进行Minifying(缩减)和Compressing(压缩),可大幅缩减首屏内容所需加载的字节数。
- 缩短 CRP 长度:CRP 长度是指为了获取所有关键资源,需要与服务器进行连续不断往返(Roundtrip)的次数最大值。为了缩短该长度,可减少关键资源的数量,并将其大小减至最低(大文件的获取需要多次往返)。为了进一步缩短,还可在 HTML 中将 CSS“置顶”,并将JS“置底”,因为 JS 的执行会阻止 CSS 的获取,并影响到 CSSOM 和 DOM 的构建。
此外浏览器缓存是一种始终值得考虑使用的非常有效的做法。这种方法适合用于上述三种类型内容的优化,因为在将资源缓存后,就无需像第一次访问那样从服务器加载。
CRP 优化是一个非常复杂的话题,尤其是内联、合并,以及异步加载等措施会彻底毁掉代码的可读性。好在目前有很多实用的工具可以帮助我们进行优化,可以考虑将其集成到自己的构建和部署流程中。下面这几个工具绝对值得一试…
- 剖析: GTmetrix 可衡量网页加载速度, Webpagetest 可对资源进行剖析,谷歌的 PageSpeed Insights 可提供建议告诉你如何针对自己的网站优化 CRP。
- 内联和优化: Critical 可自动对首屏 CSS 进行内联,并让其余内容实现异步加载, processhtml 可对资源进行合并, PostCSS 可对 CSS 进一步优化。
- 缩减和压缩:我们可以使用 tiny png 进行图像压缩,使用 UglifyJs 和 cssmin 进行缩减,并使用 Google Closure 进行 JS 优化。
在这些工具的帮助下,只须少量工作即可打造出前端性能更出色的网站。访客首次访问 Thinks 网店的页面加载速度测试结果如下:
Google PageSpeed 对 thinks.com 网站的评测结果
有趣的是,PageSpeed Insights 中检测到唯一存在问题的地方竟在于 Google Analytics 脚本的缓存寿命过短。所以谷歌基本上就是在抱怨自家的问题咯。
从加拿大(GTmetrix)访问位于法兰克福的服务器时的首次页面加载速度
4,网络性能
网络延迟是网页加载速度最大的影响因素,同时也是最难优化的。但在实际进行优化前先来看看浏览器首次请求分解后的步骤:
在浏览器中输入 https://www.thinks.com/ 并按下回车后,浏览器首先通过DNS 查询解析该域名对应的 IP 地址。访问每个域名都需要进行这样的查询。
在获得 IP 地址后,浏览器发起一个到服务器的TCP 连接。TCP 握手需要 2 次往返(1 次可使用 TCP Fast Open )。对于安全的SSL 连接,TLS 握手需要额外的 2 次往返(1 次可使用 TLS False Start 或 Session Resumption )。
初始连接完成后,浏览器发出实际请求并等待返回的数据。获得首个字节所需的时间主要取决于客户端和服务器之间的距离,其中还包含服务器呈现网页(包括会话查询、数据库查询、模板呈现等环节)所需的时间。
最后一步需要下载资源(本例中为 HTML)这一过程需要多次往返。尤其是新连接通常需要更多往返,因为初始拥塞窗口通常很小。这意味着 TCP 并不能在一开始就全面使用所有可用带宽,而是会随着时间流逝逐渐增加带宽用量(可参阅 TCP 拥塞控制)。具体速度受制于启动速度缓慢的算法,这种情况下会让每个往返的拥塞窗口内片段数量翻倍,直到数据包真正开始丢失。在移动和 Wifi 网络中,因为这种情况导致的数据包丢失会对性能产生极大影响。
另外还要注意:在使用 HTTP/1.1 的情况下,最多只能创建6 个并发连接(如果浏览器依然沿袭了最初的标准,则最多只能创建 2 个连接)。因此最多只能并行请求 6 个资源。
为了更直观地了解网络性能会对页面加载速度产生多大影响, httparchive 提供了大量统计数据。例如平均来说,每个网站需要用超过 100 个请求才能加载大约 2.5MB 的数据。
来源: http://httparchive.org/interesting.php#reqTotal
也就是说,网站需要用大量小请求加载数量众多的资源,但网络带宽不是总在增加吗?最终可以通过宽带提速等措施解决这一问题对吧?未必…
来自《 High Performance Browser Networking 》,作者 Ilya Grigorik
实际上带宽超过 5Mbps 后将无法继续对网页加载速度产生任何改善。但是降低每个请求的延迟可以大幅加快网页加载速度。这意味着带宽翻倍后加载时间依然不会有变化,但延迟减半可以让网页加载速度提高一倍。
既然延迟是网络性能的决定性因素,我们能做些什么?
- 持久连接是必须的。如果服务器每次完成一个请求之后就关闭连接,浏览器必须周而复始地重新握手并再次建立 TCP 连接,没什么比这更糟糕的了。
- 尽可能避免重定向,重定向会大幅降低页面初始加载速度。例如请尽量链接至完成 URL(例如链接至 www.thinks.com 而非 thinks.com)。
- 可行的情况下使用HTTP/2。该标准可通过服务器推送通过一个请求传输多个资源,并可通过页头压缩降低请求和回应的数据大小,同时可通过 ** 管道化(Pipelining)和多路复用(Multiplexing)** 借助一个连接发送任意数量的并行请求。例如在使用服务器推送的情况下,服务器可以在发送 HTML 的同时,无需等待实际发出请求,直接将网页所需的 CSS 和 JS 发送给客户端。
- 为静态资源(CSS、JS、徽标等图片)设置明确的缓存标头。借此可以告诉浏览器将这些资源缓存多久,何时重新验证。缓存机制可大幅减少往返次数以及需要下载的字节数。如果未设置明确的标头,浏览器将会进行启发式(Heuristic)缓存,虽然算是权宜之计,但这总归并非最优化的做法。
- 使用内容交付网络(CDN)缓存图片、CSS、JS 和 HTML。这种分布式缓存网络可以大幅拉近用户与资源之间的距离,实现更快速的资源交付。同时这种技术也可以加快初始连接速度,因为此时将会与距离最近的 CDN 节点进行 TCP 和 TLS 握手,同时这些节点会与网站后端建立快速持久的连接。
- 考虑构建单页应用,其中只包含小体积的初始页面,并通过异步方式加载其余内容。为此可以使用可缓存的 HTML 模板,通过小请求加载动态数据,并只在导航过程中对页面中的部分区域进行更新。
简而言之,网络延迟方面有一些必做,以及绝对不能做的事,但总的来说,主要局限因素依然在于往返的次数以及物理网络的延迟。破解这一局限唯一有效的方式是拉近数据和客户的距离。先进的 Web 缓存技术就是用来做这种事的,但这种技术只能用于静态资源。
对于 Thinks,我们完全遵照上述原则使用了 Fastly CDN 以及更激进的浏览器缓存机制,甚至动态数据也使用了一种新颖的 Bloom Filter 算法确保缓存数据的一致性。
重复对 www.thinks.com 进行加载测试可了解浏览器缓存的覆盖率
反复进行页面加载测试的过程中,唯一未能从浏览器缓存完成的请求(见上图)是两个对谷歌分析 API 进行的异步调用,初始 HTML 的请求则是从 CDN 获取的。因此在反复进行的测试中,页面加载速度有了显著提高。
5,后端性能
在后端性能方面,我们需要同时考虑延迟和吞吐率。为了实现低延迟,我们需要将服务器的处理工作所需时间降至最低。为了实现更高吞吐率并应对负载尖峰,我们需要采取一种可以横向缩放的架构。虽然不准备深入介绍太多细节,但设计方面对性能产生的影响是极为巨大的,需要重点关注的组件和属性包括:
可缩放后端栈包含的组件:负载均衡器、无状态应用程序服务器、分布式数据库
首先需要负载均衡(例如 Amazon ELB 或 DNS 负载均衡),借此将传入的请求分配至多台应用程序服务器中的一台。此外还可以实施自动缩放以便在需要时添加额外的应用程序服务器,并通过故障转移机制替换故障服务器,将请求重新路由至正常运转的服务器。
为将协调的次数降至最低,应用程序服务器应当维持最小化的共享状态,并可使用无状态会话处理机制实现更自由的负载均衡。此外服务器的代码和 IO 应尽可能高效,借此即可将服务器处理时间降至最低。
数据库也需要能应对尖峰期的负载,并尽量将处理工作所需的时间降至最低。与此同时,数据库需要具备建模和数据查询需求所需的能力。市面上有大量可缩放的数据库(尤其是 NoSQL 数据库),每种产品都各有利弊。更多详情可参阅我们有关该话题的调查和决策指南: NoSQL 数据库:调查和决策指南。
Thinks 的网店基于 Baqend 构建,使用了下列后端栈:
Baqend 的后端栈:MongoDB 充当的主数据库、无状态应用程序服务器、HTTP 缓存体系,以及适用于 Web 前端的 REST 和 JS SDK
Thinks 使用MongoDB作为主数据库。为了实现会在短时间内过期的 Bloom 筛选器(用于浏览器缓存),我们出于更高写入吞吐率的考虑使用了Redis。无状态应用程序服务器( Orestes Servers )提供了用于访问后端功能(文件托管、数据存储、实时查询、推送通知、访问控制等)的接口,并由该服务器负责处理动态数据的缓存连贯性。这些服务器可通过充当负载均衡器的CDN发起请求。网站前端使用了一种基于REST API的JS SDK访问后端,后端可自动利用完整的HTTP 缓存体系对请求进行加速,并确保缓存数据处于最新状态。
6,负载测试
为了对 Thinks 网店面对高负载情况的表现进行测试,我们使用位于法兰克福的两个 t2.medium AWS 实例作为应用程序服务器进行了负载测试。MongoDB 运行在两个 t2.large 实例上。我们的负载测试使用 20 台 IBM SoftLayer 计算机运行 JMeter ,借此模拟200000 用户在15 分钟内访问该网站的负载。其中 20% 的用户(40000 个)被配置为额外执行支付操作。
该网店的负载测试环境
测试发现支付系统方面存在几个瓶颈,例如我们必须从原本对库存进行乐观更新(通过 findAndModify 实现)的做法改为使用 MongoDB 的部分更新操作( inc )。但在这之后服务器面对负载表现非常出色,实现了平均 5ms 的请求延迟。
JMeter 负载测试结果:12 分钟内 680 万个请求,平均延迟 5ms
所有负载测试总共生成了大约1 千万个请求并传输了460GB 数据,CDN 的缓存命中率高达 99.8%。
负载测试之后的仪表盘概述信息
7,总结
简而言之,良好的用户体验需要从三方面来实现:前端、网络,以及后端性能。
前端性能在我们看来是最容易实现的,因为市面上已经有很多现成的工具以及各种最佳实践,照做很容易就能搞定。但依然有很多网站没有参照这些最佳实践,甚至完全没有对前端进行任何优化。
网络性能是页面加载速度的最大影响因素,同时也是最难优化的。缓存和 CDN 是最有效的优化方法,但需要注意到,这些机制只能对静态内容进行优化。
后端性能主要取决于单台服务器的性能以及分布式环境的规模。横向扩展非常难以实现,因此从一开始就要妥善考虑。很多项目将缩放能力和性能放在最后考虑,随着业务的增长最终将遇到非常棘手的问题。
8,推荐的资料和工具
围绕 Web 性能和可缩放系统的设计,目前有很多不错的图书。Ilya Grigorik 撰写的《 High Performance Browser Networking 》一书几乎涉及了有关网络和浏览器性能的方方面面,此外本书还提供了一个持续更新,可免费在线阅读的版本!Martin Kleppmann 撰写的《 Designing Data-Intensive Applications 》虽然目前尚处于早期发布阶段,但已经成为该领域最棒的图书。其中谈及了大量可缩放后端系统内部的技术基本知识,并包含很多细节介绍。Lara Callender Hogan 撰写的《 Designing for Performance 》谈到了如何构建速度快,可提供出色用户体验的网站,并提供了大量最佳实践。
此外还有大量在线指南、教程和工具可供借鉴。从面向新手的 Udacity 课程网站性能优化到谷歌的开发者性能指南,再到诸如 Google PageSpeed Insights 、 GTmetrix 以及 WebPageTest 等分析工具,都能为我们提供巨大的帮助。
9,Web 性能领域的最新进展
9.1,移动页面加速
谷歌正在通过 PageSpeed Insights 、开发者指南等有关Web 性能的项目帮助大家提高对Web 性能的重视,甚至将网页加载速度作为该公司页面排名的一个重要依据。
谷歌搜索在改善页面加载速度和用户体验方面的最新项目名为移动页面加速( AMP)。该项目意在让新闻文章、产品页面,以及其他搜索内容能通过谷歌搜索结果立刻呈现。为此必须以 AMP 的方式构建这些页面。
AMP 页面范例
AMP 主要做了两件事:
- 使用 AMP 方式构建的网站使用了一种精简(Stripped-down)版本的 HTML,并使用 JS loader 实现快速呈现,尽可能以异步方式加载更多的资源。
- 谷歌会将这些网站缓存在 Google CDN 中,并通过 HTTP/2 交付。
第一件事最为关键,AMP 会通过某种方式对 HTML、JS 和 CSS 内容进行限制,使得通过这种方式构建的页面可以获得最优化的关键呈现路径,并能被谷歌爬虫更轻松地爬网检索。AMP 会强制实施多种限制,例如所有CSS 必须是内联的,所有JS 必须是异步的,页面上包含的一切内容必须为固定大小(这是为了避免“重绘”)。虽然就算无需这些限制,按照上文提到的Web 性能最佳实践也可以实现相同结果,但AMP 也许是一种更好的做法,就算一些很简单的网站也可以使用。
第二件事意味着谷歌会在对你的网站进行爬网检索的同时将内容缓存在Google CDN 中,借此实现更快速的交付。当爬网程序再次索引你的网站时,缓存的网站内容会被更新。该CDN 还会遵守服务器设置的静态TTL,但与此同时至少会进行微缓存(Micro-caching):认为资源在至少一分钟之内是新鲜的,并在收到用户请求后在后台对资源进行更新。这样的做法使得AMP 最适合网站以静态内容为主的用例,例如以人工方式进行内容编辑的新闻网站或其他用于出版发布用途的网站。
9.2,Progressive Web Apps
另一种方法(同样由谷歌提出)是 Progressive Web Apps (PWA)。该方式意在浏览器中使用服务工作进程(Service worker)对网站中的静态部分创建缓存。通过这种方式,重新查看网页时就可以立即加载缓存的内容,并可脱机使用。但网站上的动态内容依然需要从服务器加载。
应用外壳(App shell)(单页应用程序的逻辑)可在后台重新验证。如果发现应用外壳有更新,会通过一则消息要求用户更新页面。例如 Gmail 的 Inbox 就是这样做的。
然而服务工作进程的代码会对每个网站的静态资源进行缓存并进行重新验证,这会产生不小的开销。此外目前仅 Chrome 和 Firefox 对服务工作进程提供了完善的支持。
9.3,动态内容的缓存
所有缓存方法都会遇到一个问题:无法处理动态内容。这主要是由于 HTTP 缓存的工作原理导致的。缓存主要有两种类型:基于失效(Invalidation-based)的缓存(例如转发代理缓存和 CDN),以及基于过期(Expiration-based)的缓存(例如 ISP 缓存、企业代理以及浏览器缓存)。基于失效的缓存可由服务器主动指定为失效,基于过期的缓存只能由客户端进行重新验证。
在使用基于失效的缓存时,最棘手的问题在于,首次将数据从服务器交付给客户端时,必须指定缓存的寿命(TTL)。随后对于已经缓存的数据就完全丧失了控制能力。在 TTL 过期前,浏览器将始终是用当时缓存的内容。对于静态内容来说,这个问题并不是很麻烦,因为通常这类内容只在部署新版本 Web 应用程序之后才会有改动。因此可以使用诸如 gulp-rev-all 和 grunt-filerev 等实用工具对这些资产创建哈希。
但对于会在应用程序运行过程中加载和改动的各类数据又该怎么办?更改用户资料,更新已发布的内容,或发布新的评论,这些操作涉及的内容似乎无法与浏览器缓存很好地结合在一起,因为我们无法预计此类更新会发生在未来的什么时候。此时只能禁用缓存,或使用非常短的 TTL。
被其他客户端更新后,缓存的动态数据变为陈旧状态的范例
9.4,Baqend 的缓存描述(Cache-Sketch)法
Baqend 研究并开发了一种在客户端实际获取之前检查 URL 陈旧度的方法。在启动每个用户会话后,我们首先会获取一个非常小的数据结构,该结构名为 Bloom 筛选器,是一种高度压缩的内容,其中描述了所有陈旧的资源。通过查询 Bloom 筛选器,客户端可以知道每个资源是否陈旧(包含在 Bloom 筛选器中)或确定其为新鲜状态。对于有可能陈旧的资源,我们会绕过浏览器缓存从 CDN 获取相应的内容。在其他任何情况下,我们会直接通过浏览器缓存提供内容。使用浏览器缓存可以减少网络通信并节约带宽,同时速度相当快。
此外通过在资源变得陈旧后立刻进行清理,确保了 CDN(以及其他基于失效的缓存,例如 Varnish)始终包含最新数据。
Baqend 保障被缓存动态数据新鲜度的范例
Bloom 筛选器是一种基于概率的数据结构,并使用了可调整的假阳性率(False positive rate),这意味着该数据集可能会对从未加入过的对象进行限制,但绝对不会漏掉任何一个需要限制的对象。换句话说,我们可能偶尔会对新鲜资源进行重新验证,但绝对不会交付陈旧的数据。另外值得注意的是,假阳性率非常低,借此才可以让整个数据集的规模尽可能小。例如我们只需要 11K 字节的数据集就可以存储 20000 个不同的更新。
服务器端会进行大量流处理(查询匹配检测)、机器学习(优化 TTL 的估算),以及分布式协调(可缩放 Bloom 筛选器的维护)。如果你对相关细节感兴趣可参阅这篇论文或这些幻灯片以进一步详细了解。
9.5,性能收益
诸多努力就是为了改善性能。
Baqend 的缓存基础架构可以通过哪些方面改善网页加载速度?
为了展示 Baqend 技术对性能的改进,我们通过后端即服务(BaaS)领域每个主要竞争对手的平台构建了一个非常简单的新闻应用程序,并测试了从全球不同位置加载页面所需的时间。如下图所示,Baqend 技术的页面加载速度始终不超过 1 秒,平均来说是竞争对手速度的 6.8 倍。就算所有客户端均与服务器位于同一个位置,由于浏览器缓存技术的使用,Baqend 的速度也快了 150%。
通过一个简单的新闻应用程序对平均加载时间进行的比较
为了对 BaaS 竞争对手的服务进行比较,我们还构建了一个可供大家实际操作进行比较的Web 应用。
实际操作比较结果的屏幕截图
当然,这只是一个测试场景,并非有真实用户的Web 应用程序。我们重新回到Thinks 网店这个例子,看看真实环境中的表现到底如何吧。
9.6,Thinks 网店实际表现
当 DHDL(德国版的“创智赢家”电视节目)在 9 月 6 日首播并吸引了 270 万观众时,我们正坐在电视机前密切关注着 Google Analytics 的统计信息,同时还在为 Thinks 创始人所介绍的产品而感到激动。
从他们介绍自家产品开始,网店的并发用户数在短时间内增加了大约 10000 人,但真正的尖峰发生在节目插播广告的时候,突然之间超过 45000 个并发用户涌入网店打算购买 Towell+:
从插播广告前一刻开始的 Google Analytics 统计结果
在 Thinks 上电视的 30 分钟内,我们收到了340 万请求,300000个访客,高达50000个并发访客,以及每秒最高 20000 个请求——所有这一切都在 CDN 层面实现了98.5% 的缓存命中率以及平均3% 的服务器 CPU 负载。
总的来说,全时段内低于 1 秒的页面加载时间最终产生了高达 7.8% 的转化率,这个结果让人很满意。
如果再看看同一期 DHDL 节目中介绍的其他商家,我们会发现其中有四家彻底宕机,其余几个商家仅使用了微不足道的性能优化技术。
9 月 6 日播出的 DHDL 节目中推荐的商家的整体可用性和谷歌页面加载速度评分
10,总结
在设计快速可缩放网站过程中,我们解决了很多性能瓶颈:我们全面掌握了关键呈现路径,充分理解了网络方面的限制和缓存的重要性,并设计出一套可横向缩放的后端系统。
我们发现有很多实用工具很适合用来解决某些具体的问题,此外还可以通过移动页面加速(AMP)和 Progressive Web Apps(PWA)实现更全面的优化。但动态数据的缓存这个问题依然存在。
Baqend采取的方法是尽量减少前端 Web 开发的工作量,通过 JS SDK 从全面托管的 Baqend 云服务获得所需后端功能,包括数据和文件的存储、(实时)查询、推送通知、用户管理、OAuth,以及访问控制。通过使用完整的 HTTP 缓存体系,该平台可以自动加速所有请求,同时可用性与可缩放性也更有保障。
感谢 Felix Gessert 、 Hannes Kuhlmann 以及 Wolfram Wingerath 。
作者
Erik Witt ,本文的翻译和发布已获原作者授权。阅读英文原文: Building a Shop with Sub-Second Page Loads: Lessons Learned
感谢韩婷对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论