Houve alguns problemas com relação ao comando sync
, particularmente no caso de sincronização do S3 ( s3 -> local
). Eu gostaria de tentar resumir os problemas conhecidos, bem como algumas propostas de opções possíveis, e dar às pessoas a oportunidade de compartilhar qualquer feedback que possam ter.
O comportamento de sincronização pretende ser um eficiente cp
; copie apenas os arquivos da origem para o destino que sejam diferentes. Para fazer isso, precisamos ser capazes de determinar se um arquivo em s3 / local é ou não diferente. Para fazer isso, usamos dois valores:
stat
'ing o arquivo localmente e da chave Size
em uma resposta ListObjects
)LastModified
em uma resposta ListObjects
)Como um aparte, usamos a operação ListObjects
porque obtemos até 1000 objetos retornados em uma única chamada. Isso significa que estamos limitados às informações que vêm de uma resposta ListObjects
que é LastModified, ETag, StorageClass, Key, Owner, Size
.
Agora, dados o tamanho do arquivo dos arquivos remotos e locais e os tempos da última modificação, tentamos determinar se o arquivo é diferente. O tamanho do arquivo é fácil, se os tamanhos dos arquivos forem diferentes, então sabemos que os arquivos são diferentes e precisamos sincronizar o arquivo. No entanto, a hora da última modificação é mais interessante. Embora o mtime do arquivo local seja um mtime verdadeiro, o LastModified
time de ListObjects
é realmente o horário em que o objeto foi carregado. Então imagine este cenário:
aws s3 sync local/ s3://bucket/
sleep 10
aws s3 sync s3://bucket local/
Após o primeiro comando de sincronização ( local->s3
), os arquivos locais terão um mtime de 0 e o conteúdo em s3 terá um tempo de LastModified de 10 (usando deslocamentos relativos). Quando executamos o segundo comando aws s3 sync, que está sincronizando de s3 para local, primeiro faremos a verificação do tamanho do arquivo. Neste caso, os tamanhos dos arquivos são os mesmos, portanto, examinamos as últimas verificações de hora modificadas. Nesse caso, eles são diferentes (local == 0, s3 == 10). Se estivéssemos fazendo uma comparação de igualdade estrita, porque os tempos da última modificação são diferentes, sincronizaríamos desnecessariamente os arquivos de s3 para local. Portanto, podemos dizer que se os tamanhos dos arquivos forem iguais e o tempo da última modificação em s3 for maior (mais recente) do que o arquivo local, então não sincronizamos. Este é o comportamento atual.
No entanto, isso criará um problema se o arquivo remoto for atualizado fora da banda (por meio do console ou algum outro SDK) e o tamanho permanecer o mesmo. Se executarmos aws s3 sync s3://bucket local/
, não sincronizaremos o arquivo remoto, embora devamos fazer isso.
Abaixo estão as soluções potenciais.
aws s3 sync local s3://bucket && aws s3 s3://bucket local
sincronizar arquivos desnecessariamente. No entanto, quando baixamos um arquivo, definimos a hora do arquivo para corresponder à hora de LastModified, de forma que se você executasse aws s3 sync s3://bucket local
_novamente_, não sincronizaria nenhum arquivo.Se houver alguma outra solução potencial que eu deixei de fora, entre em contato.
Em vez de armazenar o cache de ETags fornecidas pelo servidor, a ETag pode ser calculada no lado do cliente? Então seria quase como fazer verificações md5, mas usando dados disponíveis na resposta ListObjects. Contanto que o algoritmo ETag não dependa do estado do lado do servidor ...
Você achou :-)
- Seb
Em 17 de janeiro de 2014, às 16:26, Jeff Waugh < notificaçõ[email protected] [email protected] > escreveu:
Ah: https://forums.aws.amazon.com/thread.jspa?messageID=203510&state=hashArgs%23203510
-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/aws/aws-cli/issues/599#issuecomment -32668382.
Amazon EU Societe a responsabilite limitee, 5 Rue Plaetis, L - 2338 Luxembourg, RCS Luxembourg n B 101818, capital social: EUR 37.500. Autorização d estabelecimento en qualite de commercante n 104408.
Sim, não podemos calcular com segurança a ETag para uploads de várias partes, caso contrário, seria uma ótima solução.
Você poderia adicionar um novo sinalizador (ou 2) para o comportamento do tempo? Talvez --check-timestamps
para a opção 1 e --update-local-timestamps
para a opção 2. Dessa forma, o usuário pode especificar uma verificação mais robusta para alterações e aceitar as consequências ao mesmo tempo.
Sim, acho que adicionar sinalizadores para as opções 1 e 2 seria uma abordagem razoável. Uma preocupação potencial é que o comportamento padrão (sem opções especificadas) tem casos em que sync
não se comporta como seria de se esperar, mas não tenho certeza se alterar o comportamento padrão para qualquer uma dessas opções é uma coisa boa aqui, dadas as possíveis compensações que estaríamos fazendo.
@jamesls Estou usando o comando sync para implantar um site estático gerado.
Com a versão atual, estou reenviando todos os arquivos a cada sincronização porque o mtime muda quando o site é regenerado, mesmo que o conteúdo não seja alterado.
Para meus propósitos (e imagino um bom número de outras pessoas usando essa ferramenta fabulosa para fazer upload de seus sites estáticos), sincronizar via ETag, conforme sugerido em # 575, seria o mais incrível, mas, dada a minha leitura desse problema, não parece ser uma opção.
Exceto que, para fins de sites estáticos, uma verificação apenas de comprimento (embora talvez um pouco perigosa) funcionaria.
Outra opção seria desativar os uploads de várias partes e usar # 575 - veríamos uma grande economia imediatamente.
Eu encontrei o problema inverso. Eu mudei um arquivo no S3 que tem o mesmo tamanho, mas o carimbo de data / hora mais recente e a sincronização do S3 não o puxa para baixo
aws s3 sync s3: // bucket / path / dir
Olhando os dados no S3 ... acho que é por causa de problemas de fuso horário.
As propriedades mostram um tempo de
Última modificação: 21/02/2014 10:50:33 AM
Mas os cabeçalhos HTTP mostram
Última modificação: Sex, 21 de fevereiro de 2014 15:50:33 GMT
Observe que a propriedade Última modificação não mostra o fuso horário?
Como meu comando s3 sync está sendo executado em um servidor diferente com fuso horário diferente daquele em que coloquei o arquivo, ele pensa que o arquivo está no passado e não o puxa.
Tive que mudar para s3 cp para ter certeza de que receberia todos os arquivos
Acho que, como primeiro passo, devemos implementar o argumento --size-only
. Não resolve o problema no caso geral, mas para certos cenários ajudará e é fácil de entender / explicar, particularmente o caso de uso referenciado acima com sites estáticos sendo sincronizados para s3.
Acho que a sincronização deve ter uma opção de sempre sincronizar os arquivos se o arquivo a ser sincronizado for mais recente que o destino. Estamos sincronizando arquivos da máquina A para a S3 e depois da S3 para a máquina B. Se o tamanho de um arquivo não mudar (mas o conteúdo, sim), este arquivo não alcançará a máquina B. Este comportamento é interrompido. Não me importo se sincronizo muitos arquivos, mas os arquivos alterados nunca devem ser deixados de fora.
De acordo com meu post anterior, "newer" precisa levar em consideração o fuso horário também.
Atualmente não é assim se você enviar um arquivo para o S3 de um fuso horário e, em seguida, sincronizar de outro, ele não detectará corretamente que o arquivo é mais recente.
@jamesls Além do argumento --size-only, eu estaria interessado em usar um argumento --name-only. Ou seja, não verifique o tamanho do arquivo ou a hora da última modificação. Simplesmente copie os arquivos existentes na origem, mas não no destino. Em nosso cenário, sincronizamos do s3 para o local e, depois de fazer o download de um arquivo, não esperamos que ele mude no s3. Se essa opção resultar em menos operações em nosso sistema de arquivos local (nfs), pode haver uma melhoria de desempenho.
@jamesls Deve --size-only
et al estar disponível em 1.3.6?
Meu representante de suporte da AWS para o caso 186692581 diz que encaminhou minha sugestão para você.
Pensei em postar aqui de qualquer maneira para comentar:
Acho que uma solução simples seria introduzir um fator de difusão.
Se normalmente não demorasse mais de 5 minutos para a cópia local -> S3,
em seguida, use um fator de difusão de 10 minutos nas comparações de tempo subsequentes.
Trate os tempos relativos dentro de 10 minutos como iguais.
Se o tempo S3 for mais de 10 minutos mais recente, sincronize de S3 -> local.
Talvez adicione "--fuzz = 10m" como uma opção.
@jamesls @ adamsb6
Não seria https://github.com/aws/aws-cli/pull/575 uma boa opção pelo menos para arquivos carregados de uma única parte?
Se você verificar o formato ETAG do arquivo no S3, poderá diferir se o upload do arquivo foi simples ("ETAG =" MD5 Hash ") ou multiparte (ETAG =" MD5 Hash "-" Número de partes "). pode comparar todos os arquivos MD5 locais com seu ETAG e, no caso de um arquivo ter sido carregado como multiparte, você pode ignorá-lo.
Temos um cliente que tem muitos clipes de vídeo em certas pastas em um S3 Bucket, que são sincronizados com instâncias ec2 em todas as regiões da AWS. Todos os arquivos são carregados como parte única.
No momento, temos um problema devido ao s3cmd, que em alguns casos alguns arquivos estão corrompidos. Se fizermos uma sincronização completa novamente, teremos 14 TB de tráfego que serão cobrados.
Nosso problema: Os arquivos corrompidos têm exatamente o mesmo tamanho do arquivo original no s3 e, devido a carimbos de data / hora incorretos no s3cmd, não podemos usar as opções mencionadas acima. Nesse caso, --compare-on-etag
seria uma ótima solução para evitar a sincronização de todos os arquivos novamente.
Mesmo para a sincronização normal, a opção --compare-on-etag
seria ótima, se você tiver apenas uma parte dos arquivos carregados, porque o aws s3 sync sincronizará apenas os arquivos alterados.
Acabei de passar a maior parte de 3 horas tentando encontrar as permissões mínimas necessárias para usar o comando sync. O erro que estava recebendo era:
A client error (AccessDenied) occurred when calling the ListObjects operation: Access Denied
Quando realmente o erro deveria ter sido:
A client error (AccessDenied) occurred when calling the ListBucket operation: Access Denied
Um item de ajuda que mostra uma tabela com as permissões mínimas para cada comando seria _muito_ útil.
Editar: Para esclarecer, adicione o comportamento do tipo rsync ao "aws s3 sync". Parece que o problema relatado não é exatamente o que eu inicialmente entendi.
Como o último AWS-CLI-bundle.zip não contém a correção implementada acima, fiz um clone do git. Posso ver o novo código em uma pasta chamada "personalizações". No entanto, não está claro para mim como criar um comando aws-cli usando esse código. Eu tenho que executar make-bundle?
Sim. Eu uso as seguintes etapas para instalá-lo em novos servidores (Ubuntu):
git clone https://github.com/andrew512/aws-cli.git
cd aws-cli
pip install -r requirements.txt
sudo python setup.py install
OK.
Eu vejo o código modificado na versão 1.3.18.
Ele aceita meu parâmetro --exact-timestamps.
Achei que o pacote de download mais recente que eu tinha instalado anteriormente era 1.3.21.
O controle de versão confiável realmente só se aplica aos lançamentos oficiais da AWS. Eu fiz um bifurcação do repositório em 1.3.18, então essa é a versão que ele reportará, mas já está algumas versões desatualizadas, com 1.3.22 sendo a mais recente neste momento. Esperançosamente, a AWS aceita a solicitação pull e inclui o recurso em versões oficiais futuras. Tem sido muito valioso para nós e ajuda a resolver um comportamento padrão bastante questionável.
@ andrew512 Desculpe pela demora. Acho que o PR que você enviou é uma boa ideia e é muito útil ter feedback do cliente sobre quais aws s3 sync
mudanças funcionam para eles e quais não funcionam. Vou dar uma olhada em breve.
Eu acho ... para aqueles de nós que não se importam com as solicitações de cabeçalho, a comparação no MD5 deve ser uma opção. Eu (em segundo lugar) votaria no --compare-on-etag porque atualizo apenas de um servidor para o S3 - e, portanto, um repositório MD5 local não é um problema para mim. MAS eu definitivamente acho que precisamos ter algo. Do jeito que está, NUNCA tenho certeza de que meus repositórios local e S3 são iguais. Onde estamos no status de algo assim?
@janngobble +1
Nosso caso de uso é que temos esses arquivos em um repositório git e eles são arquivos de configuração, portanto, nem a data de modificação nem o tamanho do arquivo realmente funcionam, então gostaríamos de ver uma opção md5 real para aqueles que podem lidar com as implicações de desempenho.
Isso ocorre porque quando você faz check-out de um repositório git, a data de modificação do arquivo é quando o arquivo é gravado. Além disso, o tamanho do arquivo não funciona porque a alteração do arquivo pode ser algo como:
foo="bar"
para
foo="baz"
para que o tamanho do arquivo não seja alterado.
@jamesls Por que você não pode usar o método aqui para calcular o md5 para uploads de várias partes? Funcionou para mim
Olá,
Eu também tenho esse problema bem descrito com foo = "bar" / foo = "baz".
Eu uso o balde S3 para a implantação do meu aplicativo e todos os servidores sincronizam a partir do S3 quando uma implantação é concluída. Tive poucas vezes o problema de um operador> = alterado para <= em um arquivo não sincronizado devido a esse bug e para mim o comando de sincronização não é muito confiável devido a esse bug. O tamanho é o mesmo, mas o conteúdo é diferente, o arquivo deve ser sincronizado.
Não tenho nenhum conselho específico sobre como fazer isso, desculpe por isso, mas estou apenas expondo meu caso de uso :)
Vai entender, eu me deparei com o mesmo problema durante o desenvolvimento do node-ftpsync. Presumi que a AWS teria alguma solução mágica para resolver isso.
Provavelmente é uma boa ideia 'difundi-lo' (ou seja, arredondando para os 10 minutos mais próximos), como sugeriu @ngbranitsky . Fazer isso em node.js é uma dor, mas em python deve ser tão fácil quanto truncar os últimos bits usando um AND bit a bit.
Como a AWS não tem esse problema, você também deve considerar como o mtime é usado no host local. Ao alterar o valor mtime em cada sincronização, você vai acionar um evento de atualização em massa se houver transpiladores assistindo a esses arquivos? Existem outros armazenamentos de metadados que usam mtime como uma métrica para medir as alterações de arquivo?
Sei que essa não é uma solução geral, mas seria muito bom ver o seguinte comportamento opcional para sincronização, imo. É como se não fosse. 4 no OP, modificado apenas para melhor desempenho.
O caso de uso aqui é sincronizar blocos de mapas da web, dos quais <1% normalmente mudam diariamente. A exceção é quando ocorrem exclusões nos dados de origem que alteram a cobertura espacial dos blocos, o que exige que todo o conjunto de blocos do mapa seja regenerado.
O problema é o grande volume envolvido. Vejo a discussão sobre grandes uploads de várias partes como um caso de uso, mas não sobre muitos arquivos pequenos individuais. Quantos? Temos ~ 2 milhões atualmente, mas pode ficar muito pior. Por exemplo, no nível de zoom 16, o mundo tem 1 << 16 x 1 << 16, ou 65536 x 65536 blocos ou ~ 4b.
As opções atuais são:
Eu poderia escrever código C sem muita dificuldade que iria percorrer um caminho de diretório, atualizar um banco de dados de cache sqlite3 local e construir a fila de set / upload potencialmente alterada. Infelizmente, não tenho experiência em Python e não posso enviar isso como uma solicitação pull para um comportamento de sincronização opcional.
Eu não sei o quão comum é o caso de uso "muitos arquivos pequenos, garantido nenhuma mudança fora de banda, local-> servidor apenas".
Acho pouco intuitivo e perigoso que a sincronização trate uma diferença nos últimos tempos modificados como um motivo para atualizar, mesmo se um arquivo mais recente na origem estiver substituindo um mais antigo no destino. Esse comportamento estranho deve ser documentado.
Também relacionado a # 404.
Que tal adicionar um único sinalizador --sync-if
autodocumentado em vez do número crescente de opções não autodocumentáveis? (por exemplo, --size-only
, --exact-timestamps
. Posso aplicar esses dois ao mesmo tempo? Por que tenho que ler a documentação / experimentá-los para descobrir isso?).
O --sync-if
poderia ter uma lista de opções:
--sync-if newer-timestamp,different-md5,different-timestamp,different-size,deleted,...
O usuário pode especificar um ou mais (lista separada por vírgulas) e se o arquivo atender a algum dos critérios, será atualizado (carregado / excluído) no destino.
Isso esclareceria muito o comportamento, especialmente se você mencionou na documentação que o comportamento padrão é: --sync-if different-timestamp,different-size
.
Lendo este problema, não consigo descobrir se esse comportamento de sincronização ainda foi corrigido.
Eu quero algo que funcione tão simplesmente quanto rsync -avz
para sincronizar minha compilação local com as do servidor.
Eu estava usando aws s3 sync
, mas porque tenho um arquivo que é grande (um arquivo de ajuda que é um filme) e minha etapa de compilação cria todos os arquivos do novo, copia todos os arquivos sempre e é desnecessariamente lento para atualizar o site.
Então comecei a usar --size-only
para acelerar. Infelizmente, isso me mordeu na bunda recentemente. Eu havia renomeado um arquivo e a etapa de construção inclui uma lista de arquivos no arquivo service-worker.js para que o sw saiba o que armazenar em cache. Infelizmente, os nomes dos arquivos novos e antigos tinham o mesmo comprimento, então ele não atualizou o arquivo service-worker.js e continuou dando um 404 para o nome do arquivo antigo. Levei um bom tempo para descobrir o que estava acontecendo.
Parece que este é um problema resolvido em outros ambientes - ou seja, por rsync - embora, tbh, eu provavelmente seja um pouco ignorante dos desafios apresentados em fazer algo assim no S3. Enfim, tendo sido mordido por isso recentemente, estou procurando outros clientes, mas eles parecem ter dependências que não estou interessado em adotar apenas para essa funcionalidade.
Seria ótimo ter uma opção de sincronização etag. Eu sei que existem cenários em que ele falha, mas para mim seria muito valioso.
Bom Dia!
Estamos encerrando esse problema aqui no GitHub, como parte de nossa migração para o UserVoice para solicitações de recursos envolvendo o AWS CLI.
Isso nos permitirá fornecer os recursos mais importantes para você, tornando mais fácil pesquisar e mostrar suporte para os recursos que você mais gosta, sem diluir a conversa com relatórios de bug.
Como uma cartilha rápida do UserVoice (se ainda não for familiar): depois que uma ideia é postada, as pessoas podem votar nas ideias e a equipe do produto responderá diretamente às sugestões mais populares.
Importamos solicitações de recursos existentes do GitHub - Pesquise este problema lá!
E não se preocupe, esse problema ainda existirá no GitHub para o bem da posteridade. Como é uma importação somente de texto da postagem original para o UserVoice, ainda teremos em mente os comentários e a discussão que já existem aqui sobre o problema do GitHub.
O GitHub continuará sendo o canal para relatar bugs.
Mais uma vez, esse problema agora pode ser encontrado pesquisando o título em: https://aws.uservoice.com/forums/598381-aws-command-line-interface
- A equipe de SDKs e ferramentas da AWS
Esta entrada pode ser encontrada especificamente no UserVoice em: https://aws.uservoice.com/forums/598381-aws-command-line-interface/suggestions/33168808-aws-s3-sync-issues
Evitando problemas com o github? Isso parece um erro ...
Concordou. Parece mais o método que a Microsoft usa para julgar a importância / impacto dos problemas, mas acho bastante irritante.
Com base no feedback da comunidade, decidimos retornar as solicitações de recursos para problemas do GitHub.
Empurrando isso de volta!
Para o topo!
a comparação do md5 seria ótimo, eu também acrescentaria que seria útil gerar o md5 no upload ou download. isso poderia ser armazenado em nosso próprio banco de dados e ajudaria a determinar se a sincronização é necessária por meio de nosso banco de dados para limitar as solicitações.
@jamesls Você poderia comentar este assunto, por favor?
https://github.com/aws/aws-cli/issues/4460
Comentários muito úteis
Empurrando isso de volta!