Uma aplicação bem arquitetada e orientada a eventos usa uma combinação de serviços da AWS e códigos personalizados para processar e gerenciar solicitações e dados. Este capítulo se concentra em tópicos específicos do Lambda no design de aplicações. Há muitas considerações importantes para arquitetos que usam tecnologia sem servidor ao projetar aplicações para sistemas de produção com um grande volume de operações.
Muitas das práticas recomendadas que se aplicam ao desenvolvimento de software e sistemas distribuídos também se aplicam ao desenvolvimento de aplicações com tecnologia sem servidor. O objetivo geral é desenvolver workloads que sejam:
-
Confiáveis: oferece aos usuários finais um alto nível de disponibilidade. Os serviços com tecnologia sem servidor da AWS são confiáveis porque também foram projetados para falhas.
-
Duráveis: fornece opções de armazenamento que atendem às necessidades de durabilidade da sua workload.
-
Seguras: segue as práticas recomendadas e usa as ferramentas fornecidas para proteger o acesso às workloads e limitar o raio de explosão.
-
Eficientes: usa recursos de computação de forma eficiente e atende às necessidades de performance de seus usuários finais.
-
Econômicas: projeta arquiteturas que evitam custos desnecessários e que podem ser escaladas sem gastar demais, além de ser possível desativá-las, se necessário, sem gerar uma sobrecarga significativa.
Os princípios de design a seguir podem ajudar você a criar workloads que atendam a essas metas. Nem todos os princípios podem ser aplicáveis a todas as arquiteturas, mas eles devem orientar você em decisões gerais de arquitetura.
Tópicos
Uso de serviços, em vez de código personalizado
As aplicações com tecnologia sem servidor geralmente incluem vários serviços da AWS, integrados ao código personalizado executado nas funções do Lambda. Embora o Lambda possa ser integrado à maioria dos serviços da AWS, os serviços mais usados em aplicações com tecnologia sem servidor são:
Categoria | Serviço da AWS |
---|---|
Computação |
AWS Lambda |
Armazenamento de dados |
Amazon S3 Amazon DynamoDB Amazon RDS |
API |
Amazon API Gateway |
Integração de aplicações |
Amazon EventBridge Amazon SNS Amazon SQS |
Orquestração |
AWS Step Functions |
Dados de streaming e analytics |
Amazon Data Firehose |
Há muitos padrões comuns e bem estabelecidos em arquiteturas distribuídas que você pode criar ou implementar por conta própria usando os serviços da AWS. Para a maioria dos clientes, há pouco valor comercial em investir tempo para desenvolver esses padrões do zero. Quando sua aplicação precisar de um desses padrões, use o serviço da AWS correspondente:
Padrão | Serviço da AWS |
---|---|
Fila |
Amazon SQS |
Barramento de eventos |
Amazon EventBridge |
Publicação/assinatura (distribuição) |
Amazon SNS |
Orquestração |
AWS Step Functions |
API |
Amazon API Gateway |
Streams de eventos |
Amazon Kinesis |
Esses serviços são projetados para se integrarem ao Lambda, e você pode usar a infraestrutura como código (IaC) para criar e descartar recursos nesses serviços. É possível usar qualquer um desses serviços por meio do AWS SDK
Compreender níveis de abstração do Lambda
O serviço Lambda limita seu acesso aos sistemas operacionais, hipervisores e hardware subjacentes que executam suas funções do Lambda. O serviço melhora e muda continuamente a infraestrutura para adicionar recursos, reduzir custos e tornar o serviço mais eficiente. Seu código deve presumir que não tem conhecimento de como o Lambda é arquitetado e não deve presumir nenhuma afinidade com o hardware.
Da mesma forma, as integrações do Lambda com outros serviços são gerenciadas por AWS, com apenas um pequeno número de opções de configuração expostas a você. Por exemplo, quando o API Gateway e o Lambda interagem, não há nenhum conceito de balanceamento de cargas, pois ele é totalmente gerenciado pelos serviços. Você também não tem controle direto sobre quais zonas de disponibilidade
Essa abstração permite que você se concentre nos aspectos de integração da sua aplicação, no fluxo de dados e na lógica de negócios em que sua workload agrega valor aos usuários finais. Permitir que os serviços gerenciem a mecânica subjacente ajuda você a desenvolver aplicações mais rapidamente com menos código personalizado para manter.
Implementar a ausência de estado em funções
Ao criar funções do Lambda, você deve presumir que o ambiente existe somente para uma única invocação. A função deve inicializar qualquer estado necessário ao ser iniciada pela primeira vez. Por exemplo, sua função pode exigir buscas de dados de uma tabela do DynamoDB. Ele deve confirmar todas as alterações permanentes de dados em um armazenamento durável, como Amazon S3, DynamoDB ou Amazon SQS, antes de sair. Ele não deve depender de nenhuma estrutura de dados ou arquivo temporário existente, nem de qualquer estado interno que seja gerenciado por várias invocações.
Para inicializar conexões e bibliotecas de banco de dados, ou para carregar o estado, você pode tirar proveito da inicialização estática. Como os ambientes de execução são reutilizados sempre que possível para melhorar a performance, você pode amortizar o tempo necessário para inicializar esses recursos em várias invocações. No entanto, você não deve armazenar nenhuma variável nem dados usados na função dentro desse escopo global.
Minimizar o acoplamento
A maioria das arquiteturas deve preferir muitas funções mais curtas, em vez de menos funções maiores. O objetivo de cada função deve ser lidar com o evento passado para a função, sem conhecimento ou expectativas do fluxo de trabalho geral ou do volume de transações. Isso torna a função independente da origem do evento com acoplamento mínimo a outros serviços.
Quaisquer constantes de escopo global que mudam com pouca frequência devem ser implementadas como variáveis de ambiente para permitir atualizações sem implantações. Todos os segredos ou informações confidenciais devem ser armazenados no AWS Systems Manager Parameter Store ou no AWS Secrets Manager
Criar para dados sob demanda em vez de lotes
Muitos sistemas tradicionais são projetados para serem executados periodicamente e processarem lotes de transações que se acumularam ao longo do tempo. Por exemplo, uma aplicação bancária pode ser executada a cada hora para processar transações de caixas eletrônicos em livros-razão centrais. Em aplicações baseadas no Lambda, o processamento personalizado deve ser acionado por cada evento, permitindo ao serviço aumentar a escala da simultaneidade conforme necessário, para fornecer processamento quase em tempo real das transações.
Embora você possa executar tarefas cron
Por exemplo, não é uma prática recomendada usar um processo em lote que aciona uma função do Lambda para buscar uma lista de novos objetos do Amazon S3. Isso ocorre porque o serviço pode receber mais objetos novos entre os lotes do que é possível processar em uma função do Lambda de 15 minutos.

Em vez disso, o Amazon S3 deve invocar a função do Lambda sempre que um novo objeto é colocado no bucket. Essa abordagem é significativamente mais dimensionável e funciona quase em tempo real.

Considere AWS Step Functions para orquestração
Fluxos de trabalho que envolvem lógica de ramificação, diferentes tipos de modelos de falha e lógica de novas tentativas normalmente usam um orquestrador para acompanhar o estado da execução geral. Evite usar funções do Lambda para essa finalidade, pois isso resulta em um acoplamento rígido e em um roteamento complexo de manipulação de código.
Com o AWS Step Functions
É comum que fluxos de trabalho mais simples em funções do Lambda se tornem mais complexos com o tempo. Ao operar uma aplicação de produção com tecnologia sem servidor, é importante identificar quando isso está acontecendo, para que você possa migrar essa lógica para uma máquina de estado.
Implementar a idempotência
Os serviços da AWS com tecnologia sem servidor, incluindo o Lambda, são tolerantes a falhas e projetados para lidar com erros. Por exemplo, se um serviço invoca uma função do Lambda e há uma interrupção do serviço, o Lambda invoca sua função em uma zona de disponibilidade diferente. Se a função lançar um erro, o Lambda tentará executar a invocação mais uma vez.
Como o mesmo evento pode ser recebido mais de uma vez, as funções devem ser projetadas para terem idempotência
Você pode implementar a idempotência em funções do Lambda, usando uma tabela do DynamoDB para rastrear identificadores processados recentemente a fim de determinar se a transação já foi tratada anteriormente. A tabela do DynamoDB geralmente implementa um valor de tempo de vida (TTL) para expirar itens a fim de limitar o espaço de armazenamento usado.
Usar várias contas da AWS para gerenciar cotas
Muitas cotas de serviço no AWS são definidas em nível de conta. Isso significa que, à medida que você adiciona mais workloads, pode esgotar seus limites rapidamente.
Uma maneira eficiente de resolver esse problema é usar várias contas, dedicando cada workload à sua própria conta. Isso evita que as cotas sejam compartilhadas com outras workloads ou recursos que não sejam de produção.
Além disso, usando o AWS Organizations
Uma abordagem comum é fornecer uma conta da AWS a cada desenvolvedor e, em seguida, usar contas separadas para uma fase de implantação beta e produção:

Nesse modelo, cada desenvolvedor tem seu próprio conjunto de limites para a conta. Portanto, seu uso não afeta o ambiente de produção. Essa abordagem também permite que os desenvolvedores testem as funções do Lambda localmente nas máquinas de desenvolvimento em relação aos recursos ativos da nuvem em suas contas individuais.