O blog da AWS

Renderização do lado do servidor de micro-frontends – Compositor de UI e descoberta de serviços

Por Luca Mezzalira, Principal Specialist Solutions Architect, Serverless.

O publicação anterior do blog descreve a arquitetura para criar um micro-frontend de renderização do lado do servidor na AWS. Este e os próximas publicações explicam em detalhes as diferentes partes que compõem esta arquitetura. O código do exemplo está disponível em um repositório GitHub da AWS Samples.

Para contextualizar, esta publicação aborda a infraestrutura relacionada ao compositor de UI e por que você precisa de um bucket do Amazon S3 para armazenar ativos estáticos:

Visão geral da arquitetura

O restante da série explora a composição de micro-frontends, como projetar micro-frontends usando serviços Serverless, diferentes estratégias de cache e otimização de desempenho, e as implicações da estrutura organizacional associadas a sistemas distribuídos de frontend.

A jornada da requisição de um usuário

A melhor maneira de navegar por este sistema distribuído é simulando uma requisição de usuário que toca todas as partes implementadas na arquitetura.

O exemplo de aplicação mostra uma página de detalhes de produto de uma plataforma hipotética de e-commerce:

Construindo micro-frontends

Quando um usuário seleciona um artigo da página de catálogo, o DNS resolve a URL para uma distribuição do Amazon CloudFront que é o CDN de referência para este projeto.

A requisição é imediatamente atendida se a página estiver em cache. Portanto, nenhuma lógica adicional é solicitada pela infraestrutura de nuvem e a resposta é rápida (menos de 500 ms mostrados neste exemplo).

Quando a página não está disponível nos pontos de presença (PoPs) do CloudFront, a requisição é encaminhada para o Application Load Balancer (ALB). Ela chega ao cluster do AWS Fargate onde o UI Composer gera a página para atender a requisição.

Usando CloudFront na arquitetura

CDNs são conhecidos por acelerar a entrega de aplicações graças ao cache de arquivos estáticos de PoPs próximos. O CloudFront também pode acelerar conteúdo não cacheável, como APIs dinâmicas ou conteúdo personalizado.

Com uma rede de mais de 450 pontos de presença, o CloudFront encerra conexões TCP/TLS de usuários em 20-30 milissegundos em média. O tráfego para servidores de origem é transportado pela rede global da AWS em vez da internet pública. Esta infraestrutura é uma infraestrutura privada construída especificamente, altamente disponível e de baixa latência, construída sobre uma rede de fibra metropolitana global, totalmente redundante, que está conectada por cabos terrestres e transoceânicos ao redor do mundo. Além de encerrar conexões próximas aos usuários, o CloudFront acelera conteúdo dinâmico graças a protocolos modernos de internet como QUIC e TLS1.3, e persistindo conexões TCP para os servidores de origem.

O CloudFront também tem benefícios de segurança, oferecendo proteção na AWS contra ataques DDoS de infraestrutura. Ele se integra com o AWS Web Application Firewall e o AWS Shield Advanced, fornecendo controles para bloquear ataques DDoS no nível de aplicação. O CloudFront também oferece controles de segurança nativos, como redirecionamentos de HTTP para HTTPS, gerenciamento de CORS, bloqueio geográfico, tokenização e gerenciamento de cabeçalhos de resposta de segurança.

Lógica de aplicação do UI Composer

Quando a requisição não é atendida pelo cache do CloudFront, ela é roteada para o cluster Fargate. Aqui, múltiplas tarefas computam e servem a página solicitada.

Este exemplo usa o Fastify, um framework Node.js rápido que está ganhando popularidade entre a comunidade Node.js. Quando o servidor web inicializa, ele carrega parâmetros externos e o template para compor uma página.

const start = async () => {
  try {
    //load parameters
    MFElist = await init();
    //load catalog template
    catalogTemplate = await loadFromS3(MFElist.template, MFElist.templatesBucket)
    await fastify.listen({ port: PORT, host: '0.0.0.0' })
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

Para manter a independência das equipes e evitar reimplantar o UI composer para cada mudança de aplicação, os templates HTML são carregados de um bucket S3. Todas as equipes responsáveis por micro-frontends na mesma página podem posicionar seus micro-frontends no lugar certo do template HTML e delegar a tarefa de composição ao UI composer.

Nesta demonstração, os parâmetros iniciais e o template de catálogo são recuperados uma vez. No entanto, em um cenário real, é mais provável que você recupere os parâmetros na inicialização e em uma cadência regular. O template pode ser carregado em tempo de execução para cada requisição ou ter outra rotina em segundo plano buscando os parâmetros de inicialização de maneira similar.

Quando a requisição chega à rota de detalhes do produto, a lógica da aplicação web chama uma função transformTemplate. Ela passa o template de catálogo, recuperado do bucket S3 na inicialização do servidor. Ela retorna uma resposta 200 se a página for composta sem problemas.

fastify.get('/productdetails', async(request, reply) => {
  try{
    const catalogDetailspage = await transformTemplate(catalogTemplate)
    responseStream(catalogDetailspage, 200, reply)
  } catch(err){
    console.log(err)
    throw new Error(err)
  }
})

A composição de página é a responsabilidade chave do UI composer. Existem várias abordagens viáveis para compor micro-frontends em um sistema de renderização do lado do servidor, cobertas no próxima publicação.

Descoberta de micro-frontends

Para desacoplar cargas de trabalho para múltiplas equipes, você deve usar padrões arquiteturais que suportem isso. Em uma arquitetura de microsserviços, um padrão que permite a evolução independente de um serviço sem acoplar o DNS ou IP a qualquer microsserviço é o padrão de descoberta de serviços.

Neste exemplo, o AWS System Managers Parameters Store atua como um registro de serviços. Cada micro-frontend disponível na carga de trabalho se registra uma vez que a infraestrutura é provisionada.

Desta forma, o UI composer pode solicitar o ID do micro-frontend encontrado dentro do template HTML. Ele pode recuperar a maneira correta de consumir a API do micro-frontend usando um ARN ou uma URL HTTP remota, por exemplo.

AWS System Managers Parameters Store

Usar ARN em vez de requisições HTTP dentro da rede de carga de trabalho pode ajudá-lo a reduzir a latência graças a menos saltos de rede. Além disso, a segurança é delegada às políticas IAM, fornecendo uma implementação de segurança robusta.

O UI composer cuida de recuperar os endpoints dos micro-frontends em tempo de execução antes de carregá-los no template HTML. Esta é uma abordagem mais simples, porém poderosa, para manter os limites dentro de sua organização e permitir que equipes independentes evoluam sua arquitetura de forma autônoma.

Evolução da descoberta de micro-frontends

Usando o Parameter Store como um sistema de descoberta de serviços, você pode implantar um novo micro-frontend adicionando um novo par chave-valor na descoberta de serviços.

Uma opção mais sofisticada poderia ser criar um serviço que atue como um registro e também modele o tráfego em direção a diferentes versões de micro-frontends usando estratégias de implantação como lançamentos canary ou implantações blue/green.

Você pode começar iterativamente com um sistema simples de armazenamento chave-valor e evoluir a arquitetura com uma abordagem mais complexa quando a carga de trabalho exigir, fornecendo uma maneira robusta de lançar serviços de micro-frontends em seu sistema.

Quando isso estiver em vigor, é provável que aumente a cadência de lançamento de seus micro-frontends. Isso ocorre porque os desenvolvedores geralmente se sentem mais seguros lançando em produção sem afetar toda a base de usuários e podem executar testes junto com o tráfego real.

Considerações de desempenho

Esta arquitetura usa Fargate para compor os micro-frontends em vez de funções Lambda. Isso permite a renderização incremental oferecida pelos navegadores, exibindo a página HTML parcialmente antes de ser completamente retornada.

Considere um cenário onde um micro-frontend leva mais tempo para renderizar devido a uma dependência downstream ou uma versão defeituosa implantada em produção. Sem a capacidade de streaming, você deve esperar até que todas as respostas dos micro-frontends cheguem, armazená-las em buffer na memória, compor a página e então enviar a saída final para o navegador.

Em vez disso, ao usar a API de streaming oferecida pelos frameworks Node.js, você pode enviar uma página HTML parcial (por exemplo, a tag head e subsequentemente o resto da página), para ser renderizada por um navegador.

O streaming também melhora a sobrecarga do servidor, porque os servidores não precisam armazenar páginas inteiras em buffer. Ao liberar dados incrementalmente para os navegadores, os servidores mantêm a pressão de memória baixa, o que permite processar mais requisições e economizar custos de sobrecarga.

No entanto, caso sua carga de trabalho não exija essas capacidades, uma ou múltiplas funções Lambda podem ser adequadas para seu projeto também, reduzindo a complexidade de gerenciamento de infraestrutura a ser tratada.

Conclusão

Esta publicação analisa como usar o UI Composer e a descoberta de micro-frontends. Uma vez que esta parte é desenvolvida, ela não precisará mudar regularmente. Isso representa a fundação para construir micro-frontends de renderização do lado do servidor usando HTML-over-the-wire. Pode haver outras abordagens a seguir para outros frameworks como Next.js devido à implementação arquitetural do próprio framework.

A próxima publicação cobrirá como o UI composer inclui a saída dos micro-frontends dentro de um template HTML.

Para mais recursos de aprendizado Serverless, visite Serverless Land.


Este conteúdo foi traduzido do post original do blog, que pode ser encontrado aqui.

Tradutores

Nicolas Tarzia é Senior Technical Account Manager na AWS, com mais de 13 anos de experiência, com ampla experiência em arquitetura cloud, engenharia e design de software. Sua área de interesse são tecnologias serverless.
https://www.linkedin.com/in/nicolastarzia
Daniel Abib é Arquiteto de Soluções Sênior e Especialista em Amazon Bedrock na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, arquitetura Serverless & Containers e especialização em Machine Learning. Ele trabalha apoiando Startups, ajudando-os em sua jornada para a nuvem.
https://www.linkedin.com/in/danielabib/