Experts in Angular

The Twelve-Factor AppIX. Disposability – Maximizar a robustez com inicialização rápida e desligamento gracioso
Maximização da Robustez com Inicialização Rápida e Desligamento Gracioso

IX. Disposability – Maximizar a robustez com inicialização rápida e desligamento gracioso

Garantir que os processos possam ser iniciados ou encerrados rapidamente

9º Fator: Maximização da Robustez com Inicialização Rápida e Desligamento Gracioso

O nono fator da metodologia de doze fatores trata da disponibilidade e robustez dos processos de uma aplicação. Ele enfatiza que os processos devem ser descartáveis, ou seja, podem ser iniciados ou encerrados rapidamente e sem problemas, maximizando a escalabilidade, robustez e facilidade de manutenção de uma aplicação. A inicialização rápida e o desligamento gracioso garantem que a aplicação possa escalar de maneira eficaz e lidar com falhas ou atualizações sem interrupções significativas.

O Conceito de “Disposability”

No contexto da metodologia de doze fatores, o termo “disposable” significa que os processos da aplicação podem ser iniciados ou parados rapidamente, sem efeitos colaterais graves. Isso é crucial para garantir que a aplicação possa ser escalada horizontalmente de maneira eficiente, que o código possa ser atualizado frequentemente (via CI/CD), e que eventuais falhas possam ser recuperadas rapidamente.

No Angular, como um framework frontend, a maior parte da disposability se aplica ao backend e às operações que ele realiza, já que o Angular em si é executado no navegador do cliente após ser carregado. No entanto, o Angular ainda depende fortemente de um backend que siga esse princípio de disposability, principalmente quando falamos de APIs ou serviços de backend que o frontend Angular consome.

Disposability no Contexto do Angular

Embora o Angular seja uma aplicação frontend, ele interage constantemente com serviços de backend. Se o backend precisar ser escalado ou atualizado, a aplicação Angular deve ser capaz de se reconectar a novos processos de backend sem interrupção. Isso significa que o backend deve ser capaz de:

  1. Inicializar Rapidamente:
    • Quando o backend for escalado ou novos processos forem iniciados, eles devem estar prontos para aceitar conexões o mais rápido possível. Processos que demoram muito para inicializar podem introduzir lentidão na resposta da aplicação Angular ao tentar acessar dados ou APIs.
    • Exemplo Angular: Se uma aplicação Angular estiver chamando uma API REST para obter dados, o backend que fornece esses dados deve estar pronto para responder imediatamente após ser iniciado, minimizando o tempo de inatividade. Um backend que demora para inicializar pode resultar em falhas ou tempos de resposta longos para os usuários do Angular.
  2. Desligar Graciosamente:
    • Quando um processo de backend está prestes a ser encerrado (por exemplo, em uma atualização de código ou um redimensionamento da infraestrutura), ele deve lidar com as requisições em andamento de maneira apropriada antes de encerrar. Isso significa que ele deve parar de aceitar novas requisições, concluir as requisições em andamento e, em seguida, encerrar o processo de forma ordenada.
    • Exemplo Angular: Imagine que o backend que atende às requisições da aplicação Angular esteja em processo de desligamento. Se o backend fechar abruptamente, isso pode resultar em respostas incompletas ou falhas de conexão para os usuários do frontend. Um desligamento gracioso permite que o backend conclua qualquer requisição pendente antes de encerrar, garantindo uma transição suave.
  3. Gerenciamento de Processos em Execução:
    • Ferramentas de gerenciamento de processos, como Kubernetes, podem lidar com a execução de múltiplas instâncias de backend e garantir que novas instâncias sejam criadas rapidamente quando necessário. Esses sistemas devem ser capazes de escalar horizontalmente, iniciando novos processos ou movendo processos para novos servidores sem afetar o funcionamento da aplicação Angular.

Desligamento Gracioso e Resiliência

O desligamento gracioso envolve o tratamento adequado dos sinais de encerramento do sistema operacional, como o SIGTERM, para garantir que o processo tenha a oportunidade de concluir seu trabalho antes de encerrar.

  • Exemplo de Backend com Desligamento Gracioso: Um backend Node.js que atende a uma aplicação Angular pode interceptar o sinal SIGTERM para iniciar o desligamento gracioso:
process.on('SIGTERM', () => {
  console.log('Desligamento gracioso iniciado...');
  server.close(() => {
    console.log('Todas as requisições concluídas, desligando.');
    process.exit(0);
  });
});
  • Nesse exemplo, o backend para de aceitar novas requisições, conclui as que estão pendentes e, em seguida, desliga o processo. Isso evita que os usuários da aplicação Angular enfrentem interrupções inesperadas.

Inicialização Rápida

A inicialização rápida é um aspecto igualmente importante. Quanto mais rápido um processo de backend pode ser iniciado e pronto para lidar com as requisições do Angular, mais ágil e responsiva será a aplicação. Isso é especialmente importante quando a aplicação precisa escalar rapidamente em resposta a picos de tráfego, como em eventos sazonais ou picos inesperados de uso.

Ferramentas como Docker e Kubernetes permitem que novos containers sejam criados e iniciados em segundos, o que possibilita uma inicialização rápida e eficiente de novos processos de backend.

Cenários de Falha

Mesmo com todas as precauções, os processos podem falhar de maneira inesperada, seja por um erro de código, falha no hardware ou outro problema imprevisto. Nesse caso, é crucial que a arquitetura de backend seja robusta o suficiente para lidar com falhas repentinas e reiniciar os processos automaticamente.

  • Filas e Retries: Uma abordagem comum para tornar o backend resiliente é utilizar filas (como RabbitMQ ou Kafka) para gerenciar tarefas. Se um processo falhar inesperadamente, qualquer trabalho pendente na fila pode ser atribuído a outro processo. Isso garante que as tarefas críticas, como envio de e-mails ou processamento de pagamentos, sejam concluídas mesmo após falhas no processo original.

Exemplo de Concorrência e Descartabilidade

Para ilustrar como o conceito de descartabilidade pode ser implementado, vamos considerar um backend que gerencia pedidos de uma aplicação Angular. Imagine que a aplicação permite que os usuários façam pedidos online. O backend pode consistir de dois tipos de processos:

  1. Processos Web: Que lidam com as requisições de API do Angular para criação de novos pedidos e consultas.
  2. Processos de Worker: Que processam os pedidos em segundo plano, como atualizações de inventário ou envio de confirmações por e-mail.

Esses processos devem ser descartáveis. Se o backend web ou o worker precisar ser reiniciado ou redimensionado, o sistema deve lidar com essas mudanças sem interrupções para o usuário. Os pedidos em andamento podem ser colocados em uma fila e processados por outro worker ou por um novo processo web sem que o cliente Angular perceba qualquer problema.

Conclusão

O fator de disposability é fundamental para garantir que uma aplicação Angular e seu backend possam lidar com redimensionamento, falhas e atualizações sem interrupções significativas para os usuários. Embora o Angular seja uma aplicação frontend, ele depende fortemente de um backend que siga esse princípio, garantindo uma experiência suave e robusta para o usuário final.