Amazon ec2 在执行滚动部署时,如何确保Cloudfront具有正确的资产版本?

Amazon ec2 在执行滚动部署时,如何确保Cloudfront具有正确的资产版本?,amazon-ec2,amazon-cloudfront,capifony,Amazon Ec2,Amazon Cloudfront,Capifony,我们目前正在使用Capifony和插件将代码滚动部署到ELB后面的一组实例。我们还使用CloudFront来管理静态资产,我们使用查询字符串(例如?v1或?v2)对其进行版本设置 我们偶然发现了一个关于更新资产版本的罕见问题。如果当前版本为v1,并且我们一次对一台服务器执行v2的滚动部署,则v2框上的请求可能会发生以下情况: CloudFront被要求提供v2和未命中 CloudFront前往ELB并要求获得资产 ELB选择了一台服务器,发生了两件事之一:Cloudfront命中一台新部署的服务

我们目前正在使用Capifony和插件将代码滚动部署到ELB后面的一组实例。我们还使用CloudFront来管理静态资产,我们使用查询字符串(例如?v1或?v2)对其进行版本设置

我们偶然发现了一个关于更新资产版本的罕见问题。如果当前版本为v1,并且我们一次对一台服务器执行v2的滚动部署,则v2框上的请求可能会发生以下情况:

  • CloudFront被要求提供v2和未命中
  • CloudFront前往ELB并要求获得资产
  • ELB选择了一台服务器,发生了两件事之一:Cloudfront命中一台新部署的服务器(服务于v2)或命中旧服务器(v1)
  • 无论哪种方式,Cloudfront都将内容存储为v2。如果它击中v1服务器,则内容服务不正确
  • 我们目前的解决方案是,我们必须使用新的资产版本进行另一次部署

    有没有办法通过ELB强制Cloudfront只访问我们更新的(v2)服务器之一,而忽略v1


    或者我缺少了解决问题的替代解决方案?

    我认为在您的情况下,正确的部署策略应该是首先部署能够同时服务于v1和v2资产(但仍服务于v1)的实例,然后执行另一个滚动部署以切换到v2


    ELB()上也有“粘性会话”,但我不知道如何在这里使用它-每查看器cookie将消除CloudFront缓存的好处

    当CloudFront从您的源站获得404时(可能是因为它尚未收到新版本),它将404缓存5分钟。您可以通过为您的发行版创建新的“自定义错误响应”来改变该行为。自定义响应允许您设置一个非常低的TTL,以便Cloudfront将通过您的ELB,直到找到新文件为止。这样做的缺点是Cloudfront将不再有效地缓存404—您的ELB将需要处理该负载(希望负载较小!)


    我们选择的方法是广泛放弃现有的资产部署管道。以“旧”的方式,我们选择了
    asset.css?v=
    模型,其中CloudFront指向一个由多个实例提供服务的原点

    我们解决这个问题的方法是使用散列名资产模型和基于S3的源代码。这意味着,我们没有使用
    asset.css?v=
    而是使用
    asset-.css
    同步到S3 bucket。bucket会逐渐添加越来越新的版本,但是如果我们决定返回,或者像电子邮件这样的东西链接到它(图像的常见问题),旧版本总是可用的

    同步到S3脚本在我们部署到包含引用资产的HTML的Web服务器之前运行,因此CloudFront始终能够为最新的资产提供服务

    下面是一个示例脚本:

    #!/usr/bin/env bash
    
    set -e # Fail on any error
    set -x
    
    if [ "$#" -ne "1" ]
    then
        echo "Usage: call with the name of the environment you're deploying to"
        exit 1
    fi
    
    CDN_ENVIRONMENT=$1
    
    S3_BUCKET="s3://static-bucket-name-of-your-choice/${CDN_ENVIRONMENT}/"
    
    echo "Generating assets
    
    ... do the asset generation here ...
    
    echo "Copying to S3"
    
    # Now do the actual copying of the web dir. We use size-only because otherwise all files are newer, and all get copied.
    aws s3 sync --exclude "some-folder-to-exclude/*" --acl public-read --size-only ./web/ ${S3_BUCKET}
    
    echo "Copy to S3 complete"
    

    你有没有找到一个好的方法?有一个类似的问题,但由于资产版本是以名称命名的,当使用只有v1的旧服务器时,客户端会得到404。