优化 AEM 站点缓存

概述

优化 AEM 架构中的缓存,是显著提升性能的最快速的方法之一。本篇文章重点介绍如何优化 AEM 架构中各种可用的缓存。

AEM 架构和缓存

当用户访问您的站点时,会在所有的 AEM 架构中遇到多个缓存层。在 AEM 标准架构中,有 4 个缓存层需要考虑。它们分别是:Web 浏览器、CDN、调度程序和 AEM 实例。

浏览器缓存

如果用户是重复访问您的站点,那么他/她遇到的第一个缓存级别就是他们自己的浏览器。通常,浏览器级别的缓存是通过 Cache-Control: max-age=... 响应标头来设置。max-age 设置可以告知浏览器,在尝试“重新验证”或再次从相应的站点申请缓存之前,应当缓存文件的时间长度(以秒为单位)。这个缓存 max-age 的概念,往往指的是“缓存到期时间”或 TTL(“生存时间”)。

在影响缓存方式的 Cache-Control 标头中,包含了各种选项(或“指令”)。以下是一些常见的指令:

  1. private - Cache-Control 标头中的 private 指令只允许将文件缓存在浏览器,而非类似 CDN 这样的中间缓存中。这项指令的实用场合:您的页面包含个性化/特定于用户的内容。 

    用法示例:
      Cache-Control: max-age=300, private
  2. s-maxage - Cache-Control 标头中的 s-maxage 指令允许您为类似 CDN 这样的共享缓存,设置不同的 TTL。当设置了该值后,浏览器将运用 max-age 中设置的内容,而其他缓存则改为遵循 s-maxage 设置。

    用法示例:
      Cache-Control: max-age=600, s-maxage=300

现代浏览器全都支持 Cache-Control 标头;然而,有些存在于 HTTP/1.0 中的旧式过时标头,仍可能会对缓存产生影响。这些标头是 ExpiresPragma。如果您不需要支持非常旧的浏览器,那么请不要发送这两个响应标头。
除了缓存之外,“重新验证”也是一个重要的概念。重新验证依赖于 Last-Modified响应)/ If-Modified-Since请求)标头,以及 ETag(响应)/ If-None-Match(请求)标头。

注意:

浏览器测试:

在 Google Chrome 浏览器中测试缓存时,如果针对 https 协议进行测试,并且您具有自签名证书,那么将不会缓存任何内容。当存在不受信任或无效的证书时,Chrome 将不会缓存响应或执行重新验证

关于调度程序的注意事项:

在 AEM 调度程序 v4.2.3 及更早的版本中存在着一个问题,该问题会导致 /enableTTL 仅通过 max-age 指令进行缓存。这意味着,即使设置了 privates-maxage 指令,但是如果设置了 max-age 选项,那么上述版本的 AEM Dispatcher 仍将根据该选项进行缓存。这个问题会在 Dispatcher 4.2.4 及更高版本中得以解决。

CDN 缓存

CDN 或“内容分发网络”是 Web 服务器的分布式网络,旨在从距离用户最近的位置缓存和提供内容。这种缓存方式可减少网络跃点数以及用户计算机与您的内容之间的距离,从而降低“往返时间”(RTT)。RTT 指的是通过浏览器向您的站点发送请求以及收到响应所花费的时间。由于 CDN 提供商领域中的竞争,造成搭建 CDN 变得非常经济实惠。故此,人们会很容易决定使用 CDN 来访问您的站点。如果您尚未使用 CDN,则务必应该在您的站点中融入 CDN。

有许许多多的 CDN 提供商,每一家提供商提供的特征和配置各不相同。

CDN 缓存的工作方式

CDN 在缓存内容时,遵循的规则与浏览器类似。它们依赖于 Cache-Control HTTP 响应 标头;并且通常会在没有找到 Cache-Control 标头的情况下,回退到 Expires 标头。

大多数 CDN 都提供了触发手动刷新缓存的方法。在很多情况下,当涉及传播到包含您的文件的所有边缘服务器时,缓存刷新会存在着一些延迟(例如 15 分钟)。

优化 CDN 的使用

为了确保在 CDN 中采取最佳方式缓存文件,需执行以下操作:

  1. Cache-Control 标头中,使用支持 stale-while-revalidatestale-if-error 指令的 CDN。
    • stale-while-revalidate - 当缓存文件已过期且 CDN 在检索新的缓存文件时,该指令可告知 CDN 提供此文件的旧(即,已缓存的)版本。
    • stale-if-error - 同理,在重新验证期间,如果源缓存文件的响应包含错误,该指令可告知 CDN 提供此文件的旧(即,已缓存的)版本。
  2. 对于所有未经预先压缩的文件类型,GZip 压缩应予以响应。
    • 您应该按照调度程序级别执行这项操作。这将可以确保减少发送到 CDN 的字节数。由于 CDN 通常按传输的字节数收费,因此压缩响应可降低成本。
    • 在调度程序级别启用 GZip 压缩:
      • Apache - 使用 mod_deflate。当 mod_deflate 采用 Vary 标头时,应务必小心。在某些情况下,Vary 标头可能会导致 CDN 和浏览器完全跳过缓存。
      • Microsoft IIS - 使用动态压缩
      • 不允许对大型文件或已经压缩的文件执行 gzip 压缩。请注意,大多数的图像和视频格式的文件均已预先压缩。若在 Web 服务器级别上随即压缩这些文件,则要付出高昂的性能成本。 
        • 在 Apache 上,这项操作可通过 AddOutputFilterByType 指令来完成:
          AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
        • 在 IIS 上,可通过 <dynamicTypes> 配置来控制此项操作。
  3. 如果您的 CDN 提供商支持 Edge-side Include (ESI),请利用此功能。
    • 可利用 ESI,对 AEM 组件进行分组。要执行这项操作,请使用 Apache Sling Dynamic Include 或实施一个定制的解决方案。
    • 当您拥有许多静态页面,但却需要在部分页面中提供更多的动态内容时,这项功能会比较有用。对于这些情况,您实际上是要将页面分组为多个 CDN 文件。这样一来,您便可以在不同时段缓存页面的不同部分。

受欢迎的 CDN 提供商

以下列出了一些颇受欢迎的 CDN 提供商:

注意:

使用 Vary 响应标头时,应务必小心。在某些情况下,Vary 可能会导致 CDN 和浏览器完全跳过缓存。作为一项常规经验,请避免添加 Vary 标头,Vary:Accept-Encoding 除外(仅当响应经过 gzip 压缩后适用)。换言之,如果您需要“变换”响应的输出结果,请使用不同的 URL。

例如,如果要为移动设备与桌面设备选用不同的 HTML 版本,则使用不同的 URL。这将允许 CDN 和浏览器更有效地进行缓存。

AEM 调度程序缓存

如果 CDN 缓存已过期,则相关请求将传送至 AEM 调度程序缓存。在这个级别,可执行许多优化缓存的操作。

由于这是一个较大的主题,请参阅这篇文章,以了解有关如何优化调度程序缓存的详细信息。

AEM Publish 实例

在 AEM 级别,应当执行几项操作来优化各种缓存层:
  1. 设置以下 HTTP 响应标头,这些标头在默认情况下,没有经过 AEM 设置。
    1. Cache-Control: max-age=... - 若要设置这个标头,可能需要使用 ACS Commons - Dispatcher TTL;或者,您可以实施定制的代码来进行设置。
    2. Last-Modified - 如果页面内容保持相对静态(例如,一篇文章),那么可将其 last-modified 标头设置为“cq:lastModified date/time”(即,最近一次修改这篇文章的时间)。然而,如果页面是动态的,并且组件内容中包含 JCR 查询结果,则最好将其设置为使用当前的日期/时间。
    3. ETag - 如果决定使用这个标头而不是 Last-Modified,则可能需要编写一个 ReplicationEventListener,以此来侦听页面激活并生成关于页面内容的 md5 哈希值。可将这个标头设置为 author 实例上有关该页面 jcr:content 节点的属性。当复制页面时,该属性将会发送到 publish 实例中。对于内容相对静态的页面组件,这个标头可正常工作;但是,如果页面包含动态内容或引用了大量内容,则必须忽略(或计算)ETag。
  2. 如果站点包含个性化/动态内容:
    1. 运用 Apache Sling Dynamic Include 来分组内容,以便可以在不同时段缓存页面的不同部分。
      1. 可通过以下技术完成缓存:
        1. CDN 上的 Edge-side Include (ESI)
        2. Web 服务器上的 Server-side Includes (SSI)
        3. 或者,浏览器上的异步 Javascript 和 XML (AJAX)
      2. 可将页面上的组件分组为各个请求,以便在不同时段进行缓存。相对静态的页面部分可以缓存较长的时段。
    2. 考虑使用 ACS Commons 的 HTTP 缓存功能
  3. 优化客户端库。
    1. 在客户端库上,启用压缩
    2. 如果客户端库中的文件已预先缩小,则在该客户端库上禁用压缩。编辑 cq:ClientLibraryFolder 节点:
      1. 将属性 jsProcessor 设置为 String[] 类型,且值为 min:none
      2. 并且将属性 cssProcessor 设置为 String[] 类型,且值为 min:none
      3. 更多详细信息,请参阅此处
    3. 嵌入客户端,以缩小并减少 js 和 css 文件。
    4. 从 ACS Commons 实施版本控制的客户端库,以允许 CDN 和调度程序以较长的时段缓存 js 和 css 文件。
Adobe 徽标

登录到您的帐户