Como converter tarefas cron do Linux para “o jeito Amazon”?


112

Para o bem ou para o mal, migramos todo o nosso aplicativo da web LAMP de máquinas dedicadas para a nuvem (máquinas Amazon EC2). Está indo muito bem até agora, mas a forma como fazemos crons está abaixo do ideal. Tenho uma pergunta específica da Amazon sobre como gerenciar melhor os cron jobs na nuvem usando "o jeito da Amazon".

O problema : temos vários servidores da web e precisamos executar crons para jobs em lote, como criar feeds RSS, disparar e-mails, muitas coisas diferentes, na verdade. MAS os cron jobs precisam ser executados apenas em uma máquina porque eles geralmente gravam no banco de dados e, portanto, duplicariam os resultados se executados em várias máquinas.

Até agora, designamos um dos servidores web como o "servidor web mestre" e ele tem algumas tarefas "especiais" que os outros servidores web não têm. A desvantagem da computação em nuvem é a confiabilidade - não queremos um "servidor web mestre" porque é um ponto único de falha. Queremos que todos sejam idênticos e sejam capazes de aumentar e diminuir a escala sem nos lembrar de não retirar o servidor da web mestre do cluster.

Como podemos redesenhar nosso aplicativo para converter tarefas cron do Linux em itens de trabalho transitórios que não têm um único ponto de falha?

Minhas ideias até agora:

  • Tenha uma máquina dedicada apenas ao funcionamento de crons. Isso seria um pouco mais gerenciável, mas ainda seria um ponto único de falha e desperdiçaria algum dinheiro tendo uma instância extra.
  • Alguns trabalhos podem ser movidos de crons do Linux para eventos do MySQL, no entanto, não sou um grande fã dessa ideia, pois não quero colocar a lógica do aplicativo na camada do banco de dados.
  • Talvez possamos executar todos os crons em todas as máquinas, mas mudar nossos scripts cron para que todos eles comecem com um pouco de lógica que implementa um mecanismo de bloqueio de forma que apenas um servidor realmente execute uma ação e os outros simplesmente pulem. Não sou fã dessa ideia, pois parece potencialmente problemática e eu preferiria usar uma prática recomendada da Amazon em vez de lançar a nossa própria.
  • Estou imaginando uma situação em que os jobs são agendados em algum lugar, adicionados a uma fila e então os servidores da web podem ser cada um um trabalhador, que pode dizer "ei, vou pegar esse aqui". O Amazon Simple Workflow Service soa exatamente esse tipo de coisa, mas atualmente não sei muito sobre ele, portanto, quaisquer detalhes seriam úteis. Parece meio pesado para algo tão simples como um cron? É o serviço certo ou existe um serviço Amazon mais adequado?

Atualização: depois de fazer a pergunta, assisti ao seminário on-line do Amazon Simple Workflow Service no YouTube e notei às 34:40 ( http://www.youtube.com/watch?v=lBUQiek8Jqk#t=34m40s ) que vislumbrei um slide mencionando cron jobs como um aplicativo de amostra. Em sua página de documentação, " Amostras do AWS Flow Framework para Amazon SWF ", a Amazon afirma ter um código de amostra para crons:

... > Cron jobs Neste exemplo, um fluxo de trabalho de longa execução executa periodicamente uma atividade. É demonstrada a capacidade de continuar as execuções como novas execuções, de forma que uma execução possa ser executada por longos períodos de tempo. ...

Eu baixei o AWS SDK para Java ( http://aws.amazon.com/sdkforjava/ ) e com certeza enterrado em camadas ridículas de pastas há algum código java ( aws-java-sdk-1.3.6/samples/AwsFlowFramework/src/com/amazonaws/services/simpleworkflow/flow/examples/periodicworkflow).

O problema é que, para ser honesto, isso não ajuda muito, pois não é algo que posso digerir facilmente com meu conjunto de habilidades. A mesma amostra está faltando no SDK do PHP e não parece haver um tutorial que analise o processo. Então, basicamente, ainda estou procurando conselhos ou dicas.


Respostas:


38

Eu me inscrevi no suporte do Amazon Gold para fazer esta pergunta, esta foi a resposta:

Tom

Fiz uma pesquisa rápida com alguns de meus colegas e não consegui nada no cron, mas depois de dormir sobre ele percebi que a etapa importante pode estar limitada ao bloqueio. Procurei por "bloqueio de cron job distribuído" e encontrei uma referência ao Zookeeper, um projeto Apache.

http://zookeeper.apache.org/doc/r3.2.2/recipes.html

http://highscalability.com/blog/2010/3/22/7-secrets-to-successfully-scaling-with-scalr-on-amazon-by-se.html

Também vi referência ao uso de memcached ou um mecanismo de armazenamento em cache semelhante como uma forma de criar bloqueios com TTL. Desta forma, você define um sinalizador, com um TTL de 300 segundos e nenhum outro cron worker executará a tarefa. O bloqueio será automaticamente liberado depois que o TTL expirar. Isso é conceitualmente muito semelhante à opção SQS que discutimos ontem.

Veja também; O gordinho http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//archive/chubby-osdi06.pdf

Avise-me se isso ajudar e fique à vontade para fazer perguntas. Estamos cientes de que nossos serviços podem ser complexos e assustadores tanto para iniciantes quanto para desenvolvedores experientes. Estamos sempre dispostos a oferecer conselhos sobre arquitetura e melhores práticas.

Cumprimentos,

Ronan G. Amazon Web Services


13

Acho que este vídeo responde exatamente à sua pergunta - cronjobs da maneira aws (escalável e tolerante a falhas):

Usando Cron na nuvem com Amazon Simple Workflow

O vídeo descreve o serviço SWF usando o caso de uso específico de implementação de cronjobs.

A complexidade relativa da solução pode ser difícil de engolir se você estiver vindo direto de um crontab. Há um estudo de caso no final que me ajudou a entender o que essa complexidade extra compra para você. Eu sugeriria assistir ao estudo de caso e considerar seus requisitos de escalabilidade e tolerância a falhas para decidir se você deve migrar de sua solução crontab existente.


2
essa é uma ótima resposta, pois usa uma ferramenta bem suportada da AWS, e o SWF é um produto poderoso. A única desvantagem, imo, é que o SWF tem uma curva de aprendizado significativa e pode ser difícil de fazer coisas complicadas com ele. Pelo menos essa foi minha experiência com os tutoriais Java
Don Cheadle

11

Tenha cuidado ao usar SQS para cronjobs, pois eles não garantem que apenas "um trabalho seja visto por apenas uma máquina". Eles garantem que "pelo menos um" receberá a mensagem.

De: http://aws.amazon.com/sqs/faqs/#How_many_times_will_I_receive_each_message

P: Quantas vezes vou receber cada mensagem?

O Amazon SQS foi projetado para fornecer “pelo menos uma vez” entrega de todas as mensagens em suas filas. Embora na maioria das vezes cada mensagem seja entregue ao seu aplicativo exatamente uma vez, você deve projetar seu sistema de forma que o processamento de uma mensagem mais de uma vez não crie erros ou inconsistências.

Até agora, posso pensar sobre a solução onde você tem uma instância com a instância do Gearman Job Server instalada: http://gearman.org/ . Na mesma máquina, você configura tarefas cron que estão produzindo comandos para executar sua tarefa cronjob em segundo plano. Então um de seus servidores web (workers) começará a executar esta tarefa, garantindo que apenas um a realizará. Não importa quantos trabalhadores você tem (especialmente quando você está usando o dimensionamento automático).

Os problemas com esta solução são:

  • O servidor Gearman é um ponto único de falha, a menos que você o configure com armazenamento distribuído, por exemplo, usando memcached ou algum banco de dados
  • Em seguida, usando vários servidores Gearman, você deve selecionar um que crie tarefas por meio do cronjob, portanto, estamos de volta ao mesmo problema. Mas se você pode conviver com esse tipo de ponto único de falha, usar o Gearman parece uma solução muito boa. Principalmente porque você não precisa de grande instância para isso (micro instância no nosso caso é suficiente).

Bem, as mensagens permanecem no servidor após serem recebidas. Cabe ao desenvolvedor excluí-los posteriormente. Enquanto estão sendo processados, eles não podem ser acessados ​​por outro servidor.
Frederik Wordenskjold

2
@FrederikWordenskjold Incorreto, mesmo depois que uma mensagem foi enviada a um cliente, ela ainda pode ser enviada a outro, pois a replicação do estado SQS é assíncrona. Você pode até receber uma cópia de uma mensagem "depois" de ela ter sido excluída!
Chris Pitman

Esta resposta está desatualizada. Existem 2 tipos de filas agora. Use FIFO para obter o processamento exatamente uma vez: uma mensagem é entregue uma vez e permanece disponível até que um consumidor a processe e exclua. As duplicatas não são introduzidas na fila. aws.amazon.com/sqs/features
Lukas Liesis

10

A Amazon acaba de lançar novos recursos para o Elastic Beanstalk. Dos documentos :

O AWS Elastic Beanstalk oferece suporte a tarefas periódicas para
níveis de ambiente de trabalho em ambientes que executam uma configuração predefinida com uma pilha de solução que contém "v1.2.0" no nome do contêiner. "

Agora você pode criar um ambiente contendo um cron.yamlarquivo que configura tarefas de agendamento:

version: 1
cron:
- name: "backup-job"          # required - unique across all entries in this file
  url: "/backup"              # required - does not need to be unique
  schedule: "0 */12 * * *"    # required - does not need to be unique
- name: "audit"
  url: "/audit"
   schedule: "0 23 * * *"

Eu imagino que a segurança de executá-lo apenas uma vez em um ambiente com escalonamento automático é utilizada por meio da fila de mensagens (SQS). Quando o cron daemon dispara um evento, ele coloca essa chamada na fila SQS e a mensagem na fila é avaliada apenas uma vez. Os documentos dizem que a execução pode ser atrasada se o SQS tiver muitas mensagens para processar.


Você também poderia incluir algum conteúdo dos links?
Robert

6

Eu me deparei com essa pergunta pela terceira vez e pensei em ajudar. Já estamos enfrentando esse dilema há algum tempo. Eu ainda realmente sentir AWS está faltando uma característica aqui.

No nosso caso, depois de examinar as soluções possíveis, decidimos que tínhamos duas opções:

  • Configure um servidor cronjob que executa as tarefas que devem ser executadas apenas uma vez por vez, escalone-o automaticamente e certifique-se de que seja substituído quando certas estatísticas do CloudWatch não forem o que deveriam ser. Usamos cloud-initscripts para colocar os cronjobs em execução. Claro, isso vem com um tempo de inatividade, levando a cronjobs perdidos (ao executar certas tarefas a cada minuto, como fazemos).
  • Use a lógica que rcronusa. Claro, a mágica não está realmente em rcronsi mesma, está na lógica que você usa para detectar um nó com falha (que usamos keepalivedaqui) e "atualizar" outro nó para mestre.

Decidimos ir com a segunda opção, simplesmente porque é incrivelmente rápida e já tínhamos experiência com servidores da Web executando esses cronjobs (em nossa era pré-AWS).

Claro, esta solução é destinada especificamente para substituir a abordagem tradicional de cronjob de um nó, onde o tempo é o fator decisivo (por exemplo, "Eu quero que o trabalho A seja executado uma vez por dia às 5h" , ou como em nosso caso "Eu quero o trabalho B para executar uma vez a cada minuto " ). Se você usar cronjobs para acionar a lógica de processamento em lote, você realmente deve dar uma olhada em SQS. Não há dilema ativo-passivo, o que significa que você pode usar um único servidor ou uma força de trabalho inteira para processar sua fila. Eu também sugiro olhar SWFpara escalar sua força de trabalho (embora auto scalingpossa ser capaz de fazer o truque também na maioria dos casos).

Depender de outro terceiro era algo que queríamos evitar.




4

A maneira "Amazon" é para ser distribuída, o que significa que crons volumosos devem ser divididos em muitas tarefas menores e entregues às máquinas certas.

Usando a fila SQS com o tipo definido como FIFO, cole-os para garantir que cada trabalho seja executado por apenas uma máquina. Ele também tolera falhas, pois as filas serão armazenadas em buffer até que a máquina volte a girar.

Processamento FIFO exatamente uma vez : uma mensagem é entregue uma vez e permanece disponível até que um consumidor a processe e exclua. As duplicatas não são introduzidas na fila.

Considere também se você realmente precisa 'agrupar' essas operações. O que acontece se as atualizações de uma noite forem consideravelmente maiores do que o esperado? Mesmo com recursos dinâmicos, seu processamento pode ser atrasado ao esperar que máquinas suficientes girem. Em vez disso, armazene seus dados em SDB, notifique as máquinas sobre atualizações via SQS e crie seu feed RSS rapidamente (com cache).

Os trabalhos em lote são de uma época em que os recursos de processamento eram limitados e os serviços 'ativos' tinham precedência. Na nuvem, não é o caso.


Obrigado - gosto da direção que você está descrevendo.
Tom,

5
Esteja avisado que o SQS apenas garante que uma mensagem será vista por uma máquina eventualmente, não que as mensagens serão vistas apenas por um único servidor. Qualquer coisa que você colocar em uma fila SQS deve ser idempotente.
Richard Hurt

Meu cron job deve ser executado diariamente e com o SQS você só pode atrasar até 15 minutos. Uma opção poderia ser adicionar uma tag personalizada à mensagem com o tempo alvo para executá-la e colocá-la de volta na fila se esse tempo ainda não tiver atingido - mas isso realmente parece uma coisa idiota. Além disso, ainda preciso de um cron job para preencher inicialmente a fila. Parece um problema de ovo de galinha :) Mas eu ainda acho que SQS é a coisa certa a usar, porque garante escalabilidade e tolerância a falhas
Raffaele Rossi

"Os trabalhos em lote são de uma época em que os recursos de processamento eram limitados e os serviços 'ativos' prevaleciam. Na nuvem, esse não é o caso." Isso é verdade para algumas atividades, mas não para todas. Por exemplo, processar logs de tráfego é algo melhor como um processo em lote do que ao vivo.
Jordan Reiter,

1

Por que você construiria o seu próprio? Por que não usar algo como Quartz (com Clustered Scheduling). Veja a documentação.

http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering


Usei o Quartz.NET em uma solução SaaS que dependia muito de tarefas agendadas. Alguns eram tarefas de manutenção do sistema, mas a maioria era atividades programadas pelos usuários finais. Todas as nossas tarefas foram gravadas em filas de mensagens (amq) para as quais tínhamos qualquer número de serviços idempotentes. A API é muito boa e permite agendamentos poderosos. Não agrupamos várias instâncias do Quartz, mas há suporte para isso.
Jerico Sandhorn 14/03/15

1

O que fazemos é ter um servidor específico que faz parte de nosso cluster de aplicativo da web por trás de um ELB também atribuído a um nome DNS específico para que possamos executar os trabalhos nesse servidor específico. Isso também tem a vantagem de que, se esse trabalho fizer com que o servidor fique lento, o ELB o removerá do cluster e o retornará assim que o trabalho terminar e ele ficar bom novamente.

Trabalha como um campeão.




0

Já que ninguém mencionou o evento CloudWatch , eu diria que é a maneira da AWS de fazer trabalhos cron. Ele pode executar várias ações, como função Lambda, tarefa ECS.

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.