如何使用 CDN 和负载均衡器进行文件版本控制?
How to do file versioning with CDN and a loadbalancer?
所以我使用的是一个非常简单的 CDN 服务。你指向你的网站,如果你通过他们的主机名调用它,他们会在第一次调用后为你缓存它。
我将它用于所有静态内容,例如 JavaScript 文件和图像。
这一切都很完美 - 我喜欢它几乎没有维护或设置成本。
推出 JavaScript 文件的新版本时出现问题。如果文件更改,新的 JavaScript 文件会自动获得新的哈希值。
因为不是同时推出多个实例,所以会出现问题。我试图在这张图中对其建模:
换言之:
- 请求使用新版本访问服务器
- 请求具有新版本哈希的 Js 文件
- CDN 正确检测到文件未缓存
- CDN 从负载均衡器请求带有新哈希的原始文件
- 负载均衡器将 CDN 请求提供给随机服务器 - 不小心从具有旧版本的服务器提供服务
- CDN 使用新哈希缓存旧版本
- 每个人都从 CDN 获得旧版本
我知道有一些方法可以解决此问题 - 即手动将文件上传到单独的存储空间,并内置哈希等。
但这需要额外的代码并且有更多的 "moving parts" 使得维护更加复杂。
我更愿意拥有像正常 CDN 行为一样无缝工作的东西。
我想这是 运行 在多个实例上的站点的常见问题,但我找不到很多关于此的信息。
解决这个问题的常用方法是什么?
编辑
我认为另一种解决方案是以某种方式强制 CDN 将 .js 文件转到与原始 html 文件相同的实例 - 但是怎么做呢?
这类问题的问题是缓存控制驻留在浏览器端,所以你不能从服务器端做太多。
我知道的最常见的方法基本上就是您提到的向文件名或用于获取它们的 URL 添加一些哈希值的方法。
问题是您不应该手动执行此操作。您应该使用一些 Web 应用程序构建器(如 Webpack)来自动执行此过程,这取决于您使用的技术。 13 年前,我第一次使用 GWT 看到了这一点,而我最近使用 AngularJS 或 React 参与的所有项目都已与自动执行您需要的构建器集成。
实施后,您的用户将获得最新版本,资源将被正确缓存以加速您的网站。
如果您还可以自动化完整管道以在达到配置的过期时间后从 CDN 中删除旧资源,那么您就触及了天空。
以下是我过去解决方案的一些想法,尽管您使用的 CDN 会排除其中的一些想法:
- 从 CDN 缓存服务中排除 .js 文件,防止它首先被缓存。
- 向 CDN 发送请求,在发布时使特定文件的缓存失效。
- 在您的 build/deploy 脚本中,更改 .js 文件的名称并在您的 HTML 中引用新文件。
- 在 .js 文件名后使用查询参数,这些参数将被忽略但缓存在不同的地址引用下,例如/mysite/myscript.js?build1234
我最终通过在运行几分钟后仅引用 CDN 版本来解决此问题。
因此,如果运行时间少于 5 分钟,则指的是:
/scripts/example.js?v=351
5分钟后引用CDN版本:
https://cdn.example.com/scripts/example.js?v=351
5 分钟后,我们非常确定所有实例都是 运行 新版本,这样我们就不会不小心用新哈希缓存旧版本。
缺点是在非常繁忙的时刻,如果您要重新部署,您将无法利用 CDN,但我还没有看到更好的选择。
所以我使用的是一个非常简单的 CDN 服务。你指向你的网站,如果你通过他们的主机名调用它,他们会在第一次调用后为你缓存它。
我将它用于所有静态内容,例如 JavaScript 文件和图像。
这一切都很完美 - 我喜欢它几乎没有维护或设置成本。
推出 JavaScript 文件的新版本时出现问题。如果文件更改,新的 JavaScript 文件会自动获得新的哈希值。
因为不是同时推出多个实例,所以会出现问题。我试图在这张图中对其建模:
换言之:
- 请求使用新版本访问服务器
- 请求具有新版本哈希的 Js 文件
- CDN 正确检测到文件未缓存
- CDN 从负载均衡器请求带有新哈希的原始文件
- 负载均衡器将 CDN 请求提供给随机服务器 - 不小心从具有旧版本的服务器提供服务
- CDN 使用新哈希缓存旧版本
- 每个人都从 CDN 获得旧版本
我知道有一些方法可以解决此问题 - 即手动将文件上传到单独的存储空间,并内置哈希等。 但这需要额外的代码并且有更多的 "moving parts" 使得维护更加复杂。
我更愿意拥有像正常 CDN 行为一样无缝工作的东西。 我想这是 运行 在多个实例上的站点的常见问题,但我找不到很多关于此的信息。
解决这个问题的常用方法是什么?
编辑
我认为另一种解决方案是以某种方式强制 CDN 将 .js 文件转到与原始 html 文件相同的实例 - 但是怎么做呢?
这类问题的问题是缓存控制驻留在浏览器端,所以你不能从服务器端做太多。
我知道的最常见的方法基本上就是您提到的向文件名或用于获取它们的 URL 添加一些哈希值的方法。
问题是您不应该手动执行此操作。您应该使用一些 Web 应用程序构建器(如 Webpack)来自动执行此过程,这取决于您使用的技术。 13 年前,我第一次使用 GWT 看到了这一点,而我最近使用 AngularJS 或 React 参与的所有项目都已与自动执行您需要的构建器集成。
实施后,您的用户将获得最新版本,资源将被正确缓存以加速您的网站。
如果您还可以自动化完整管道以在达到配置的过期时间后从 CDN 中删除旧资源,那么您就触及了天空。
以下是我过去解决方案的一些想法,尽管您使用的 CDN 会排除其中的一些想法:
- 从 CDN 缓存服务中排除 .js 文件,防止它首先被缓存。
- 向 CDN 发送请求,在发布时使特定文件的缓存失效。
- 在您的 build/deploy 脚本中,更改 .js 文件的名称并在您的 HTML 中引用新文件。
- 在 .js 文件名后使用查询参数,这些参数将被忽略但缓存在不同的地址引用下,例如/mysite/myscript.js?build1234
我最终通过在运行几分钟后仅引用 CDN 版本来解决此问题。
因此,如果运行时间少于 5 分钟,则指的是:
/scripts/example.js?v=351
5分钟后引用CDN版本:
https://cdn.example.com/scripts/example.js?v=351
5 分钟后,我们非常确定所有实例都是 运行 新版本,这样我们就不会不小心用新哈希缓存旧版本。
缺点是在非常繁忙的时刻,如果您要重新部署,您将无法利用 CDN,但我还没有看到更好的选择。