Experts in Angular

The Twelve-Factor AppVI. Processes – Executar a aplicação como processos sem estado
Executar a aplicação como processos sem estado

VI. Processes – Executar a aplicação como processos sem estado

Garantir que os processos não dependam de estado persistente, permitindo escalabilidade

6º Fator: Processos Independentes e Sem Estado

No desenvolvimento de aplicações modernas, especialmente com Angular, o sexto fator da metodologia de doze fatores — processos sem estado — é uma prática essencial para garantir escalabilidade e resiliência. A ideia central desse fator é que os processos que executam a aplicação devem ser sem estado e não compartilhar nada, o que significa que qualquer dado que precise persistir deve ser armazenado em serviços externos, como bancos de dados ou sistemas de cache.

O Que Significa “Sem Estado”?

Uma aplicação sem estado é aquela onde cada processo que a executa não mantém informações entre uma execução e outra. Isso quer dizer que, se o processo for reiniciado, movido ou substituído, ele não “se lembrará” do estado anterior. Esse estado temporário pode ser armazenado na memória do processo ou no sistema de arquivos, mas ele só pode durar enquanto o processo estiver ativo. Para garantir que a aplicação continue funcionando corretamente em diferentes momentos e com múltiplos processos, qualquer dado que precise ser persistido entre as execuções deve ser armazenado fora do processo, geralmente em um banco de dados, cache, ou outros sistemas de apoio.

Processos Sem Estado no Angular

Embora o Angular seja um framework focado no frontend, ele se integra com diversos serviços de backend e APIs para processar dados. O frontend de uma aplicação Angular é, por natureza, “sem estado”, já que ele não armazena persistência diretamente. No entanto, existem práticas que precisam ser seguidas para garantir que a aplicação mantenha essa característica em conjunto com o backend.

Aqui estão alguns exemplos de como garantir que a aplicação Angular siga esse princípio:

  1. Sessões e Autenticação: No Angular, a autenticação de usuários pode ser feita por meio de tokens como JWT (JSON Web Tokens). Quando um usuário faz login, o token JWT é armazenado no localStorage ou sessionStorage do navegador, mas nunca no backend da aplicação. Isso garante que a autenticação não dependa de um processo específico do servidor.
    • Exemplo: Um usuário pode fazer login na aplicação Angular, o token JWT é armazenado localmente no navegador e, a cada requisição subsequente, o token é enviado nas cabeçalhos da requisição para validar a sessão. Se o backend for reiniciado, ele não precisa “lembrar” do estado de sessão do usuário; basta validar o token enviado.
  2. Armazenamento de Dados Temporários: O Angular pode manipular dados temporários em memória para realizar cálculos ou cache de forma breve, mas qualquer dado que precise ser persistido deve ser enviado para um banco de dados externo ou serviço de cache, como Redis ou Memcached. Por exemplo, se a aplicação estiver manipulando grandes volumes de dados, é importante enviar os resultados das operações para um serviço de backend assim que possível.
  3. Escalabilidade com Backend Sem Estado: Quando o Angular interage com um backend, seja ele construído com Node.js, Spring Boot ou outra tecnologia, é importante que o backend siga os mesmos princípios de “processos sem estado”. Isso facilita a escalabilidade horizontal, onde múltiplas instâncias do backend podem ser executadas simultaneamente sem depender do estado de uma única instância.

Evitar Sessões Persistentes

Uma prática comum em algumas arquiteturas web é o uso de sessões persistentes (também conhecidas como “sticky sessions”). Isso ocorre quando um servidor armazena informações da sessão do usuário na memória e espera que todas as requisições subsequentes desse usuário sejam roteadas para o mesmo servidor. Essa abordagem viola o princípio dos doze fatores, pois vincula o estado do usuário a um processo específico.

Em vez disso, o estado da sessão deve ser armazenado em um serviço externo que possa ser acessado por todos os processos de backend. Serviços como Redis ou Memcached são amplamente usados para armazenar dados de sessão temporários, permitindo que qualquer processo de backend possa atender a requisições subsequentes sem depender de um processo específico.

Exemplo: Armazenando Sessões no Redis

Aqui está um exemplo de como isso pode ser feito em uma arquitetura com um backend que fornece APIs para uma aplicação Angular:

  • O usuário faz login e o servidor gera um token JWT.
  • O token JWT é armazenado no navegador (Angular) e também no Redis para rastreamento de sessões.
  • Quando o usuário faz uma requisição subsequente, o token JWT é enviado, e qualquer instância do backend pode verificar o token no Redis.

Essa abordagem elimina a dependência de um único processo ou servidor e garante que a aplicação seja escalável.

Cache de Arquivos

Em algumas situações, a aplicação pode precisar realizar operações temporárias em arquivos grandes, como processar uploads de usuários. Nesses casos, o sistema de arquivos pode ser utilizado como um cache temporário para operações breves, mas é importante que o resultado final dessas operações seja armazenado em um serviço de apoio persistente.

Por exemplo, ao processar um arquivo de imagem carregado por um usuário, o backend pode armazenar temporariamente o arquivo no sistema de arquivos, processá-lo (redimensionar ou comprimir) e, em seguida, enviar o resultado para um serviço externo, como o Amazon S3, onde o arquivo será armazenado permanentemente.

Benefícios de Processos Sem Estado

  1. Escalabilidade: Quando os processos são sem estado, é fácil escalar a aplicação horizontalmente. Novos processos podem ser adicionados ou removidos sem impacto no funcionamento da aplicação.
  2. Tolerância a Falhas: Se um processo falha ou é reiniciado, a aplicação pode continuar funcionando sem perda de dados, desde que todos os dados persistentes estejam armazenados em serviços de apoio externos.
  3. Flexibilidade na Infraestrutura: A aplicação pode ser movida entre diferentes servidores ou containers (como no Docker) sem precisar replicar o estado entre eles. Isso torna a infraestrutura mais resiliente e flexível.

Conclusão

A implementação de processos sem estado é essencial para garantir que a aplicação Angular seja escalável e tolerante a falhas. Ao garantir que qualquer estado necessário seja armazenado em serviços de apoio externos, como bancos de dados ou sistemas de cache, sua aplicação estará preparada para rodar em múltiplos processos, em diferentes ambientes, sem depender de um processo ou servidor específico.