Forçar distribuição / atualização de arquivo do CloudFront


146

Estou usando o CloudFront da Amazon para veicular arquivos estáticos dos meus aplicativos da web.

Não há como dizer a uma distribuição na nuvem que ele precisa atualizar seu arquivo ou apontar um único arquivo que deve ser atualizado?

A Amazon recomenda que você versão seus arquivos como logo_1.gif, logo_2.gif e assim por diante como uma solução alternativa para esse problema, mas isso parece uma solução bastante estúpida. Não existe absolutamente outra maneira?



como nota de rodapé, não acho estúpido nomear arquivos estáticos assim. Nós o usamos muito e a renomeação automática conforme a versão do arquivo no controle de versão nos salvou muitas dores de cabeça.
eis

1
@eis, a menos que o arquivo que você precise substituir tenha sido vinculado a 1000 locais diferentes online. Boa sorte em atualizar todos esses links.
21412 Jake Wilson

@Jakobud, por que os links devem ser atualizados nesse caso? eles estão se referindo a uma versão específica, que não é a mais recente, se o arquivo foi alterado. Se o arquivo não tiver sido alterado, funcionará como antes.
eis

6
Em alguns casos, uma empresa pode cometer um erro ao publicar a imagem errada para algo ou algum outro tipo de item em que recebe um aviso de remoção de um escritório de advocacia e precisa substituir o arquivo. O simples upload de um novo arquivo com um novo nome não resolverá esse tipo de problema, que infelizmente é cada vez mais comum nos dias de hoje.
9309 Jake Wilson

Respostas:


134

Boas notícias. Finalmente, a Amazon adicionou um recurso de invalidação. Veja a Referência da API .

Esta é uma solicitação de amostra da Referência da API:

POST /2010-08-01/distribution/[distribution ID]/invalidation HTTP/1.0
Host: cloudfront.amazonaws.com
Authorization: [AWS authentication string]
Content-Type: text/xml

<InvalidationBatch>
   <Path>/image1.jpg</Path>
   <Path>/image2.jpg</Path>
   <Path>/videos/movie.flv</Path>
   <CallerReference>my-batch</CallerReference>
</InvalidationBatch>

9
Observe que a invalidação levará algum tempo (aparentemente de 5 a 30 minutos, de acordo com algumas postagens do blog que li).
22660 Michael Michael Warkentin em

37
Se você não quiser fazer uma solicitação da API, você também pode efetuar login no Console Amazon e criar um pedido de invalidação lá: docs.amazonwebservices.com/AmazonCloudFront/latest/...
j0nes

Para aqueles que usam a API para fazer a invalidação, aproximadamente quanto tempo leva para a invalidação entrar em vigor?
ill_always_be_a_warriors

20
Lembre-se de que isso custa US $ 0,005 por arquivo após suas primeiras 1.000 solicitações de invalidação por mês aws.amazon.com/cloudfront/pricing
TimS

1
@MichaelWarkentin Depois de fazer uma createInvalidationsolicitação de API , a atualização ainda está demorando de 5 a 10 minutos para invalidar. Observe que eu escrevo esse comentário 4 anos após o seu.
tim Peterson

19

A partir de 19 de março, a Amazon agora permite que o TTL do cache do Cloudfront seja de 0 segundos; portanto, teoricamente, você nunca deve ver objetos obsoletos. Portanto, se você possui seus ativos no S3, basta acessar o Painel da Web da AWS => S3 => Editar propriedades => Metadados e defina seu valor "Cache-Control" como "max-age = 0".

Isso é direto da documentação da API :

Para controlar se o CloudFront armazena em cache um objeto e por quanto tempo, recomendamos o uso do cabeçalho Cache-Control com a diretiva max-age =. O CloudFront armazena em cache o objeto pelo número especificado de segundos. (O valor mínimo é 0 segundos.)


Onde está essa configuração na nova interface do usuário do AWS Console? Não consigo encontrar.
ill_always_be_a_warriors

1
Encontrei a configuração de um arquivo individual, mas existe uma configuração para que qualquer coisa carregada no meu bucket tenha um TTL de 0?
ill_always_be_a_warriors

Embora eu também estivesse interessado em uma configuração abrangente, achei esta uma solução mais rápida / melhor. As solicitações de invalidação (junto com o restante da API) são muito confusas e mal documentadas, e eu girei minhas rodas por 3 horas antes que isso funcionasse instantaneamente.
Alquimista de dois bits

33
Chame-me de louco, mas definir o TTL como 0 e max-age como 0 está realmente usando o CloudFront sem armazenamento em cache, isso não encaminharia todas as solicitações para a origem verificando constantemente atualizações? Essencialmente tornando a CDN inútil?
acidjazz

6
Se você estiver usando o cloudfront como um mecanismo para ter um site S3 estático habilitado para SSL com um domínio personalizado, o cache não será importante. Além disso, essas questões que estamos discutindo é que, nas fases de desenvolvimento, o armazenamento em cache de 0 horas é bom.
Dan G

10

Com a API de invalidação, ela é atualizada em alguns minutos.
Confira PHP Invalidator .


Era exatamente isso que eu estava procurando. Vou colocar isso nos ganchos da Web do Beanstalkapp ao implantar automaticamente a partir do git! Obrigado pelo link!
usar o seguinte comando

10

Configuração de atualização automatizada em 5 minutos

Ok pessoal. A melhor maneira possível por enquanto de executar a atualização automática do CloudFront (invalidação) é criar a função Lambda que será acionada sempre que qualquer arquivo for carregado no bucket do S3 (um novo ou reescrito).

Mesmo se você nunca usou funções lambda antes, é realmente fácil - basta seguir minhas instruções passo a passo e levará apenas 5 minutos:

Passo 1

Acesse https://console.aws.amazon.com/lambda/home e clique em Criar uma função lambda

Passo 2

Clique em Função em branco (personalizada)

etapa 3

Clique na caixa vazia (com traços) e selecione S3 no combo

Passo 4

Selecione seu Balde (o mesmo da distribuição do CloudFront)

Etapa 5

Defina um tipo de evento para "Objeto criado (todos)"

Etapa 6

Defina Prefixo e Sufixo ou deixe em branco se não souber o que é.

Etapa 7

Marque a caixa de seleção Ativar gatilho e clique em Avançar

Etapa 8

Nomeie sua função (algo como: YourBucketNameS3ToCloudFrontOnCreateAll )

Etapa 9

Selecione Python 2.7 (ou posterior) como Runtime

Etapa 10

Cole o seguinte código em vez do código python padrão:

from __future__ import print_function

import boto3
import time

def lambda_handler(event, context):
    for items in event["Records"]:
        path = "/" + items["s3"]["object"]["key"]
        print(path)
        client = boto3.client('cloudfront')
        invalidation = client.create_invalidation(DistributionId='_YOUR_DISTRIBUTION_ID_',
            InvalidationBatch={
            'Paths': {
            'Quantity': 1,
            'Items': [path]
            },
            'CallerReference': str(time.time())
            })

Etapa 11

Abra https://console.aws.amazon.com/cloudfront/home em uma nova guia do navegador e copie seu ID de distribuição do CloudFront para uso na próxima etapa.

Etapa 12

Retorne à guia lambda e cole seu ID de distribuição em vez de _YOUR_DISTRIBUTION_ID_ no código Python. Mantenha as aspas circundantes.

Etapa 13

Manipulador de conjunto : lambda_function.lambda_handler

Etapa 14

Clique na caixa de combinação de funções e selecione Criar uma função personalizada . Uma nova guia no navegador será aberta.

Etapa 15

Clique em exibir documento de política , clique em editar , clique em OK e substitua a definição de função pelo seguinte (como está):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
          "cloudfront:CreateInvalidation"
      ],
      "Resource": [
          "*"
      ]
    }
  ]
}

Etapa 16

Clique em permitir . Isso o levará a uma lambda. Verifique novamente se o nome da função que você acabou de criar está selecionado na caixa de combinação Existente da função .

Etapa 17

Defina Memória (MB) para 128 e Timeout para 5 seg.

Etapa 18

Clique em Avançar e , em seguida, clique em Criar função

Etapa 19

Você está pronto para ir! A partir de agora, sempre que você carregar / recarregar qualquer arquivo no S3, ele será avaliado em todos os locais do CloudFront Edge.

PS - Ao fazer o teste, verifique se o navegador está carregando imagens do CloudFront, não do cache local.

PSS - Observe que apenas as primeiras 1000 invalidações de arquivo por mês são gratuitas, e cada invalidação acima do limite custa US $ 0,005. Também podem ser aplicadas cobranças adicionais pela função Lambda, mas é extremamente barato.


Apenas o último item de cada lote S3?
Phil

@ Phil O código é escrito dessa maneira, para que apenas os arquivos recém-enviados sejam invalidados, e não um intervalo inteiro. No caso de upload de vários arquivos, cada um deles será invalidado separadamente. Funciona como um encanto.
Kainax

A única razão pela qual esse código funciona conforme o esperado é porque o S3 atualmente inclui apenas um item por notificação, ou seja, o comprimento da matriz é sempre feliz 1 e, consequentemente, mesmo se você fizer o upload de vários arquivos de uma só vez, você recebe uma notificação totalmente nova por arquivo. De qualquer forma, você não recebe uma notificação para todo o intervalo. No entanto, esse código, como está escrito, não está pronto, caso a AWS mude esse comportamento. Muito mais seguro escrever código que lida com toda a matriz, independentemente do comprimento, que foi o meu ponto original (infelizmente não atendido).
Phil

A única razão pela qual a AWS adiciona manipuladores de eventos é ... bem ... lidar com eventos. Por que eles a removeriam? Não importa como um novo arquivo foi adicionado, ele deve disparar um evento para a API e é assim que funciona agora e continuará funcionando. Estou usando a AWS há 4 anos e eles nunca mudaram algo, então o código anterior parou de funcionar. Mesmo que mudem a API, mudam para uma nova versão autônoma, mas todas as versões anteriores sempre são suportadas. Nesse caso específico, simplesmente não acredito que o evento de arquivo pessoal seja removido. Provavelmente já é usado por milhões de projetos em todo o mundo.
Kainax

Caso eu não entenda seu primeiro comentário e você queira dizer que 'Quantidade': 1 adicionará apenas o último item - existe um loop FOR para cada item da matriz.
Kainax

9

Explorador de balde tem uma interface do usuário que facilita bastante isso agora. Aqui está como:

Clique com o botão direito do mouse no seu balde. Selecione "Gerenciar distribuições".
Clique com o botão direito na sua distribuição. Selecione "Obter lista de invalidação do Cloudfront". Em seguida, selecione "Criar" para criar uma nova lista de invalidação. Selecione os arquivos para invalidar e clique em "Invalidar". Aguarde de 5 a 15 minutos.


4

Se você instalou o boto (que não é apenas para python, mas também instala um monte de utilitários de linha de comando úteis), ele oferece um utilitário de linha de comando especificamente chamado cfadminou 'cloud front admin' que oferece a seguinte funcionalidade:

Usage: cfadmin [command]
cmd - Print help message, optionally about a specific function
help - Print help message, optionally about a specific function
invalidate - Create a cloudfront invalidation request
ls - List all distributions and streaming distributions

Você invalida as coisas executando:

$sam# cfadmin invalidate <distribution> <path>

Na verdade, o cfadmin é uma ferramenta muito útil, especialmente se você precisar redefinir o cache do CloudFront a partir do script de implantação console \ bash \ travis ci. BTW aqui é o pós como repor \ invalidate CoudFront de cache durante a implantação Travis a AWS
Mikita Manko

3

Apenas postando para informar quem visita esta página (primeiro resultado em 'Cloudfront File Refresh') que existe um invalidador on-line fácil de usar e disponível, disponível no swook.net

Este novo invalidador é:

  • Totalmente online (sem instalação)
  • Disponível 24x7 (hospedado pelo Google) e não requer associações.
  • Há suporte ao histórico e verificação de caminho para permitir que você invalide seus arquivos com facilidade. (Geralmente, com apenas alguns cliques depois de invalidar pela primeira vez!)
  • Também é muito seguro, como você descobrirá ao ler seu post de lançamento .

Divulgação completa: Eu fiz isso. Diverta-se!


2
desculpe, mas mesmo "você diz" as credenciais não armazenadas ou ocultas ... nunca se deve dar sua credencial a terceiros. Pode ser implementar uma autenticação amazon remota ou algo assim?
precisa saber é

Você deve colocar isso para trás https no mínimo.
Oliver Tynes

As ferramentas online geralmente são boas, mas fornecer credenciais para ferramentas de terceiros será uma preocupação de segurança válida. Eu sugeriria usar o console da web oficial ou a ferramenta oficial da CLI .
RayLuo 22/01

2
Para a segurança dos outros, estou votando negativamente nesta resposta. Você nunca deve pedir às pessoas para as suas credenciais
Moataz Elmasry

3

Uma maneira muito fácil de fazer isso é a versão do FOLDER.

Portanto, se seus arquivos estáticos são centenas, por exemplo, basta colocá-los em uma pasta chamada por ano + versão.

por exemplo, eu uso uma pasta chamada 2014_v1, onde por dentro tenho todos os meus arquivos estáticos ...

Então, dentro do meu HTML, eu sempre coloco a referência na pasta. (é claro que eu tenho um PHP para incluir onde defini o nome da pasta.) Então, alterando um arquivo, ele realmente muda em todos os meus arquivos PHP.

Se eu quiser uma atualização completa, simplesmente renomeio a pasta para 2014_v2 no meu código-fonte e altero dentro do php include para 2014_v2

todo o HTML muda automaticamente e solicita o novo caminho, cache MISS na nuvem e solicita-o à fonte.

Exemplo: SOURCE.mydomain.com é minha fonte, cloudfront.mydomain.com é CNAME para distribuição em nuvem.

Então, o PHP chamou esse arquivo cloudfront.mydomain.com/2014_v1/javascript.js e quando eu quero uma atualização completa, simplesmente renomeio a pasta na fonte para "2014_v2" e altero o PHP incluindo definindo a pasta como "2014_v2" .

Assim, não há atraso para invalidação e SEM CUSTO!

Este é o meu primeiro post no stackoverflow, espero que tenha feito bem!



2

Em rubi, usando a gema de nevoeiro

AWS_ACCESS_KEY = ENV['AWS_ACCESS_KEY_ID']
AWS_SECRET_KEY = ENV['AWS_SECRET_ACCESS_KEY']
AWS_DISTRIBUTION_ID = ENV['AWS_DISTRIBUTION_ID']

conn = Fog::CDN.new(
    :provider => 'AWS',
    :aws_access_key_id => AWS_ACCESS_KEY,
    :aws_secret_access_key => AWS_SECRET_KEY
)

images = ['/path/to/image1.jpg', '/path/to/another/image2.jpg']

conn.post_invalidation AWS_DISTRIBUTION_ID, images

mesmo na invalidação, ainda leva de 5 a 10 minutos para a invalidação processar e atualizar em todos os servidores de borda da amazon


Você acabou de salvar minha vida!
Fábio Batista

2

invalidação atual do suporte da CLI da AWS no modo de visualização. Execute o seguinte no seu console uma vez:

aws configure set preview.cloudfront true

Eu implanto meu projeto da web usando o npm. Eu tenho os seguintes scripts no meu package.json:

{
    "build.prod": "ng build --prod --aot",
    "aws.deploy": "aws s3 sync dist/ s3://www.mywebsite.com --delete --region us-east-1",
    "aws.invalidate": "aws cloudfront create-invalidation --distribution-id [MY_DISTRIBUTION_ID] --paths /",
    "deploy": "npm run build.prod && npm run aws.deploy && npm run aws.invalidate"
}

Com os scripts acima, você pode implantar seu site com:

npm run deploy

1
Acho que você precisa do asterisco no seu comando 'aws.invalidate', mude --paths /para --paths /*. meu também era como a sua e não invalida a distribuição ...
Herald Smit

1

Se você estiver usando a AWS, provavelmente também usará sua ferramenta CLI oficial (mais cedo ou mais tarde). AWS CLI versão 1.9.12 ou superior suporta a invalidação de uma lista de nomes de arquivos.

Divulgação completa: Eu fiz isso. Diverta-se!


Link morto - leva a um 404 :( e não consigo atualizá-lo porque a versão 1.9.12 está ausente nas notas de versão ( aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli )
SlyDave

Cara, essa foi uma versão lançada quase 3 anos atrás. Experimente a versão mais recente e o recurso provavelmente ainda está lá. (Divulgação completa: eu não trabalho no AWS CLI mais.)
RayLuo

oh, eu sei, apenas achei estranho que, de todas as notas de lançamento, apenas 1.9.12 não exista: D (que é o que eu estava falando sobre não poder atualizar o link). O comentário foi mais uma dica para quem encontrou o caminho até aqui, como eu fiz e precisava encontrar as notas de lançamento para a AWS CLI. nenhum dano, nenhuma falta.
SlyDave 17/01/19

0

Vá para o CloudFront.

Clique no seu ID / Distribuições.

Clique em Invalidações.

Clique em criar Invalidação.

Na caixa de exemplo gigante, digite * e clique em invalidar

Feito

insira a descrição da imagem aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.