Web性能优化——网络篇

Web 性能优化是一个复杂的问题,往往涉及从需求到维护的软件工程的各个方面。并且根据具体业务的不同也会采取不尽相同的针对性措施。本文主要针对 Web 网络性能,从问题产生的原因以及对应的一些优化措施,对 Web 的性能优化做一些简单的总结和思考。

1. Web 网络性能分析

随着计算机性能的提升和现代浏览器的不断进步,客户端的性能完全能够胜任普通的 Web 页面甚至是复杂的 Web 应用和具有炫酷特效的 Web 游戏。客户端性能对于绝大多数 Web 开发者来说不再是性能优化的瓶颈。Web 性能优化的焦点来到计算机网络的传输能力。但随着家庭用户的网络带宽和通信质量不断提升,入户带宽能达到数百兆甚至上千兆,这对于通常只有数兆大小的 Web 页面资源来说是完全足够的。似乎一切有关 Web 性能的软硬件环境看起来都很美好,那么 Web 性能的瓶颈出现在哪呢?

答案是网络延迟。网络延迟之所以成为影响 Web 性能的重要因素,有很多方面的原因,下面结合我个人的知识和经验简单分析。

1.1. 信号传输时延

网络信号传输的延迟受很多因素影响,包括

  • 信号在链路中的传播速度
  • 消息长度和链路速率 (带宽)
  • 网络设备对网络信号的处理能力
  • 以及网络拥塞造成的排队时间等

即使抛开其他因素,只考虑信号在链路中的传播速度也会发现这是一个不容忽视的数值 (见下表)。并且根据现有的物理学理论,信号传播速度无法突破光速上限,所以信号传播的时延已经很难得到像客户端性能和网络带宽那样大幅的提升了。

路线 距离(km) 时间: 光在真空中 时间: 光在光纤中 RTT(Roud-Trip Time)
纽约到旧金山 4148 14ms 21ms 42ms
纽约到伦敦 5585 19ms 28ms 56ms
纽约到悉尼 15993 53ms 80ms 160ms

上表摘自《Web 性能权威指南》[2],列举了理想情况下光纤信号在全球一些城市之间的传播延迟,可以发现当距离较远时光纤的 RTT 会达到较高的数值。

1.2. 传输协议的握手机制

由于 HTTP 最初是基于 TCP 实现的,所以在建立 HTTP 连接前不可避免地要先进行 TCP 的三次握手。并且目前安全传输又成了很多 Web 应用的必要需求,HTTPS 几乎成为 Web 页面的“标配”。因此 TLS 等安全传输协议的握手机制也要在正式建立 HTTP 通信之前进行。这就导致了在数据正式开始传输之前至少要经历 2 至 3 个 RTT 才能开始。也就是说即使不考虑数据传输所需要的时间,单是准备工作就要消耗上百毫秒的时间。

TLS 1.0 握手流程,至少消耗 3 个 RTT

1.3. 网络资源请求的串行

由于 Web 应用越来越复杂,一个页面往往伴随着十数个甚至数十上百个资源请求。如果这些请求串行执行,那么再大的网络带宽也得不到有效利用,网络延迟造成的资源加载时间被成倍扩大。等到几十个资源的依次加载完成时用户早已失去了耐心。

不过好消息是,现代浏览器会对页面进行资源预扫描,然后并行地对网络资源进行请求和加载。但坏消息是,为了避免服务器因接接受过多的 TCP 请求而不堪重负,各浏览器都会对同一个域名发起的 TCP 请求数进行限制,一般是 6 个左右。这就意味当页面中需要的资源请求太多时,很多请求还是不可避免地要串行执行。

1.4. 移动网络的不稳定性

随着移动设备的大规模普及和应用,移动网络环境成为开发者不得不考虑的因素。移动网络相较有线网络,不仅网络延迟更高、带宽更低,更致命的是移动网络的不稳定性会导致 TCP 连接的丢包甚至中断。而 TCP 连接一旦出现问题就会触发拥塞避免机制降低网络传输的速率,甚至重新执行握手算法!这对于本就不快的移动网络来说更是雪上加霜。而移动设备用户因为有更丰富的 APP 可以使用,可能对 Web 应用的包容度更低,这就意味着缓慢的加载速度将极大地摧毁用户的好感。

2. 网络性能的优化方法

以上对影响网络性能的因素进行了分析。可以发现核心就在于网络信号传播的时延无法避免,而其他因素如多资源的串行请求、协议的握手算法、移动网络的不稳定等因素又加剧了网络的延迟。那么解决方自然也要从这些因素入手。

2.1. 升级服务端的 HTTP 协议

如果只能选一个优化 Web 网络性能的方法我一定会选择把服务端的 HTTP 协议升级至 HTTP/3。因为从 HTTP/2 开始就引入了数据分帧的技术,在建立一个连接的基础上能实现对数据进行并行请求。同时还进行了一系列的性能优化。而 HTTP/3 更是使用 UDP 重写了 HTTP,从根本上避免了很多由于 TCP 握手以及拥塞控制等机制导致的延迟。并且更重要的是从开发者的角度来看,这几乎是一个零成本的举措,由于 HTTP/3 的兼容性客户端和服务端几乎不需要对原有的软件进行任何修改 (当然要升级服务端的 web server)。现代浏览器也对 HTTP/2 和 HTTP/3 有了很好的支持。

下表是截止到该文章发表我的主页 hozen.site 7 天内的访问请求的客户端 HTTP 版本统计。从统计结果可以看出,HTTP/2 和 HTTP/3 的访问占比已经高达三分之二,并且我估计其中真实用户的 HTTP/2 和 HTTP/3 的占比会更高。因为应该有很多网络爬虫使用了低版本的 HTTP 协议。

版本 请求 请求百分比
HTTP/2 8,045 49.72%
HTTP/1.1 5,344 33.03%
HTTP/3 2,767 17.1%
HTTP/1.0 23 0.1%

当然由于用户群体的不同 HTTP 协议版本的分布会有差别,但毫无疑问的是客户端使用高版本 HTTP 的占比会不断的提高。所以低成本带来的高性能提升使得所以 HTTP/3 非常值得尝试。

2.2. 使用 CDN

在 1.1 节中的表格可以看出,信号传播的时延与距离成正比。若服务器离客户端非常远,那么信号传播时延无疑会非常高。而 Contente Delivery Network 正是为了解决此问题而生的。CDN 将就近为用户分配资源服务器,以缩短由于距离造成的传播时延过长。并且 CDN 已经有非常成熟的技术和提供商,唯一的问题可能就是需要支付一定的费用。

2.3. 提高网络资源的并行效率

由于浏览器对于同一个域名下的并行请求数量有限制,那么当网络资源过多时可以将它们分别放置在不同的域名下,这样浏览器就会为该页面使用更多的并行连接。

另一方面,对于一些体积很小但数量很多的资源,例如图标文件。要想办法将这些资源整合起来减少资源的数量。因为无论网络资源体积的大小有多大,建立连接和传播消耗的时间都是相同的常数时间。当资源体积较小时,资源的传输时间占据的相对比例就会变得很小,整个网络的利用率就会降低。另一方面这些数量众多的资源还会消耗很多并行请求,使得其他资源的请求不得不进入排队队列。解决该问题的一个常见的例子就是使用“雪碧图”技术拼接一些小体积的图片以减少请求次数。

但还要注意,当某个资源体积过大造成数据的传输时间占据过高比重时。那么就需要对该资源进行拆分,以利用浏览器的并行请求加快对该资源的加载。这种思路在单页面应用中比较常见,由于主要的 JS 文件融合许多依赖库导致体积过大,当该文件加载完成前页面可能会面临白屏的风险。所以一些“拆包”插件应运而生。

但是问题是进行拆包或者资源合并这两个看似矛盾的举措之间的分界线在哪里?也就是说当资源文件多小时要整合,又当达到多大时要拆分?很显然这个阈值和用户的网络带宽和网络延迟有关,因此需要对用户群体的网络状况进行统计分析后才有可能得到整体较优的阈值。

但是!当你使用了 HTTP/2 或 HTTP/3 之后,你就无需考虑这些问题了。因为 HTTP/2 和 HTTP/3 使用数据分帧技术只需要建立一个连接就可以并行传输资源。甚至以上的方法可能产生负优化的效果,例如将资源放在不同的域名反而会额外增加建立连接的时间。当这里的负优化是相对 HTTP/3 自身来说的,相对与 HTTP/1.1 仍然具有性能的提升。

2.4. 服务端渲染和缓存控制

使用服务端渲染的对网络性能提升的好处很明显,那便是减少客户端网络资源请求的次数。但并不是所有的资源都适合服务端渲染,服务端渲染的目的是提高 Web 的响应速度,所以服务端渲染最好用于一些长时间有效的静态资源或者用户共享资源。否则可能会给服务端造成过大的压力,导致资源响应过慢反而降低了页面的加载速度。

缓存是一个老生常谈但却并不简单的问题,网上的材料很多这里不再赘述。

There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton

2.5. 合理的组织 HTML

合理的组织 HTML 页面包括:

  • 合理放置样式文件和脚本文件的位置
  • 使用 script 标签的 asyncdefer 属性加快资源加载
  • 尽可能使用 image 标签提前向浏览器暴露资源请求 (而不是使用 background-images 属性)
  • 合理使用 base64 编码减少资源请求

等。由于这些方法和 Web 性能优化的其他方面产生重合,本文不再展开。

3. 小结

本文对最近对于 Web 网络性能的学习和实践做了一个小的总结,主要的资料和经验来自于《计算机网络》[1]、《Web 性能权威指南》[2]、各大开发者社区及开放文档,以及对个人项目 hexo-theme-tranquility 的优化实践。正如文章开头所讲 Web 性能是一个复杂但重要的问题,所以难免有所疏漏,恳请读者批评。


参考资料

[1] 谢希仁. 计算机网络[M/OL]. 6 版. 电子工业出版社, 2013[2023-07-09].

[2] GRIGORIK I. Web性能权威指南[M/OL]. 李松峰, 译. 人民邮电出版社, 2013[2023-07-09].

[3] 等