AWS Builder Center
WebSockets Serverless em Hiperescala: Comunicação Bidirecional com Amazon API Gateway e EventBridge

WebSockets Serverless em Hiperescala: Comunicação Bidirecional com Amazon API Gateway e EventBridge

O artigo detalha a construção de backends em tempo real (real-time) utilizando o Amazon API Gateway para sustentar WebSockets na borda da rede. Focado em engenheiros seniores, o material demonstra como rastrear conexões no Amazon DynamoDB e orquestrar fan-outs assíncronos de bilhões de mensagens empregando o Amazon EventBridge e adaptadores de entrega baseados na Arquitetura Hexagonal, garantindo escalabilidade ilimitada sem comprometer a elasticidade da computação.

Systems Architect na NTT DATA, Estudante Doutorado na MUST University, 12x AWS e ASD & ADHD
Aplicações modernas e colaborativas exigem atualizações bidirecionais em tempo real para painéis de controle, plataformas de negociação financeira e sistemas de notificação. No entanto, a implementação tradicional de conexões TCP de longa duração (WebSockets) diretamente em contêineres ou pods Kubernetes destrói a elasticidade inerente à nuvem. Processos de implantação contínua (Rolling Updates) e escalonamento horizontal forçam a queda abrupta de milhares de soquetes ativos, gerando tempestades de reconexão (reconnection storms) que sobrecarregam o plano de controle e derrubam bancos de dados. A implementação de WebSockets serverless através do Amazon API Gateway resolve essa deficiência estrutural de forma matemática. Ao delegar a sustentação física da conexão TCP à infraestrutura gerenciada de borda da AWS e orquestrar a lógica de entrega via Amazon EventBridge, os arquitetos de software mantêm a camada de computação estritamente apátrida (stateless). Esta topologia blinda o núcleo de processamento contra a volatilidade da rede cliente, entregando escalabilidade infinita e latência sub-milissegundo para sistemas críticos em produção.

Pré-requisitos

A construção desta malha de comunicação assíncrona exige domínio avançado sobre roteamento de rede e modelos computacionais orientados a eventos. A infraestrutura deve ser provisionada deterministicamente utilizando o Terraform versão 1.7.0 ou superior e o provedor HashiCorp AWS versão 5.40.0. A camada de resolução lógica necessita do Python 3.12, acoplado à biblioteca boto3 versão 1.34.0 para comunicação com a API de gerenciamento da AWS, e aws-lambda-powertools versão 2.34.0. Privilégios administrativos no AWS IAM são exigidos para conceder as permissões explícitas de execute-api:ManageConnections e configurar regras de barramento corporativo.

Passo a Passo

Delegação de Estado TCP na Borda (Stateless Connection Offloading)

A construção da resiliência em tempo real inicia transferindo a responsabilidade da manutenção da conexão para o Amazon API Gateway (Protocolo WebSocket) e ancorando o metadado relacional no Amazon DynamoDB. O raciocínio arquitetônico primordial determina que os microsserviços de negócio jamais devem manter estado de rede em memória RAM local. Quando o dispositivo cliente inicia o aperto de mão (handshake) do WebSocket, o API Gateway invoca uma função AWS Lambda designada à rota $connect. Esta função inspeciona o token de autorização, extrai o identificador do usuário e persiste um mapeamento direto entre o UserId e o identificador efêmero do soquete (ConnectionId) fornecido pela infraestrutura da AWS. Operando com faturamento de capacidade sob demanda (Pay-Per-Request), o DynamoDB rastreia perfeitamente as conexões concorrentes de um mesmo usuário utilizando uma chave primária composta, assegurando que múltiplos dispositivos recebam a mesma transmissão simultaneamente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
resource "aws_apigatewayv2_api" "websocket_api" {
name = "enterprise-realtime-api"
protocol_type = "WEBSOCKET"
route_selection_expression = "$request.body.action"
}

resource "aws_dynamodb_table" "connection_state" {
name = "WebSocketConnections"
billing_mode = "PAY_PER_REQUEST"
hash_key = "UserId"
range_key = "ConnectionId"

attribute {
name = "UserId"
type = "S"
}

attribute {
name = "ConnectionId"
type = "S"
}

tags = {
Domain = "EdgeConnectivity"
}
}
Uma vez que o banco de dados rastreia os soquetes ativos na borda da infraestrutura, como garantimos que eventos originados em domínios de negócios isolados alcancem esse repositório sem acoplar os microsserviços centrais à tecnologia específica de WebSockets?

Coreografia de Eventos e Fan-out Assíncrono

Garantimos o isolamento de domínio implementando uma arquitetura de coreografia orientada a eventos utilizando o Amazon EventBridge acoplado a filas do Amazon SQS. O princípio da Arquitetura Hexagonal dita que um microsserviço de faturamento, por exemplo, deve ignorar completamente a existência de interfaces de usuário ou protocolos de rede bidirecionais. Quando uma transação é compensada, o domínio de faturamento publica um Evento de Integração puro (como InvoicePaidEvent) no barramento corporativo. O EventBridge atua como o roteador inteligente. Configuramos uma regra de filtragem para capturar eventos sinalizados para notificação de interface e os roteamos para uma fila SQS exclusiva de notificações. Esta camada de enfileiramento amortece picos massivos de processamento simultâneo (Fan-out), protegendo as funções Lambda subsequentes contra estrangulamentos de concorrência e assegurando que nenhuma notificação seja perdida durante flutuações temporárias da rede.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import json
import boto3
from dataclasses import dataclass
from aws_lambda_powertools import Logger

logger = Logger(service="BillingDomain")
eventbridge = boto3.client("events")

@dataclass(frozen=True)
class InvoicePaidEvent:
user_id: str
invoice_id: str
amount: float

class BillingDomainService:
def process_payment(self, event: InvoicePaidEvent) -> None:
logger.info(f"Pagamento processado e validado para a fatura {event.invoice_id}")

# O payload contém exclusivamente semântica de negócios
payload = {
"user_id": event.user_id,
"type": "INVOICE_PAID",
"data": {"amount": event.amount, "status": "CLEARED"}
}

eventbridge.put_events(
Entries=[{
"Source": "com.enterprise.billing",
"DetailType": "RealTimeNotification",
"Detail": json.dumps(payload),
"EventBusName": "enterprise-bus"
}]
)
Quando a fila consumidora recebe este evento puro de domínio perfeitamente roteado, como o adaptador de entrega traduz essa carga útil abstrata na chamada de rede física necessária para atingir a tela exata do usuário conectado sem colapsar sob falhas de conexão silenciosas?

Adaptador de Entrega de Borda e Limpeza de Estado

Executamos a tradução da rede orquestrando um adaptador secundário que consome a fila SQS, consulta o DynamoDB em busca de ponteiros de conexão e realiza a postagem direcionada utilizando a API Management do API Gateway. A complexidade técnica crítica nesta etapa envolve a gestão do ciclo de vida das conexões obsoletas (Stale Connections). Em redes móveis, os clientes frequentemente perdem o sinal ou fecham aplicativos abruptamente sem enviar o quadro de controle de desconexão (TCP FIN). O DynamoDB manterá um ConnectionId fantasma. Quando o adaptador Python invocar o método post_to_connection do boto3, o API Gateway identificará que o soquete físico não existe mais e retornará uma exceção HTTP 410 Gone. O código deve obrigatoriamente capturar a exceção GoneException e deletar agressivamente o registro do banco de dados na mesma transação. Isso impede o vazamento de memória lógica e previne o consumo inútil de capacidade de leitura nas próximas transmissões destinadas àquele usuário.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import os
import json
import boto3
from botocore.exceptions import ClientError
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.data_classes import SQSEvent

logger = Logger(service="WebSocketDelivery")
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table(os.getenv("CONNECTIONS_TABLE"))

# O endpoint requer o protocolo HTTPS e o estágio de implantação da API
management_api = boto3.client(
"apigatewaymanagementapi",
endpoint_url=os.getenv("APIGW_MANAGEMENT_ENDPOINT")
)

class NotificationDeliveryAdapter:
def push_to_active_devices(self, user_id: str, payload: dict) -> None:
response = table.query(
KeyConditionExpression=boto3.dynamodb.conditions.Key('UserId').eq(user_id)
)

for item in response.get('Items', []):
connection_id = item['ConnectionId']
try:
management_api.post_to_connection(
ConnectionId=connection_id,
Data=json.dumps(payload).encode('utf-8')
)
logger.info(f"Dados transmitidos com sucesso para o soquete {connection_id}")

except ClientError as e:
# Interceptação vitalícia da conexão silenciosamente perdida
if e.response['Error']['Code'] == 'GoneException':
logger.warning(f"Soquete obsoleto {connection_id}. Executando expurgo.")
table.delete_item(
Key={'UserId': user_id, 'ConnectionId': connection_id}
)
else:
raise e

delivery_adapter = NotificationDeliveryAdapter()

@logger.inject_lambda_context
def lambda_handler(event: dict, context: dict) -> None:
sqs_event = SQSEvent(event)
for record in sqs_event.records:
body = json.loads(record.body)
detail = body.get("detail", {})

target_user = detail.get("user_id")
if target_user:
delivery_adapter.push_to_active_devices(target_user, detail)

Solução de Problemas Comuns

Um incidente operacional frequente durante a implantação de WebSockets no API Gateway é o recebimento do erro ForbiddenException imediatamente ao tentar executar o post_to_connection a partir da função Lambda. Este sintoma não indica falha de rede lógica, mas sim uma negação de autorização (IAM Denial) ou formatação incorreta do endpoint da API. Certifique-se de que a aws_iam_role_policy da Lambda consumidora possua a permissão execute-api:ManageConnections apontando para o ARN (Amazon Resource Name) específico da API WebSocket. Adicionalmente, verifique o parâmetro endpoint_url fornecido ao inicializar o cliente Boto3. Diferente dos endpoints padrão da AWS, o Management API exige obrigatoriamente que a URL contenha o estágio de implantação no caminho (por exemplo, https://{api-id}.execute-api.{region}.amazonaws.com/production).
Outro gargalo severo manifesta-se sob o formato de estrangulamento (ThrottlingException) durante picos vertiginosos de notificações globais. A Management API do API Gateway possui cotas estritas de chamadas por segundo. Quando o EventBridge roteia milhares de mensagens para o SQS simultaneamente, o consumo agressivo dos lotes pelas instâncias Lambda superará o limite da API. Mitigue esse comportamento reduzindo o BatchSize da integração SQS-Lambda e configurando um limite de concorrência reservada (Reserved Concurrency) na função de entrega, forçando a infraestrutura a nivelar o pico e processar a carga dentro dos limites de segurança impostos pela AWS.

Conclusão

A delegação do estado das conexões TCP ao Amazon API Gateway redefine as capacidades de comunicação assíncrona corporativa. Ao acoplar essa borda inteligente a mecanismos robustos de roteamento como EventBridge e SQS, as organizações dissolvem completamente o estrangulamento operacional causado por infraestruturas de WebSockets monolíticas. O encapsulamento lógico das lógicas de expurgo garante bancos de dados otimizados. Para arquitetos planejando a expansão rumo à adoção de federações de dados (Data Federation) em arquiteturas frontend, este padrão deve evoluir naturalmente para a adoção do AWS AppSync, substituindo as transmissões bidirecionais puras por Subscrições GraphQL fortemente tipadas e ancoradas em resolução automática de atualizações transacionais.

Referências

Hohpe, G., & Woolf, B. (2004). Enterprise integration patterns: Designing, building, and deploying messaging solutions. Addison-Wesley Professional.
Kleppmann, M. (2017). Designing data-intensive applications: The big ideas behind reliable, scalable, and maintainable systems. O'Reilly Media.
Amazon Web Services. (2022). Building serverless WebSockets architectures using API Gateway. AWS Architecture Center. https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html 
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article