O blog da AWS

Usando o padrão “circuit-breaker” com extensões do AWS Lambda e Amazon DynamoDB

Este blog foi escrito por Alan Oberto Jimenez, arquiteto sênior de aplicativos em nuvem, e Tobias Drees, arquiteto de aplicativos em nuvem.

Os sistemas de software modernos frequentemente dependem de chamadas remotas para outros sistemas nas redes. Quando ocorrem falhas, elas podem se espalhar em vários serviços, causando interrupções no serviço. Uma técnica para mitigar esse risco é o padrão circuit-breaker, que pode detectar e isolar falhas em um sistema distribuído. O padrão circuit-breaker pode ajudar a evitar falhas em cascata e melhorar a estabilidade geral do sistema.

O padrão isola o serviço com falha e, assim, evita falhas em cascata. Ele melhora a capacidade de resposta geral, evitando tempos de espera longos por períodos de tempo limite. Além disso, também aumenta a tolerância a falhas do sistema, pois permite que o sistema interaja com o serviço afetado quando ele estiver disponível novamente.

Esta postagem do blog apresenta um exemplo de aplicativo, mostrando como as extensões do AWS Lambda se integram ao Amazon DynamoDB para implementar o padrão circuit-breaker.

Usando extensões Lambda para implementar o padrão circuit-breaker

As extensões do AWS Lambda fornecem uma forma de integrar ferramentas de monitoramento, observabilidade, segurança e governança ao ambiente de execução do Lambda sem gerenciamento complexo de instalação ou configuração. Você pode executar extensões como parte do processo de runtime com uma extensão interna ou como um processo separado no ambiente de execução com uma extensão externa.

As extensões Lambda habilitam o padrão circuit-breaker sem modificar o código da função principal. Uma extensão externa verifica em um runtime separado se um determinado serviço está acessível ou não. Essa abordagem separa a lógica de negócios na função Lambda da detecção de falhas, permitindo a reutilização dessa extensão do Lambda em diferentes funções. Tanto a dissociação do código com finalidades diferentes quanto a reutilização do código já estão alinhadas com as melhores práticas para criar funções do Lambda.

Fazer ping em um microsserviço em cada invocação do Lambda aumenta o tráfego e a latência da rede. As implementações de circuit-breaker se beneficiam de uma camada de cache para armazenar o estado dos microsserviços. A extensão Lambda busca o status de um microsserviço de um banco de dados e armazena o resultado na memória por um tempo especificado, evitando a gravação em disco. A função Lambda verifica o cache da extensão antes de executar o ping no microsserviço, reduzindo o tráfego de rede. As extensões do Lambda são uma ferramenta ideal para criar uma camada de cache para funções do Lambda, pois seu cache na memória o torna mais seguro, fácil de gerenciar e mais eficiente devido à maior disponibilidade em comparação com a chamada de um recurso de rede.

Visão geral

Architecture Overview

  1. O processo da função principal gerencia o evento após cada invocação do AWS Lambda. Antes de realizar qualquer chamada externa nos componentes externos, ele escuta os eventos HTTP POST do processo de extensão do Lambda para buscar o último status dos circuitos.
  2. O processo de extensão fornece o estado do circuito para o processo principal via HTTP POST.
    1. A extensão verifica seu cache interno e retorna um valor válido, se disponível. Caso contrário, lê o estado dos circuitos na tabela do DynamoDB e atualiza o cache.
    2. Finalmente, o processo de extensão retorna o estado dos circuitos para a função principal por meio de uma resposta de chamada da API.
    3. Devido ao ciclo de vida das extensões do Lambda, esse processo ocorre periodicamente para manter o cache local atualizado até que o ambiente de execução seja encerrado.
  3. Se o circuito estiver no estado ABERTO, o processo da função principal executará chamadas nos microsserviços externos, caso contrário, o processo retornará uma resposta local.
  4. Um evento do Amazon EventBridge invoca periodicamente um Lambda responsável pela atualização dos estados do circuito.
  5. Essa função do Lambda executa as validações necessárias para determinar o status dos diferentes microsserviços remotos (circuitos) com um ponto de entrada do Amazon API Gateway.
  6. A função Lambda grava o resultado do processo de verificação na tabela do DynamoDB.

Passo a passo

Os seguintes pré-requisitos são necessários para concluir o passo a passo:

  • Uma conta ativa da AWS
  • AWS CLI 2.15.17 ou posterior
  • AWS SAM CLI 1.116.0 ou posterior
  • Git 2.39.3 ou posterior
  • Python 3.12

Configuração inicial

  1. Clone o código do GitHub em uma máquina local:
    git clone https://github.com/aws-samples/implementing-the-circuit-breaker-pattern-with-lambda-extensions-and-dynamodb.git
  2. Para instalar os pacotes, utilize um ambiente virtual:
    python -m venv circuit_breaker_venv && source circuit_breaker_venv/bin/activate
  3. Para preparar os serviços para implantação, execute o seguinte comando do AWS Serverless Application Model (SAM):
    sam build
  4. Para implantar os serviços, use esse comando especificando o perfil da AWS CLI (no arquivo de configuração na pasta .aws) da conta da AWS para implantar os serviços em:
    sam deploy --guided --profile <AWSProfile>

    Responda às perguntas conforme apropriado.

  5. Você pode implantar alterações locais subsequentes no código com:
    sam build 
    sam deploy

Testando e ajustando a solução

A função Lambda que atualiza o estado no DynamoDB é executada a cada minuto, conforme especificado pelo modelo. Depois que a função for executada pela primeira vez após 1 minuto, a entrada do DynamoDB contendo o status (“OPEN” ou “CLOSED”) estará pronta. Como a API simulada faz parte da pilha, o status é “ABERTO”.

Você pode invocar a função My Microservice Lambda manualmente para ver:

Response

A função Lambda que atualiza o estado no DynamoDB é invocada com uma regra do EventBridge que especifica a URL e a ID do serviço a ser monitorado. Ao criar uma nova regra do EventBridge com o URL correto e um novo ID, você pode usar o modelo do AWS SAM para monitorar vários serviços.

Para adicionar uma nova regra do EventBridge, adicione isso ao modelo:

NewEventRule:
    Type: AWS::Events::Rule
    Properties:
      Description: Event rule to trigger the Lambda function with a JSON payload
      ScheduleExpression: rate(1 minute) 
      State: ENABLED
      Targets:
        - Arn: !GetAtt UpdatingStateLambda.Arn
          Id: TargetFunction
          Input: '{ "URL": "https://aws.amazon.com/", "ID": "NewMicroservice"}'  # Add the JSON payload here

  MyPermissionForNewEventRule:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref UpdatingStateLambda
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt NewEventRule.Arn

Na função Lambda que contém a lógica de negócios, adicione as seguintes variáveis de ambiente. No entanto, para casos mais complexos com vários microsserviços a serem monitorados, é recomendável usar o AWS Config. Usando o AWS Config, as configurações das funções do Lambda podem ser armazenadas para permitir um controle mais granular do que com variáveis de ambiente.

Environment:
        Variables:
          service_name: "NewMicroservice"

Você pode ajustar a lógica dessa função do Lambda alterando o código em my-microservice/lambda-handler.py ou diretamente na seção Lambda do AWS Management Console.

Se você acabar usando sua própria função Lambda para usar a extensão Lambda do circuit-breaker, inclua a extensão do circuit-breaker como uma camada:

BusinessLogicMicroservice:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: business-logic-microservice/
      Handler: lambda_function.lambda_handler
      MemorySize: 128
      Policies:
      - DynamoDBCrudPolicy:
          TableName: !Ref CircuitBreakerStateTable
      Timeout: 100
      Runtime: python3.8
      Layers:
      - !Ref CircuitBreakerExtensionLayer

Circuit-breaker em estado fechado

Até agora, o aplicativo de amostra apresenta apenas um estado de circuit-breaker aberto sinalizando um microsserviço em funcionamento. Esta seção simula um microsserviço que não responde para testar o comportamento do sistema com um estado de circuit-breaker fechado.

  1. Edite as variáveis de ambiente da função MyMicroservice Lambda na linha 47 do arquivo template.yaml e a URL da entrada para o Lambda atualizando o estado na regra de evento na linha 107 para um domínio que atinge o tempo limite, como “https://aws.amazon.com:81/”.
    API_URL: "https://aws.amazon.com:81/"
    Input: '{ "URL": "https://aws.amazon.com:81/", "ID": "MyMicroservice"}'
  2. Implante essas alterações:
    sam build
    sam deploy

A regra do evento invoca a função Lambda, atualizando o estado a cada minuto. Para ver a saída dessa função do Lambda, invoque-a manualmente:

Execution result

Essa função do Lambda altera a entrada do DynamoDB desse URL para:

DynamoDB entry

A função MyMicroservice Lambda recebe as entradas do DynamoDB para o status via HTTP da extensão Circuit-Breaker Lambda e continua com a lógica seguindo um estado fechado. O resultado de invocar o Lambda manualmente é:

Manual output

Isso mostra o padrão circuit-breaker funcionando conforme o esperado. No estado de atualização do Lambda, o tempo necessário para a função Lambda lançar uma exceção de timeout é definido como 4 segundos e pode ser ajustado ao caso de uso.

requests.get(API_URL, headers=headers, timeout=4)

Limpeza

Para excluir todos os recursos dessa stack, execute:

sam delete –stack-name new-circuit-breaker-sam-stack

Segurança

O modelo do AWS SAM fornecido não fornece uma Amazon Virtual Private Cloud (VPC) para hospedar os recursos. Integre os recursos em uma configuração de rede apropriada se você a estiver usando em aplicativos de produção.

A solução tem características de auditabilidade, pois as chamadas para o circuit-breaker e para os microsserviços são registradas no grupo de log do Amazon CloudWatch. O log de auditoria é criptografado usando o AWS Key Management Service.

Para monitorar a segurança da sua conta com a solução, use o Amazon GuardDuty, o AWS CloudTrail, o AWS Config e o AWS WAF para o API Gateway.

Conclusão

O padrão circuit-breaker é uma ferramenta poderosa para ajudar a garantir a resiliência e a estabilidade de aplicativos serverless. As extensões Lambda são uma boa opção para sua implementação, conforme demonstrado neste exemplo. Com a extensão e o código Lambda fornecidos, você pode incorporar o padrão circuit-breaker em seus aplicativos e personalizá-lo para atender às suas necessidades específicas, ajudando a garantir um sistema robusto e confiável.

Para obter mais recursos de aprendizado serverless, visite Serverless Land.

Este blog é uma tradução do conteúdo original em inglês (link aqui).

Biografia dos Autores

Alan Oberto Jimenez, Senior Cloud Application Architect
Tobias Drees, Cloud Application Architect

Biografia do tradutor

Rodrigo Peres é Arquiteto de Soluções na AWS, com mais de 20 anos de experiência trabalhando com arquitetura de soluções, desenvolvimento de sistemas e modernização de sistemas legados.

Biografia do revisor

Daniel Abib é arquiteto de soluções sênior 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 segurança. Ele trabalha apoiando clientes corporativos, ajudando-os em sua jornada para a nuvem.

https://www.linkedin.com/in/danielabib/