超详细的 CDN(内容分发网络)技术指南

超详细的 CDN(内容分发网络)技术指南

超详细的 CDN(内容分发网络)技术指南

内容交付网络 (CDN) 通过使用分布式服务器网络向用户提供资源,提高了站点性能。由于 CDN 可降低服务器负载,因此它们降低了服务器成本,并且非常适合处理流量峰值。本文讨论 CDN 的工作方式,并提供有关选择、配置和优化 CDN 设置的平台无关的指导。

概述

内容交付网络由服务器网络组成,该网络经过优化,可快速向用户交付内容。尽管 CDN 可以说是最出名的提供缓存内容,但 CDN 也可以改进不可缓存内容的交付。一般来说,你的站点最好是使用 CDN。

CDN 的性能优势源于以下几个原则:CDN 服务器比源服务器更接近用户,因此具有较短的往返时间 (RTT)延迟;网络优化允许 CDN 比从源服务器"直接"加载内容时更快地交付内容;最后,CDN 缓存无需请求访问源服务器。

资源交付

尽管这似乎不直观,但使用 CDN 交付资源(即使是不可缓存的资源)通常比让用户从服务器"直接"加载资源更快。

当 CDN 用于从源传递资源时,客户端和附近的 CDN 服务器之间将建立新的连接。旅程的其余部分(换句话说,CDN 服务器和源之间的数据传输)通过 CDN 的网络进行,这通常包括与源的现有持久连接。这样做的好处是双重的:尽可能接近用户终止新连接,从而消除了不必要的连接设置成本(建立新连接成本高昂,需要多次往返);使用预热连接可以立即以最大可能的吞吐量传输数据。

一些 CDN 通过通过分布在 Internet 的多个 CDN 服务器将流量路由到源,进一步改进了这一点。CDN 服务器之间的连接发生在可靠且高度优化的路由上,而不是由边界网关协议 (BGP) 确定的路由。尽管 BGP 是互联网事实上的路由协议,但其路由决策并不总是以性能为导向。因此,BGP 确定的路由性能可能低于 CDN 服务器之间的微调路由。

缓存

在 CDN 服务器上缓存资源无需请求一路运行到源才能送达。因此,资源交付速度更快;这还可以减少源服务器上的负载。

向缓存添加资源

填充 CDN 缓存最常用的方法是根据需要使用 CDN"拉取"资源 - 这称为"源拉取"。首次从缓存请求特定资源时,CDN 将从源服务器请求该资源并缓存响应。这样,当请求其他未缓存资源时,缓存的内容会随着时间的推移而构建。

从缓存中删除资源

CDN 使用缓存逐出来定期从缓存中删除不太有用的资源。此外,网站所有者可以使用清除来显式删除资源。

  • 缓存删除

    缓存的存储容量有限。当缓存接近其容量时,它通过删除最近未访问的资源或占用大量空间的资源来为新资源提供空间。此过程称为缓存逐出。从一个缓存中逐出的资源并不一定意味着它已被从 CDN 网络中的所有缓存中逐出。

  • 清除缓存

    清除(也称为"缓存无效")是一种从 CDN 缓存中删除资源的机制,无需等待其过期或被逐出。它通常通过 API 执行。在需要收回内容(例如,更正错别字、定价错误或不正确的新闻文章)的情况下,清除至关重要。除此之外,它还可以在站点的缓存策略中发挥关键作用。 如果 CDN 支持近乎即时清除,则清除可用作管理动态内容缓存的机制:使用长 TTL 缓存动态内容,然后在资源更新时清除资源。这样,尽管事先不知道资源何时会更改,但可以最大化动态资源的缓存持续时间。这种技术有时被称为"保持-告诉缓存"。 当大规模使用清除时,它通常与称为"缓存标记"或"代理缓存键"的概念结合使用。此机制允许网站所有者将一个或多个附加标识符(有时称为"标记")与缓存的资源相关联。然后,这些标记可用于执行高度粒度的清除。例如,你可以将"页脚"标记添加到包含站点页脚的所有资源(例如 /about/blog)。更新页脚时,指示 CDN 清除与"页脚"标记关联的所有资源。

可缓存资源

资源是否和如何缓存取决于它是公共的还是私有的;静态或动态。

私有和公共资源

  • 私有资源

    私有资源包含供单个用户使用的数据,因此不应由 CDN 缓存。私有资源由 Cache-Control: private 标头指示。

  • 公共资源

    公共资源不包含特定于用户的信息,因此 CDN 可缓存。如果 CDN 没有 Cache-Control: no-storeCache-Control: private 标头,则 CDN 可认为该资源可缓存。公共资源可以缓存的时间长度取决于资产更改的频率。

动态和静态内容

  • 动态内容

    动态内容是频繁更改的内容。API 响应和商店主页是此内容类型的示例。但是,此内容经常更改的事实并不一定会阻止缓存它。在流量大期间,在很短的时间(例如,5 秒)中缓存这些响应可以显著降低源服务器上的负载,同时对数据新鲜度的影响最小。

  • 静态内容

    静态内容很少更改(如果曾经)。图像、视频和版本控制库通常是此内容类型的示例。由于静态内容不会更改,因此应使用长时间生存时间 (TTL) 进行缓存,例如 6 个月或 1 年。

选择 CDN

在选择 CDN 时,性能通常是重中之重。但是,CDN 提供的其他功能(例如,安全和分析功能)以及 CDN 的定价、支持和入职在选择 CDN 时都很重要。

性能

在高级别上,可以从最小化延迟和最大化缓存命中率之间权衡来考虑 CDN 的性能策略。具有多个存在点 (POP) 的 CD 可以提供较低的延迟,但由于流量在更多缓存之间拆分,可能会遇到较低的缓存命中率。相反,PoP 较少的 CD 可能位于远离用户的地理位置,但可以达到更高的缓存命中率。

由于这种权衡,一些 CDN 使用分层方法来缓存:靠近用户的 POP(也称为"边缘缓存")辅以具有较高缓存命中率的中央 POP。当边缘缓存找不到资源时,它将查找资源的中央 PoP。此方法的延迟稍大一些,因此可以从 CDN 缓存提供资源的可能性更高,但不一定是边缘缓存。

最小化延迟和最小化缓存命中率之间的权衡是一个频谱。没有一种特别的方法是普遍更好的;但是,根据网站的性质及其用户群,你可能会发现其中一种方法的性能明显优于另一种方法。

值得注意的是,CDN 性能可能因地理位置、时间、甚至当前事件而有显著差异。尽管对 CDN 的性能进行自己的研究总是一个好主意,但很难预测从 CDN 获得的确切性能。

其他功能

CDN 除了提供核心 CDN 产品外,通常还提供多种功能。常用功能包括:负载平衡、图像优化、视频流、边缘计算和安全产品。

如何设置和配置 CDN

理想情况下,你应该使用 CDN 来为整个网站服务。在高级别上,此设置过程包括与 CDN 提供程序注册,然后更新 CNAME DNS 记录以指向 CDN 提供程序。例如,www.example.com 的 CNAME 记录可能指向 example.my-cdn.com。由于此 DNS 更改,访问到站点的流量将通过 CDN 路由。

如果使用 CDN 服务所有资源不是一个选项,你可以将 CDN 配置为仅为资源子集服务,例如,仅为静态资源服务。你可以通过创建单独的 CNAME 记录来做到这一点,该记录将仅用于 CDN 应提供的资源。例如,你可以创建指向 static.example.comexample.my-cdn.com CNAME记录。你还需要重写 CDN 提供的资源的 URL,以指向你创建的子域。

尽管此时将设置 CDN,但你的配置可能会效率低下。本文的两节将介绍如何通过提高缓存命中率和启用性能功能来充分利用 CDN。

提高缓存命中率

有效的 CDN 设置将从缓存中为尽可能多的资源提供服务。这通常用缓存命中率 (CHR) 来衡量。缓存命中率定义为缓存命中数除以给定时间间隔内的总请求数。

新初始化的缓存的 CHR 为 0,但随着缓存中填充资源,这会增加。90% 的 CHR 是大多数网站的一个很好的目标。CDN 提供商应提供有关你的 CHR 的分析和报告。

优化 CHR 时,首先要验证的是所有可缓存资源都在以正确的时间长度进行缓存和缓存。这是一个简单的评估,应该由所有网站进行。

从广义上讲,CHR 优化的下一个级别是微调 CDN 设置,以确保逻辑上等效的服务器响应不会单独缓存。这是由于查询参数、cookies 和请求标头等因素对缓存的影响而导致的常见低效率。

初步审计

大多数 CDN 将提供缓存分析。此外,WebPageTest 和 Lighthouse 等工具还可用于快速验证页面的所有静态资源是否缓存的时间长度正确。这是通过检查每个资源的 HTTP 缓存标头来完成的。使用最大适当的生存时间 (TTL) 缓存资源将避免将来出现不必要的源提取,从而增加 CHR。

至少需要设置以下标头之一,以便 CDN 缓存资源:

  • Cache-Control: max-age=
  • Cache-Control: s-max-age=
  • Expires

此外,尽管它不会影响 CDN 缓存资源是否或如何缓存资源,但也可以设置 Cache-Control: immutable。表示资源"在其新鲜度生命周期内不会更新"。因此,浏览器在从浏览器缓存中提供资源时不会重新验证资源,从而消除不必要的服务器请求。不幸的是,此指令仅 Firefox 和 Safari 支持 - 基于 Chrom 的浏览器不支持该指令。

微调

CDN 缓存工作方式的一个稍微简化的解释是,资源的 URL 用作缓存和从缓存中检索资源的键。实际上,这仍然绝对正确,但由于请求标头和查询参数等影响而略有复杂。因此,重写请求 URL 是最大化 CHR 和确保向用户提供正确内容的重要技术。正确配置的 CDN 实例在过于粒度缓存(这会损害 CHR)和颗粒不足缓存(这会导致向用户提供不正确的响应)之间取得了正确的平衡。

查询参数

默认情况下,CDN 在缓存资源时考虑查询参数。但是,对查询参数处理进行少量调整会对 CHR 产生重大影响。例如:

  • 不必要的查询参数

    默认情况下,CDN 将单独缓存 example.com/blogexample.com/blog?referral_id=2zjk,即使它们可能是相同的基础资源。这是通过调整 CDN 的配置来忽略查询参数的固定。

  • 查询参数顺序

    CDN 将从 example.com/blog?id=123&query=dogsexample.com/blog?query=dogs&id=123中单独缓存。对于大多数站点,查询参数顺序并不重要,因此配置 CDN 对查询参数进行排序(从而规范化用于缓存服务器响应的 URL)将增加 CHR。

Vary

Vary响应标头通知缓存,对应于特定 URL 的服务器响应可能因在请求上设置的标头而异(例如,接受语言或接受编码请求标头)。因此,它指示 CDN 单独缓存这些响应。CdN 不广泛支持 Vary 标头,这可能会导致无法从缓存中提供可缓存的资源。

尽管 Vary 标头可能是一个有用的工具,但不适当的使用会伤害 CHR。此外,如果确实使用 ,规范化请求标头将有助于改进 CHR。例如,如果不规范化请求标头,将导致 Vary``Accept-Language: en-USAccept-Language: en-US,en;q=0.9 这两个单独的条目被缓存,即使它们的内容可能相同。

Cookie

Cookie 通过 Cookie 标头对请求进行设置;它们通过 Set-Cookie 在响应上设置。应避免不必要地使用 Set-Cookie 标头,因为缓存通常不会缓存包含此标头的服务器响应。

性能功能

本节讨论 CDN 通常作为其核心产品一部分提供的性能功能。许多网站忘记启用这些功能,从而损失了大量的时间。

压缩

所有基于文本的响应都应使用 gzip 或 Brotli 进行压缩。如果你有选择权,请选择布罗特利而不是 gzip。Brotli 是一种较新的压缩算法,与 gzip 相比,它可以实现更高的压缩比。

有两种类型的 CDN 支持布罗特利压缩:"布罗特利从原点"和"自动布罗特利压缩"。

首次请求资源时,使用"最新"的压缩(例如 Brotli-5)提供资源。这种类型的压缩适用于可缓存资源和非可缓存资源。

同时,如果资源是可缓存的,CDN 将使用脱机处理以更强大但速度慢得多的压缩级别压缩资源,例如 Brotli-11。完成此压缩后,将缓存更多压缩的版本并用于后续请求。

压缩最佳实践

希望最大限度地提高性能的站点应同时在源服务器和 CDN 上应用 Brotli 压缩。源处的 Brotli 压缩可最大程度地减少无法从缓存中提供的资源的传输大小。为了防止服务请求的延迟,源应使用相当保守的压缩级别(例如 Brotli-4) 压缩动态资源;可以使用 Brotli-11 压缩静态资源。如果原点不支持 Brotli,则 gzip-6 可用于压缩动态资源;如果源不支持 Brotli,则 gzip-6 可用于压缩动态资源。gzip-9 可用于压缩静态资源。

TLS 1.3

TLS 1.3 是最新版本的传输层安全 (TLS),这是 HTTPS 使用的加密协议。与 TLS 1.2 相比,TLS 1.3 提供了更好的隐私和性能。

TLS 1.3 将 TLS 握手从两个往返缩短为一个往返。对于使用 HTTP/1 或 HTTP/2 的连接,将 TLS 握手缩短为一次往返可有效将连接设置时间缩短 33%。

HTTP/2 和 HTTP/3

HTTP/2 和 HTTP/3 都比 HTTP/1 提供性能优势。其中,HTTP/3 提供了更大的潜在性能优势。HTTP/3 尚未完全标准化,但一旦公开发布,将得到广泛支持。

HTTP/2

如果 CDN 默认情况下尚未启用 HTTP/2,则应考虑将其打开。HTTP/2 比 HTTP/1 提供多种性能优势,并且所有主要浏览器都支持它。HTTP/2 的性能特点包括:多路复用、流优先级、服务器推送和标头压缩。

  • 复用

    多路复用可以说是 HTTP/2 最重要的功能。多路复用使单个 TCP 连接能够同时为多个请求-响应对服务。这消除了不必要的连接设置的开销;鉴于浏览器在给定时间可以打开的连接数量是有限的,这还意味着浏览器现在能够并行请求更多页面的资源。多路复用从理论上讲消除了对 HTTP/1 优化(如串联和子画面表)的需要 - 但是,在实践中,这些技术将保持相关性,因为较大的文件压缩效果更好。

  • 流优先级

    多路复用支持多个并发流;流优先级提供了一个接口,用于传达每个流的相对优先级。这有助于服务器首先发送最重要的资源 - 即使没有首先请求它们。

流优先级由浏览器通过依赖项树表示,只是一个首选项语句:换句话说,服务器没有义务满足(甚至考虑)浏览器提供的优先级。当通过 CDN 提供更多站点时,流优先级将变得更加有效。

尽管将 CDN 实例切换到 HTTP/2 在很大程度上是翻转交换机的问题,但在在生产中启用此更改之前,必须彻底测试此更改。HTTP/1 和 HTTP/2 对请求和响应标头使用相同的约定,但当这些约定未得到遵守时,HTTP/2 就不那么宽容了。因此,在启用 HTTP/2 后,标头中包含非 ASCII 或大写字符等非规范做法可能会开始导致错误。如果发生这种情况,浏览器下载资源的尝试将失败。失败的下载尝试将在 DevTools 的"网络"选项卡中可见。此外,错误消息"ERR_HTTP2_PROTOCOL_ERROR"将显示在控制台中。

HTTP/3

HTTP/3是HTTP/2 的后继。截止 2020 年 9 月,所有主要浏览器都支持HTTP/3,部分 CDN 支持它。性能是 HTTP/3 比 HTTP/2 的主要优势。具体地说,HTTP/3 消除了连接级别的线头阻塞,并缩短了连接设置时间。

  • 消除线头阻塞

    HTTP/2 引入了多路复用功能,该功能允许使用单个连接同时传输多个数据流。但是,使用 HTTP/2 时,单个丢弃的数据包会阻止连接上的所有流(这种现象称为线头阻塞)。使用 HTTP/3 时,丢弃的数据包仅阻止单个流。这种改进主要是使用UDP(HTTP/3通过QUIC使用 UDP)而不是TCP的结果。这使得 HTTP/3 对于通过拥塞或有损网络进行数据传输特别有用。

    HTTP 各版本请求流程

  • 缩短连接设置时间

    HTTP/3 使用 TLS 1.3,因此共享其性能优势:建立新连接只需要一次往返,恢复现有连接不需要任何往返。

    TLS 1.3 版本建立连接流程图

HTTP/3 对用户网络连接不良的影响最大:不仅因为 HTTP/3 处理数据包丢失比其前身更好,还因为 0-RTT 或 1-RTT 连接设置产生的绝对时间节省在高延迟的网络上会更大。

图像优化

CDN 图像优化服务通常侧重于图像优化,这些优化可以自动应用,以减少图像传输大小。例如:剥离 EXIF 数据,应用无损压缩,将图像转换为较新的文件格式(例如 WebP)。图像占中位数网页上传输字节的 ±50%,因此优化图像可以显著降低页面大小。

压缩

删除从 JavaScript、CSS 和 HTML 中删除不必要的字符。最好在源服务器而不是 CDN 进行压缩。网站所有者对要分明的代码有更多的上下文,因此通常可以使用比 CDN 使用的更激进的分化技术。但是,如果在源指定代码不是一个选项,则由 CDN 进行分明是一个很好的选择。

结论

  • 使用 CDN:CDN 可快速提供资源,减少源服务器上的负载,并有助于处理流量峰值。
  • 尽可能积极地缓存内容:静态和动态内容都可以而且应该缓存 - 尽管持续时间不同。定期审核你的网站,以确保你以最佳方式缓存内容。
  • 启用 CDN 性能功能:Brotli、TLS 1.3、HTTP/2 和 HTTP/3 等功能进一步提高了性能。