如何在没有用户停机的情况下将我的 CloudFront 分配替换为另一个

Posted

技术标签:

【中文标题】如何在没有用户停机的情况下将我的 CloudFront 分配替换为另一个【英文标题】:How can I replace my CloudFront distribution with another without user downtime 【发布时间】:2015-07-18 02:40:04 【问题描述】:

初始设置

在 AWS 上,我有一个为页面提供服务的 Elastic Beanstalk (EB) 服务器。 在任何一个月的特定请求中,它始终会提供相同的数据,因此我设置了 Cloudfront 分发版以更好地为客户提供服务并减少服务器访问量。 在 Route53 中将域配置为指向 Cloudfront 分发 所有客户访问都通过此域

每月

我部署了新版本的 EB 服务器 然后我想使 CloudFront 中的所有页面无效,以便它从 EB 服务器获取最新数据。

但是失效是缓慢且昂贵的,所以我的计划是创建一个新的 Cloudfront 发行版。然后修改我的 Route53 域以指向新的 CloudFront,然后在完成后删除原始 CloudFront 分配。

问题在于,如果您设置的 Alternate CName 已被另一个分配使用,CloudFront 不允许您创建新分配。所以我无法创建新的发行版,直到我禁用并删除现有的发行版,然后我必须部署我的新发行版,这需要很长时间,并且在此期间网站会关闭。

我的替代方案如下

部署新的 EB 服务器 将 Route53 指向新 EB 服务器的负载均衡器 禁用 CloudFront 分发,然后等待。 删除 CloudFront 分配,然后等待。 创建新的 CloudFront 分配,然后等待。 点 Route 53 域到新的 CloudFront 分配

【问题讨论】:

【参考方案1】:

您实际上不必等待分发被删除来重用 cname。我做类似的事情。

创建一个新的发行版,其设置与我当前的发行版相同,但减去 cname 设置 从旧发行版中删除 cname,保存 立即将 cname 添加到新发行版中 更新 DNS 以指向新的分布 在部署之前保留旧的分发版 禁用再删除,进行清理

由于我使用了 Cloudfront 发行版的别名,因此我不必担心解析器会缓存我的旧 Cloudfront 提供的 DNS 名称。对我来说效果很好。

【讨论】:

现在正在尝试,但是与部署 EB 服务器相比,为什么在 Cloudfront 中部署如此缓慢。 @PaulTaylor 这是因为 CloudFront 需要将更改部署到全球大约一百个 POP。请注意,它可能仍然会更快……但与部署一个 EB 相比,它还有很多工作要做。【参考方案2】:

有一个变体的笑话说“有些人在遇到问题时会想,'我知道,我会使用缓存。'”现在他们有两个问题。”

一般来说,在使用 CDN 时,需要失效(尤其是“立即”)失效是一种反模式。有几种方法可以解决这个问题:

(最佳)在为您的分发中的内容提供链接时,对链接进行版本控制。你说它每月都会改变 - 所以 /image-2015-04.jpg 可能是上个月的图像,现在是 /image-2015-05.jpg。 使用 Cache-Control 标头,以便每次或每小时重新验证内容

为此使用 Route53 是粗略的——不仅有一个带有 DNS 的 TTL(缓存周期),而且并非所有服务器都支持短 TTL。

【讨论】:

我认为您可能需要使用缓存控制标头或版本控制是正确的,但我只是想保持简单。但是,还有另一种情况无法解决 - 代码更改。如果我需要部署新版本的服务器并且依赖于新的 css/javascript 等,它们都需要在 CloudFront 中失效 - 在这种情况下你会怎么做? 您的服务器可能链接到静态内容。在代码更改的情况下,您使用新内容的新唯一路径。这很常见——Ruby 有一个“资产管道”可以自动执行此操作。举个简单的例子——也许你的 main.css 变成了 main-git hash.css。 静态内容(例如 css)部署在软件中(即它不存储在单独的 S3 缓存中),但关键是一切都通过 CloudFront,因此 cloudfront 只会为现有的 widget.css 提供服务,而不是尝试从服务器获取一个新的。我不太喜欢在我的实际代码中添加版本控制只是为了处理 Cloudfront 问题的想法。 问题在于这不是云端问题,而是缓存(尤其是 CDN)的工作方式。 好吧,我不想为了让它们与 CDN 一起工作而进行代码更改,这不是不合理吗?

以上是关于如何在没有用户停机的情况下将我的 CloudFront 分配替换为另一个的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有私钥的情况下将我的元掩码钱包中的 erc20 代币发送到其他地址?

如何在没有 Index.html 或.php 的情况下将我的 Web 应用程序文件运行到服务器?

如何在不包含节点模块文件夹的情况下将我的 React 项目上传到 GitHub [重复]

如何在不使用和拆分测试集的情况下将我的数据集拆分为训练和验证?

如何在不杀死 /health 的情况下将我的 Spring Boot 应用程序默认为 application/xml?

如何在仍然显示Widgets的情况下将我的AppBar放在Flutter中的单独文件中?