parent
f0cee05836
commit
bbf31256fb
@ -0,0 +1,130 @@ |
|||||||
|
--- |
||||||
|
Web 性能优化最佳实践 |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 前言 |
||||||
|
2. 在客户端缓存资源 |
||||||
|
|
||||||
|
#### 前言 |
||||||
|
|
||||||
|
无论什么网络,也不管所用网络协议是什么版本,所有应用都应该致力于消除或减少不必要的网络延迟,将需要传输的数据压缩至最少。这两条标准是经典性能优化最佳实践,是其他数十条性能准则的出发点: |
||||||
|
|
||||||
|
1. 减少 DNS 查找 |
||||||
|
|
||||||
|
每一次主机名解析都需要一次网络往返,从而增加请求的延迟时间,同时还会阻塞后续请求。 |
||||||
|
|
||||||
|
2. 重用 TCP 连接 |
||||||
|
|
||||||
|
尽可能使用持久连接,以消除 TCP 握手和慢启动延迟。 |
||||||
|
|
||||||
|
3. 减少 HTTP 重定向 |
||||||
|
|
||||||
|
HTTP 重定向极费时间,特别是不同域名之间的重定向,更加费时;这里面既有额外的 DNS 查询、TCP 握手,还有其他延迟。最佳的重定向次数为零。 |
||||||
|
|
||||||
|
4. 使用 CDN(内容分发网络) |
||||||
|
|
||||||
|
把数据放到离用户地理位置更近的地方,可以显著减少每次 TCP 连接的网络延迟,增大吞吐量。 |
||||||
|
|
||||||
|
5. 去掉不必要的资源 |
||||||
|
|
||||||
|
6. 在客户端缓存资源 |
||||||
|
|
||||||
|
应该缓存应用资源,从而避免每次请求都发送相同的内容。 |
||||||
|
|
||||||
|
7. 传输压缩过的内容 |
||||||
|
|
||||||
|
传输前应该压缩应用资源,把要传输的字节减至最少。 |
||||||
|
|
||||||
|
8. 消除不必要的请求开销 |
||||||
|
|
||||||
|
减少请求的 HTTP 首部数据(比如 HTTP Cookie),节省的时间相当于几次往返的延迟时间。 |
||||||
|
|
||||||
|
9. 并行处理请求和响应 |
||||||
|
|
||||||
|
请求和响应的排队都会导致延迟,无论是客户端还是服务端。 |
||||||
|
|
||||||
|
10. 针对协议版本采取优化措施 |
||||||
|
|
||||||
|
HTTP/1.x 支持有限的并行机制,要求打包资源、跨域分散资源,等等。相对而言,HTTP/2.0 只要建立一个连接就能实现最优性能,同时无需针对 HTTP/1.x 的那些优化方法。 |
||||||
|
|
||||||
|
#### 在客户端缓存资源 |
||||||
|
|
||||||
|
要说最快的网络请求,那就是不用发送请求就能获取资源。将之前下载过的数据缓存并维护好,就可以做到这一点。对于通过 HTTP 传输的资源,要保证首部包含适当的缓存字段: |
||||||
|
|
||||||
|
- Cache-Control 首部用于制定缓存时间 |
||||||
|
- Last-Modified 和 ETag 首部提供验证机制 |
||||||
|
|
||||||
|
只要可能,就给每种资源都指定一个明确的缓存时间。这样客户端就可以直接使用本地副本,而不必每次都请求相同的内容。类似的,指定验证机制可以让客户端检查过期的资源是否有更新,没有更新,就没必要重新发送。 |
||||||
|
|
||||||
|
最后,还要注意应同时指定缓存时间和验证方法。 |
||||||
|
|
||||||
|
#### 压缩传输的数据 |
||||||
|
|
||||||
|
利用本地缓存可以让客户端避免每次请求都重复取得数据。不过,还是有一些资源是必须取得的,比如原来的资源过期了,或者有新资源,再或者资源不能缓存。对于这些资源,应该保证传输的字节数最少。因此要保证对它们进行最有效的压缩。 |
||||||
|
|
||||||
|
HTTP、CSS 和 JavaScript 等文本资源的大小经过 gzip 压缩平均可以减少 60~80%。而图片则需要仔细考量,比如选择最优的图片格式。 |
||||||
|
|
||||||
|
这里说一下 WebP 格式,它是 Google 开发的一种新的图片格式,这种格式的无损压缩和有损压缩效能都有所提升: |
||||||
|
|
||||||
|
- WebP 的无损压缩图片比 PNG 的小 26% |
||||||
|
- WebP 的有损压缩图片比 JPG 的小 25%~34% |
||||||
|
- WebP 支持无损透明压缩,但因此仅增加了 22% 的字节 |
||||||
|
|
||||||
|
但是,这种格式需要客户端 CPU 多花点时间解码(大约相当于处理 JPG 的 1.4 倍),但字节的节省完全可以补偿处理时间的增长。 |
||||||
|
|
||||||
|
#### 消除不必要的请求字节 |
||||||
|
|
||||||
|
HTTP 是一种无状态协议,也就是说服务器不必保存每次请求的客户端的信息。然而,很多应用又依赖于状态信息以实现会话管理、个性化、分析等功能。为了实现这些功能,HTTP 做了扩展,允许任何网站针对自身来源关联和更新 Cookie 元数据:浏览器保存数据,而在随后发送给来源的每一个请求的 Cookie 首部中自动附加这些信息。 |
||||||
|
|
||||||
|
上述标准并未规定 Cookie 最大不能超过多大,但实践中大多数浏览器都将其限制为 4KB。与此同时,该标准还规定每个站点针对其来源可以有多个关联的 Cookie。于是,一个来源的 Cookie 就有可能多达几十 KB。不用说,这么多元数据随请求传递,必然会给应用带来明显的性能损失: |
||||||
|
|
||||||
|
- 浏览器会在每个请求中自动附加关联的 Cookie 数据 |
||||||
|
- 在 HTTP/1.x 中,包括 Cookie 在内的所有 HTTP 首部都会在不压缩的状态下传输 |
||||||
|
- 在 HTTP/2.0 中,这些元数据经过压缩了,但开销依然不小 |
||||||
|
- 最坏的情况下,过大的 HTTP Cookie 会超过初始的 TCP 拥塞窗口,从而导致多余的网络往返 |
||||||
|
|
||||||
|
应该认真对待和监控 Cookie 的大小,确保只传输最低数量的元数据,比如安全会话令牌。同时,还应该利用服务器上共享的会话缓存,从中查询缓存的元数据。更好的结果,则是完全不用 Cookie,比如在请求图片、脚本和样式表等静态资源时,浏览器绝大多数情况下不必传输特定于客户端的元数据。 |
||||||
|
|
||||||
|
#### 并行处理请求和响应 |
||||||
|
|
||||||
|
为了让应用响应速度达到最快,应该尽可能第一时间就分派所有资源请求。可是,还有一点也要考虑,那就是所有这些请求以及它们对应的响应,将会被服务器如何处理。如果我们的请求在服务器上按先来后到的顺序依次排队,那就又会导致不必要的延迟。要想实现最佳性能,就要记住以下几点: |
||||||
|
|
||||||
|
- 使用持久连接,从 HTTP/1.0 升级到 HTTP/1.1 |
||||||
|
- 利用多个 HTTP/1.1 连接实现并行下载 |
||||||
|
- 可能的情况下利用 HTTP/1.1 管道 |
||||||
|
- 考虑升级到 HTTP/2.0 以提升性能 |
||||||
|
- 确保服务器有足够的资源并行处理请求 |
||||||
|
|
||||||
|
如果不使用持久连接,则每个 HTTP 请求都要建立一个 TCP 连接。由于 TCP 握手和慢启动,多个 TCP 会造成明显的延迟。在使用 HTTP/1.1 的情况下,最好尽可能重用已有连接。如果碰上能使用 HTTP 管道的机会,不要放过。更好的选择,则是升级到 HTTP/2.0,从而获得最佳性能。 |
||||||
|
|
||||||
|
#### 针对 HTTP/1.1 的优化建议 |
||||||
|
|
||||||
|
针对 HTTP/1.x 的优化次序很重要:首先要配置服务器以最大限度的保证 TCP 和 TLS 的性能最优,然后在谨慎的选择和采用经典的应用最佳实践,之后在度量、迭代。 |
||||||
|
|
||||||
|
1. 利用 HTTP 管道 |
||||||
|
|
||||||
|
如果你的应用可以控制客户端和服务器这两端,那么使用管道可以显著减少网络延迟。 |
||||||
|
|
||||||
|
2. 采用域名分区 |
||||||
|
|
||||||
|
如果你的应用性能受限于默认的每来源 6 个连接,可以考虑将资源分散到多了来源。 |
||||||
|
|
||||||
|
3. 打包资源以减少 HTTP 请求 |
||||||
|
|
||||||
|
拼接和精灵图等技巧有助于降低协议开销,又能达成类似管道的性能提升。 |
||||||
|
|
||||||
|
4. 嵌入小资源 |
||||||
|
|
||||||
|
考虑直接在父文档中嵌入小资源,从而减少请求数量。 |
||||||
|
|
||||||
|
管道缺乏支持,而其他优化手段又各有各的利弊。事实上,这些优化措施如果使用不当,反倒会伤害性能。总之,要有务实的态度,通过度量来评估各种措施对性能的影响。 |
||||||
|
|
||||||
|
#### 针对 HTTP/2.0 的优化建议 |
||||||
|
|
||||||
|
HTTP 2.0 的主要目标就是提升传输性能,实现客户端与服务器间较低的延迟和较高的吞吐量。显然,在 TCP 和 TLS 之上实现最佳性能,同时消除不必要的网络延迟,从来没有如此重要过。 |
||||||
|
|
||||||
|
接下来,或许有点意外,那就是采用移动及其他经典的最佳做法:少发数据、削减请求,根据无线网络情况调整资源供给。不管是用什么版本的协议,减少传输的数据量和消除不必要的网络延迟,对任何应用都是最有效的优化手段。 |
||||||
|
|
||||||
|
最后,杜绝和忘记域名分区、文件拼接、图片精灵等不良的习惯,这些做法在 HTTP/2.0 之上完全没有必要。事实上,继续使用这些手段反而有害,可以利用 HTTP/2.0 内置的多路分发以及服务器推送等新功能。 |
Loading…
Reference in new issue