Executando um cron job no Elastic Beanstalk

Então eu tenho uma funcionalidade em um aplicativo Django Elastic Beanstalk que funciona assim:

  • Baixe um arquivo
  • Analise o arquivo, execute algumas chamadas para a API com os dados do arquivo
  • Atualize o database da instância do EB com os novos dados

Em instâncias de teste em que acabei de configurar um cron job local. Acabei de chamar o wget em uma URL específica do meu aplicativo Django e ele executará o comando.

Meu problema é como lidar com isso em um aplicativo Elastic Beanstalk multi-instanciado. Apenas uma instância do meu aplicativo EB deve executar este comando. Eu quero evitar condições de corrida no database e chamadas redundantes para APIs externas de várias instâncias. ou seja, apenas uma instância deve estar gravando no database.

No entanto, pesquisando ao redor mostra a criação de tarefas cron é inábil, especialmente se o seu novo para EB como eu sou. O método de sondagem mais promissor parece ser o método cron.yaml , mas parece não haver um exemplo de configuração de um ambiente de trabalho do cron em qualquer lugar da web a partir do que eu possa ver.

Meu entendimento é:

  • Você inclui um arquivo cron.yaml na raiz do seu projeto EB.
  • Implantar o projeto
  • As tarefas agendadas são configuradas automaticamente em um ambiente de trabalho (?).
  • O comando que você definiu é executado no (s) horário (s) especificado (s).

Minha pergunta é como você garante que apenas uma instância execute esse comando? Eu tenho a idéia certa sobre como o cron.yaml funciona ou há algo que me falta?

Apenas uma instância executará o comando porque a tarefa cron não é executada em um daemon do cron por si.

Existem alguns conceitos que podem ajudá-lo a aumentar rapidamente a mentalidade Elastic Beanstalk da Amazon.

  • Um ambiente de pé de feijão elástico deve eleger uma instância de líder da qual só deve haver um (e deve ser uma instância saudável, etc).
  • Um ambiente de trabalho aloca o trabalho por meio de uma fila SQS (Simple Queue Service).
  • Uma vez que uma mensagem tenha sido lida da fila, ela é considerada ’em vôo’ até que o trabalhador retorne 200 ou a solicitação expire / falhe. No primeiro cenário, a mensagem é excluída e, no último cenário, ela entra novamente na fila. (As políticas de redenção podem determinar quantas vezes uma mensagem pode falhar antes de ser enviada para a fila de devoluções)
  • Em vôo, as mensagens não podem ser lidas novamente (a menos que sejam retornadas).

Uma mensagem na fila é capturada apenas uma vez por uma das instâncias no ambiente de trabalho por vez.

Agora, o arquivo cron.yaml apenas informa ao líder para criar uma mensagem na fila com atributos especiais, nos horários especificados no planejamento. Quando ele encontra essa mensagem, ela é enviada para uma instância apenas como uma solicitação POST para o URL especificado.

Quando eu uso o Django em um ambiente de trabalho eu crio um aplicativo cron com views que mapeiam a ação que eu quero. Por exemplo, se eu quisesse pesquisar periodicamente um ponto de extremidade do Facebook, eu poderia ter um caminho /cron/facebook/poll/ que chama uma function poll_facebook() em views.py

Dessa forma, se eu tiver um cron.yaml da seguinte maneira, ele pesquisará o Facebook uma vez a cada hora:

 version: 1 cron: - name: "pollfacebook" url: "/cron/facebook/poll/" schedule: "0 * * * *"