Programação de tarefas confiável no Google Compute Engine

Em sistemas distribuídos, como uma rede de instâncias do Google Compute Engine, programar tarefas de maneira confiável é desafiador porque qualquer instância individual pode ficar indisponível devido à autenticação ou ao particionamento de rede.

No Google App Engine, é fornecido um Cron Service. Com o uso desse serviço para a programação, e o Google Cloud Pub/Sub para a distribuição de mensagens, crie um aplicativo para programar tarefas de maneira confiável ao longo de uma frota de instâncias do Compute Engine.

Neste artigo de três partes, são discutidos os seguintes itens:

Como programar tarefas de maneira confiável no Google Compute Engine

O Cron é a ferramenta padrão para a programação de tarefas recorrentes nos sistemas Unix. Conforme os sistemas criados aumentam de complexidade e se tornam distribuídos, ter apenas um computador executando o cron pode se tornar um ponto de falha crítico. A instância pode parar devido ao escalonamento automático, ou o segmento de rede pode ser particionado dos sistemas com os quais ela precisa se comunicar.

Outras abordagens para aumentar a disponibilidade, como grupos de instâncias por trás de um balanceador de carga, não funcionam quando é necessário programar um evento que só precisa ser executado uma vez por todo o sistema. Por exemplo, se quatro servidores executarem o mesmo cron job singleton a cada hora, pode acontecer competição por recursos e possível duplicação de resultados.

Resolver o problema de como programar tarefas em um sistema distribuído não é algo trivial. Uma solução para esse problema está na biblioteca Chronos para Apache Mesos, mas ela envolve uma grande quantidade de configuração e gerenciamento.

No App Engine, é fornecido um Cron Service. Se o aplicativo for executado no App Engine, você pode apenas gravar gerenciadores do App Engine e programar eventos, e o serviço do Cron vai disparar os eventos e chamar os gerenciadores de eventos certos para seu aplicativo. Para executar tarefas na sua instância do Compute Engine em resposta a eventos do Cron Service, você precisa redirecionar os eventos do Cron Service para essas instâncias.

Isso pode ser feito de diversas maneiras, por exemplo:

  1. Chame um ponto de extremidade HTTP em execução nas suas instâncias do Compute Engine usando o serviço de busca de URL do App Engine.
  2. Orquestre tarefas e bloqueios usando as transações do Google Cloud Datastore.
  3. Envie mensagens de manipuladores de eventos no App Engine para suas instâncias do Compute Engine usando um serviço de mensagens.

Nesta amostra, é usado o terceiro padrão de design. Ele é mais simples de se implementar do que gerenciar bloqueios e o estado das tarefas no Cloud Datastore. Também é mais confiável do que enviar solicitações HTTP para instâncias do Compute Engine, que podem parar ou perder a conectividade com a rede antes de completar uma tarefa.

No diagrama a seguir,é ilustrada uma visão geral da arquitetura desse padrão de design.

Diagrama de visão geral da arquitetura

Nesta implementação, um aplicativo do App Engine programa eventos no serviço do Cron e os transmite para instâncias do Compute Engine usando o Google Cloud Pub/Sub. O Cloud Pub/Sub é um serviço na rede totalmente gerenciado com envio de mensagens assíncronas muitos para muitos robusto entre aplicativos.

Um serviço utilitário nas instâncias do Compute Engine é inscrito nos tópicos do Cloud Pub/Sub e executa cron jobs em resposta aos eventos que ele extrai daqueles tópicos. O utilitário executa scripts padrão, não sendo necessário modificar os scripts cron atuais para usá-los nessa amostra.

Com o uso do Cloud Pub/Sub para desacoplar a lógica de programação de tarefas da lógica que executa os comandos no Compute Engine, você pode atualizar os scripts do cron conforme a necessidade, sem precisar atualizar ou reimplantar o aplicativo do App Engine. Também é possível mudar a programação das tarefas sem atualizar o utilitário nas instâncias do Compute Engine.

Cotas

Como os cron jobs costumam ser poucos e executados em uma programação por hora, por semana ou por dia, esse padrão de design não deve exceder as cotas do serviço projetadas para operações de alto volume. Caso isso aconteça, use outros padrões de aplicativo, como gerenciar o tempo das tarefas diretamente no código do aplicativo.

Custo

O custo de executar esse padrão de design é inferior a US$ 1,00 por mês. Nessa análise de custo, supõe-se um cron job executado a cada doze horas, durante uma hora a cada vez, em uma instância f1-micro. Para um detalhamento dos custos dessa estimativa e para calcular os custos do seu próprio caso de uso, consulte a Calculadora de preços do Google Cloud Platform.

No App Engine, há uma cota gratuita de back-end de 8 horas-instância por dia. Se essa cota não estiver sendo usada em outros aplicativos, o custo do App Engine para executar esse padrão de design será US$ 0,00, e ainda menor.

Por exemplo, se você executar a implementação de amostra na seção a seguir por uma hora e depois excluir os recursos do Google Cloud, o custo será de aproximadamente US$ 0,01.

Amostra de implementação do padrão de design

Uma amostra de implementação desse padrão de design, Amostra: programação confiável de tarefas no Google Compute Engine, está disponível no GitHub.

A amostra contém dois componentes:

  • Um aplicativo do App Engine que usa o Cron Service do App Engine para retransmitir mensagens do Cron para os tópicos do Cloud Pub/Sub.

  • Um utilitário executado no Compute Engine. Esse utilitário monitora um tópico do Cloud Pub/Sub. Quando detecta uma nova mensagem, ele executa o comando correspondente localmente no servidor.

A amostra é descrita detalhadamente no arquivo leia-me, que também demonstra como executar o código de amostra no Google Cloud Platform.

Como criar com base no padrão de design e na amostra

É fácil configurar crons distribuídos nas instâncias do Compute Engine usando o Cron Service do App Engine, com o mínimo de preparação e custo.

Na amostra anterior, foi ilustrada uma forma de implementar uma solução de programação confiável para o Compute Engine usando o Cron Service do App Engine. Esse padrão de design é útil porque, nele, a lógica de programação fica separada da lógica que executa os comandos na instância do Compute Engine, o que torna possível mudar o local e a execução das tarefas sem precisar atualizar a lógica de programação.

No diagrama abaixo, está ilustrado o fluxo das mensagens cron nessa amostra. Especificando quais instâncias se inscrevem em um tópico, pode-se controlar a execução de um cron job em uma ou em várias instâncias.

Diagrama arquitetônico detalhado

Outra vantagem dessa arquitetura é o controle dado sobre a maneira como os cron jobs são roteados para suas instâncias.

Você pode enviar mensagens cron diferentes para conjuntos de servidores diferentes, conforme ilustrado nos tópicos A e C do Cloud Pub/Sub. As tarefas do Tópico A são enviadas para apenas um assinante, enquanto vários servidores estão inscritos no Tópico C. Essa estratégia pode ser usada para executar um conjunto de comandos no servidor da Web e outro nos outros servidores.

Outra opção é executar um comando em um dos vários servidores. Isso está ilustrado no Tópico B. Nesse caso, uma assinatura é compartilhada por vários servidores, e as mensagens publicadas no tópico B são gerenciadas pelo primeiro servidor. Este reivindica a mensagem, e o comando correspondente é executado somente no servidor em questão. Use isso para fazer análises de dados noturnas que só precisam ser executadas em um servidor.

Próximas etapas

Modifique a amostra e use-a como modelo para seu próprio aplicativo. Abaixo estão algumas ideias para você começar.

  • Atualize o cron.yaml para especificar suas próprias mensagens do cron. Atualize o cron job diretamente, como descrito em Atualizar cron jobs, ou reimplante o aplicativo do App Engine para atualizar o Cron Service do App Engine.

  • Atualize o test_executor.py para executar um script real em vez de logger_sample_task.py, ou escreva seu próprio utilitário Executor.

  • Em vez de lançar manualmente o utilitário no Compute Engine e executá-lo como um processo de primeiro plano, lance-o automaticamente como daemon por uma ferramenta de sistema ou de terceiros, como o systemd ou o Supervisor.

  • Tanto no Cron Service do App Engine quanto no Cloud Pub/Sub, não há garantias de entrega restrita "exatamente uma vez". Pode acontecer uma entrega de mensagem duplicada, mas isso é improvável. Se a execução de uma tarefa específica mais de uma vez gerar um resultado indesejado, use uma ferramenta de bloqueio consistente e distribuída, como o Zookeeper, para garantir que a tarefa seja executada somente uma vez e por uma só instância.

  • Ao programar tarefas, siga as práticas recomendadas do cron e programe-as distantes o bastante para que possam ser processadas completamente antes de serem executadas outra vez.

  • Execute o utilitário em uma microinstância para criar uma solução cron de baixo custo. Quando recebe uma tarefa, ela inicia instâncias mais poderosas para processar as tarefas cron rapidamente. Após completar as tarefas, as instâncias maiores podem apenas ser desligadas. Isso dá a você flexibilidade para completar as tarefas pouco tempo depois do tempo do evento, com um custo mínimo.

  • Nessa implementação, o cron.yaml é implantado no App Engine junto com o aplicativo do App Engine. Isso significa que qualquer alteração nas mensagens cron exige que você reimplante o aplicativo do App Engine. Para evitar isso, estenda a mesma implementação reescrevendo o aplicativo do App Engine para puxar o arquivo YAML de um intervalo do Cloud Storage. Faça com que ela monitore o arquivo em busca de mudanças e atualize o Cron Service do App Engine quando detectar modificações no arquivo YAML.

Conheça outros recursos do Google Cloud Platform. Confira nossos tutoriais.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…