Lab 40 — Teste de carga e o gargalo real
O problema, e a empresa que o tem
A Cadência chega a este laboratório depois do L06 (escala automática por métrica de chegada) e do L36 (retry com jitter e disjuntor para o gateway de pagamento). A arquitetura é a mesma: ALB, ECS Fargate com autoscaling, RDS Postgres em sub-rede privada, cache de catálogo no ElastiCache. Ela publica sem indisponibilidade e absorve a variação diária de tráfego. O que falta não é uma peça nova — é saber até onde ela aguenta.
Um distribuidor regional propôs levar a Cadência de 30 para até 300 lojas em doze meses, com um contrato que exige compromisso de capacidade: erro abaixo de 0,5% e p99 abaixo de 1 s até uma taxa de requisição declarada no anexo técnico. Alguém precisa assinar aquele número. Na reunião, a pergunta foi "quantos usuários simultâneos a arquitetura aguenta?", e a resposta sincera foi "não sabemos, mas o autoscaling está configurado" — que não é um número, é uma esperança sobre um comportamento nunca observado.
A campanha do L06 chegou a 260 requisições por segundo e funcionou. O contrato novo pede validação a uma taxa maior, sustentada por horas, não vinte minutos de pico. Ninguém na equipe sabe dizer, com dado, se a arquitetura degrada aos poucos perto desse número ou colapsa de uma vez — e a diferença entre as duas respostas é o tipo de cláusula que se assina no contrato.
O que este laboratório NÃO é
Não é chaos engineering completo — derrubar uma AZ de propósito com hipótese escrita é o L57, e mede resiliência a falha, não capacidade sob carga crescente. Também não é uma auditoria de performance de cada camada: o objetivo é achar UM número (o teto) e UM gargalo, corrigir esse ponto, e devolver o restante intocado. Otimizar tudo "por garantia" é exatamente o antipadrão que a seção de anti-padrões nomeia.
O que você vai conseguir fazer
Objetivos verificáveis: cada um se prova com um comando ou uma leitura de métrica na seção de implantação, não com a sensação de ter entendido o método.
- Desenhar um degrau de carga com critério de estabilização declarado, distinguindo saturação real de pico transitório.
- Rodar o mesmo teste sem criar um único pedido ou uma única cobrança real.
- Ler as quatro métricas certas — CPU da task, DatabaseConnections, taxa de acerto do cache, estado do disjuntor — no mesmo eixo de tempo.
- Descartar, com dado, três das quatro camadas como gargalo antes de tocar em qualquer configuração.
- Derivar por que o sucesso do autoscaling do L06 é, ele mesmo, o que aperta o RDS.
- Configurar o RDS Proxy com MaxConnectionsPercent derivado de uso monitorado, não copiado de exemplo.
- Repetir o degrau que antes quebrava e provar que só a correção aplicada mudou o resultado.
- Publicar a curva de carga (requisição por segundo × p99 × erro) como artefato versionado, não como número decorado numa planilha.
O que a certificação cobra disto
| Conceito | Certificação | Como aparece aqui | O que dominar |
|---|---|---|---|
| Metodologia de teste de carga em degraus | SAA-C03, DOP-C02 | critério de estabilização por degrau, nunca carga direto no pico | por que pico direto confunde saturação real com pico transitório |
| PERF05-BP04 — Load test your workload | DOP-C02, SAA-C03 | o laboratório segue o processo: ambiente, monitoramento, cenário, execução, análise | que testar carga é prática nomeada do pilar de eficiência de desempenho, não recomendação vaga |
| RDS Proxy e connection pooling | DVA-C02, SAA-C03 | MaxConnectionsPercent, DatabaseConnectionsBorrowLatency | que o teto físico do banco é dividido entre o proxy e a aplicação, e que a folga recomendada é de 30% sobre o uso monitorado |
| Escala automática de uma camada vs teto de outra | SAA-C03, SOA-C02 | ECS escala; RDS não acompanha na mesma proporção | que "esta camada escala" não implica "o sistema inteiro escala" |
| Disjuntor sob carga concorrente | DOP-C02 | o disjuntor do L36 é um dos quatro sinais monitorados no teste | diferenciar degradação real da dependência de saturação induzida pela própria carga de teste |
| Métricas do ElastiCache sob carga | SAA-C03 | taxa de acerto de cache como sinal antecedente, não o gargalo final | que queda de acerto empurra carga para a camada seguinte, com atraso |
| Painéis correlacionados do CloudWatch | SOA-C02, DOP-C02 | um painel, quatro sinais, mesmo eixo de tempo | que ler métricas isoladas atrasa o diagnóstico do gargalo real |
Onde isto costuma ser cobrado errado
A pergunta clássica dá um número de requisições por segundo e pede se a arquitetura "aguenta". A resposta certa nunca é sim ou não isolado: é perguntar de volta qual componente foi medido. "A arquitetura aguenta 300 req/s" só é uma frase completa quando alguém diz qual das quatro camadas foi observada naquela taxa — sem isso, é opinião com aparência de medição.
Requisitos, e como cada um muda o desenho
Requisito não funcional que não aparece numa linha de configuração é intenção. A coluna da direita é onde cada um deixou marca.
| Requisito | Valor declarado | O que ele decide no desenho |
|---|---|---|
| Certificar capacidade antes de assinar o contrato | teto medido, não estimado | obriga a existência de um gerador de carga controlado e repetível, versionado no repositório |
| Não afetar cliente real durante o teste | zero pedido real criado, zero cobrança real disparada | ALB do teste aponta para réplica de staging, e a cobrança vai para o simulador do L36 |
| Separar saturação real de pico transitório | degrau que estabiliza antes de subir | critério de estabilização declarado (variância de p99 abaixo de um limiar por minutos seguidos), não tempo fixo arbitrário |
| Achar QUAL camada satura, não só QUE alguma satura | quatro sinais no mesmo eixo de tempo | um painel correlacionado do CloudWatch, não quatro widgets lidos em momentos diferentes |
| Corrigir só o que os dados apontaram | uma correção por rodada de teste | proíbe mexer em ECS, cache e disjuntor nesta rodada — decisão registrada, não esquecimento |
| Resultado repetível ao longo do tempo | o teste roda de novo depois de mudança relevante | script de carga versionado, não execução manual ad-hoc — habilita o L52 e o L54 |
| Folga de conexão depois da correção | pelo menos 30% acima do uso monitorado | MaxConnectionsPercent do RDS Proxy derivado da medição, não copiado de um exemplo |
A hipótese do mix de tráfego é a parte que mais gente pula
Gerar carga só na rota de leitura mais barata do catálogo mede uma arquitetura mais rápida do que a que existe: sem escrita concorrente, o RDS nunca vê o padrão de bloqueio e conexão de uma cobrança real. O degrau precisa reproduzir a proporção real de leitura e escrita da campanha — não a mistura mais conveniente de simular.
Arquitetura antes do teste: risco não gerenciado
Este é o desenho que a Cadência já tem, e ele é legítimo: publica sem janela desde o L03, absorve a variação diária desde o L06, e protege a cobrança externa desde o L36. Nada aqui está mal configurado. O defeito é uma ausência: nenhum componente responde "em que taxa isto quebra, e o quê quebra primeiro".
- → HTTPS, tráfego de produção real
- → encaminha ao alvo saudável
- → consulta o catálogo antes do banco
- → abre pool próprio por task
- → cobrança com retry e jitter do L36
- → CPU e contagem de tasks, sem carga controlada
- → conexões abertas, lidas isoladamente
- Fora da AWS
- Rede e entrega
- Compute
- Banco de dados
- Gestão e governança
Nada aqui está configurado errado — é a mesma arquitetura do L06 e do L36, funcionando. O defeito é uma ausência: não existe nenhum componente que responda "em que taxa isto quebra". Percorra os passos e repare que o autoscaling dá a sensação de segurança sem entregar a resposta.
- A pergunta que ninguém consegue responder com número. Um contrato novo pede um compromisso de capacidade. A resposta hoje é "o autoscaling está configurado", que não é um número — é uma esperança sobre um comportamento nunca observado sob carga real.
- O autoscaling do L06 escala uma camada, não o sistema. A política sobe tasks de 2 a 40 por `ALBRequestCountPerTarget`, e ela funciona — mas "esta camada escala" não implica "o sistema inteiro escala". As outras três camadas (banco, cache, dependência externa) têm tetos próprios que a política do ECS não enxerga.
- O risco do RDS está anotado, nunca medido. O L06 já registrou a suspeita: "`max_capacity` alto demais derruba o banco no próximo pico". Ficou como linha de risco numa tabela, não como número — e risco escrito e não medido é aposta.
- Cache e disjuntor são caixas-pretas acima do regime atual. A taxa de acerto do cache e o comportamento do disjuntor do L36 são saudáveis em 25 requisições por segundo. Ninguém sabe a forma dessas curvas em 150 ou 300 — só que hoje estão bem.
- O painel existe, mas mostra quatro filmes separados. CPU, conexões e acerto de cache aparecem em widgets distintos, sem ninguém gerando uma carga controlada que os force a se mover juntos. Sem isso, correlacionar causa e efeito depois de um incidente é reconstrução, não medição.
- A única forma de descobrir o teto, hoje, é uma campanha real quebrando. Sem instrumento de carga controlada, o primeiro teste de capacidade desta arquitetura é o próprio evento que a empresa mais precisa que dê certo — o pior momento possível para aprender o limite.
A forma mais rápida de "responder" essa pergunta hoje é também a mais perigosa: alguém aponta uma ferramenta de carga direto para a URL de produção.
# O jeito rapido, e por isso o mais tentador, de tentar responder
# "quanto aguenta" — sem degrau, sem isolamento, sem simulador.
# NAO RODE isto contra producao. E o antipadrao que este laboratorio existe
# para substituir.
ab -n 50000 -c 300 https://api.cadencia.exemplo/pedidos
# Cada pedido criado aqui e um pedido REAL. Cada cobranca tentada chega
# ao gateway de pagamento DE VERDADE. E o pico e instantaneo — nao ha como
# separar saturacao real de latencia de partida a frio.A mesma aposta em duas direções opostas de custo
Assinar um compromisso de capacidade sem medir é apostar o contrato num número que ninguém verificou. Medir batendo direto em produção, sem isolamento, é apostar dinheiro real do cliente e a reputação da marca num script de teste. As duas são a mesma falta de método, só com o risco apontando para lados diferentes — e a resposta para as duas é o degrau controlado das próximas seções.
Arquitetura para o teste: degrau isolado, painel correlacionado, uma correção
Cada peça nova abaixo rastreia a um requisito da seção anterior. O ECS, o cache e o disjuntor não mudam neste desenho — é o próprio teste que prova, com dado, que eles não precisavam mudar.
- → dispara cada degrau e aguarda estabilizar
- → carga sintética em RPS crescente
- → encaminha ao alvo saudável
- → consulta o catálogo antes do banco
- → abre pool por task, como antes
- → multiplexa em conexões físicas limitadas
- → credencial de autenticação no banco
- → cobrança simulada, sem efeito real
- → DatabaseConnections e borrow latency
- → CPU e contagem de tasks no mesmo instante
- → taxa de acerto no mesmo instante
- Integração de apps
- Compute
- Fora da AWS
- Rede e entrega
- Banco de dados
- Segurança e identidade
- Gestão e governança
A diferença estrutural não é "mais uma caixa": é um executor de carga isolado do cliente real, um painel que lê as quatro camadas no mesmo instante, e o RDS Proxy — a única peça nova, porque foi a única que o dado apontou. ECS, cache e disjuntor saem do teste sem mudança nenhuma.
- A carga sobe em degraus, e cada um espera estabilizar. O orquestrador aplica uma fração fixa de aumento (por exemplo, 1,5×) e segura ali até a variância do p99 cair abaixo do critério declarado por alguns minutos seguidos — nunca sobe direto para o pico esperado.
- O ambiente é isolado do cliente real. O ALB do teste aponta para uma réplica de staging, e a cobrança vai para o simulador do parceiro que o L36 já construiu — nenhum pedido real é criado, nenhuma cobrança real é disparada durante a medição.
- ECS escala, e é exatamente por isso que o proxy existe. Conforme o degrau sobe, a política do L06 aumenta o número de tasks — funcionando como projetado. Sem o proxy, cada task nova abriria seu próprio pool, e o total de conexões físicas cresceria junto.
- O painel correlacionado mostra três camadas que NÃO quebraram. No mesmo eixo de tempo, a CPU da task nunca passa de um patamar moderado, a taxa de acerto do cache se mantém estável, e o disjuntor do L36 permanece fechado do início ao fim — três hipóteses descartadas com dado, não por suposição.
- O proxy multiplexa, e o teto físico deixa de crescer com a frota. `DatabaseConnections` no RDS deixa de acompanhar o número de tasks: o proxy reduz N pools de aplicação a um número menor de conexões físicas, reutilizadas entre requisições — é a mecânica que rompe o vínculo entre escalar ECS e saturar RDS.
- A credencial vem do Secrets Manager, não da task. O RDS Proxy exige autenticação por segredo gerenciado — é um pré-requisito do serviço, e reaproveita a rotação que a arquitetura da Cadência já tem para o banco.
- O teto muda, e por isso o teste se repete. O número medido depois da correção vale para ESTA versão do sistema. Qualquer mudança de código, de tráfego ou de configuração pode mover o teto de novo — o teste não é um relatório único, é um passo que se repete (L52, L57).
A diferença estrutural em relação ao desenho anterior não é o executor de carga isolado — ele só produz o dado. A diferença é o RDS Proxy, porque foi a única peça que o dado apontou como necessária.
O ajuste com maior efeito por linha alterada
Sem o proxy, cada task nova que o L06 sobe é conexão física nova no RDS — o teto do banco encolhe conforme a escala automática funciona melhor. Com o proxy multiplexando, o número de tasks para de determinar o número de conexões físicas: a mesma política de escala do L06, sem nenhuma mudança nela, deixa de esbarrar no teto do banco.
O método, ponta a ponta: como um degrau decide subir, ficar ou parar
Os nomes dos passos abaixo não são cerimônia: cada um existe para impedir uma forma específica de ler o teste errado. Pular um deles é como pular a ordem entre desregistragem e SIGTERM no L03 — o efeito colateral só aparece depois, e sem explicação óbvia.
Cada degrau publica um registro estruturado ao final, com os quatro sinais e a decisão tomada. É esse registro — não uma tela vista uma vez — que vira o artefato da curva de carga.
// O que a task .NET publica ao fim de CADA degrau. E o registro que vira
// a curva de carga, e a base para a decisao "subir, ficar ou parar".
{
"degrau": 5,
"rps_alvo": 220,
"rps_aplicado_medio": 218.4,
"duracao_segundos": 420,
"p99_ms": 812,
"taxa_erro": 0.021,
"estabilizou": true,
"sinais": {
"ecs_cpu_media_pct": 54.2,
"rds_database_connections": 187,
"rds_max_database_connections_allowed": 190,
"cache_hit_rate_pct": 89.7,
"disjuntor_aberto": false
},
// 187 de 190 e o sinal que decide este degrau: RDS perto do teto
// enquanto CPU, cache e disjuntor seguem dentro do esperado.
"decisao": "parar_e_confirmar"
}As decisões, e o que se perde em cada uma
📋 Certificar um teto de capacidade sustentável para assinar um contrato de SLA, sobre uma arquitetura ECS Fargate + RDS + cache + dependência externa já protegida por retry e disjuntor, sem afetar cliente real durante a medição.
O degrau separa saturação real de pico transitório sem exigir uma segunda arquitetura de teste: reaproveita o Terraform da produção. O painel correlacionado é o que transforma "algo saturou" em "isto saturou primeiro", que é a pergunta que o contrato precisa de resposta. E corrigir só o ponto confirmado mantém o teste repetível — a próxima rodada compara contra uma linha de base que não mudou em três lugares ao mesmo tempo.
Alt: Confiar só no autoscaling configurado — escala uma camada, não o sistema — é exatamente a crença que este laboratório desmonta com dado.
Alt: Injeção de falha completa (derrubar uma AZ de propósito) — responde a uma pergunta diferente, sobre resiliência a falha, não sobre capacidade sob carga crescente. É o L57, e ele depende deste.
Alt: Capacity planning teórico, somando specs de cada serviço no papel — não captura efeitos de multiplicação como conexão por task — esse efeito só aparece sob carga real, correndo contra o banco de verdade.
Alt: Contratar teste de carga como serviço, sem instrumentar o próprio painel — devolve um número sem dizer ONDE ele quebrou — você sabe o teto e não sabe o que corrigir, então a próxima rodada começa do zero.
| Decisão | Escolha | Alternativas | Motivo | O que se perde |
|---|---|---|---|---|
| Forma da carga | degraus com estabilização | pico direto; rampa contínua sem patamar | separa saturação real de pico transitório | o teste demora mais — cada degrau espera estabilizar antes de subir |
| Ambiente do teste | réplica de staging + simulador do L36 | produção real; conta separada dedicada a carga | zero pedido e zero cobrança reais durante a medição | staging pode divergir de produção em dado e volume, e isso tem de ser verificado à parte |
| Leitura dos sinais | painel único correlacionado | quatro widgets separados, lidos um de cada vez | permite descartar camadas por dado, no mesmo instante | exige montar o painel antes do teste — trabalho que não aparece no resultado final |
| Escopo da correção | só o ponto que o dado apontou (RDS Proxy) | ajustar as quatro camadas de uma vez, "por garantia" | mantém o teste repetível e a causa isolável na próxima rodada | um gargalo que só apareceria em degrau mais alto fica para a próxima rodada |
| Ferramenta do gerador | task .NET própria, no mesmo runtime da aplicação | k6, Locust ou ferramenta externa dedicada | reaproveita o SDK e a observabilidade já usados no resto da Cadência | ferramentas dedicadas têm recursos prontos (relatório, distribuição geográfica) que este script não tem |
A dívida que este laboratório cria, e que ele não paga
O número medido vale para ESTA versão do código, deste tráfego e desta configuração. Um deploy que muda o tamanho do pool, uma migration que altera uma consulta quente, ou um crescimento orgânico de tráfego movem o teto sem avisar. O teste não é um relatório único — é um passo que precisa se repetir, e automatizar essa repetição é o L52 e o L54.
Construir: RDS Proxy, a única correção
A trava central desta correção é o mesmo raciocínio de menor privilégio que o resto da série usa para IAM, aplicado a conexão de banco: o proxy decide quantas conexões físicas existem, e a aplicação para de decidir isso sozinha, multiplicada pelo número de tasks.
# rds-proxy.tf — a UNICA peca nova que o teste de carga justificou
# RDS Proxy exige a credencial do banco no Secrets Manager — nunca em
# variavel de ambiente da task. Reaproveita o segredo que o RDS ja usa.
resource "aws_db_proxy" "api" {
name = "${var.projeto}-proxy"
engine_family = "POSTGRESQL"
role_arn = aws_iam_role.rds_proxy.arn
vpc_subnet_ids = var.subnets_privadas
require_tls = true
auth {
auth_scheme = "SECRETS"
secret_arn = aws_secretsmanager_secret.db_credencial.arn
iam_auth = "DISABLED"
}
}
resource "aws_db_proxy_default_target_group" "api" {
db_proxy_name = aws_db_proxy.api.name
connection_pool_config {
# Medido no teste: pico de uso monitorado foi por volta de 62% do
# max_connections da instancia. A documentacao da AWS recomenda
# MaxConnectionsPercent >= 1,3 vezes o uso monitorado (nao +30 pontos
# percentuais) — aqui, 1,3 x 62% = ~81%, e o proxy redistribui cota
# de conexao entre nos internamente sem aviso previo.
max_connections_percent = 90
max_idle_connections_percent = 45
connection_borrow_timeout = 120
}
}
resource "aws_db_proxy_target" "api" {
db_proxy_name = aws_db_proxy.api.name
target_group_name = aws_db_proxy_default_target_group.api.name
db_instance_identifier = aws_db_instance.api.identifier
}
# Menor privilegio: o proxy so precisa buscar o segredo especifico dele.
# GetSecretValue aceita recurso, entao "*" nao se justifica aqui.
data "aws_iam_policy_document" "rds_proxy_segredo" {
statement {
effect = "Allow"
actions = ["secretsmanager:GetSecretValue"]
resources = [aws_secretsmanager_secret.db_credencial.arn]
}
}
output "endpoint_proxy" {
value = aws_db_proxy.api.endpoint
description = "A aplicacao aponta para AQUI, nao mais para o endpoint direto do RDS"
}
O cutover não é instantâneo, e a ordem importa
Trocar a string de conexão da task para o endpoint do proxy exige um rollout (do L03) — não uma edição manual. Mantenha o security group do RDS aceitando tanto o proxy quanto as tasks até o rollout completar, e só então remova o acesso direto: cortar a rota antiga cedo demais derruba a metade da frota que ainda não recebeu a revisão nova.
Construir: o executor de carga, isolado por desenho
O orquestrador é deliberadamente simples: uma máquina de estados que dispara um degrau, espera, avalia o critério de estabilização e decide o próximo passo. A parte que importa não é a ferramenta — é que ela só consegue falar com o ambiente isolado.
# executor-de-carga.tf — a role do executor NAO tem acesso a nada de
# producao. E a garantia estrutural do requisito de isolamento.
resource "aws_iam_role" "executor_carga" {
name = "${var.projeto}-executor-carga"
assume_role_policy = data.aws_iam_policy_document.assume_ecs_tasks.json
}
# So publica metrica e le a URL do ambiente ISOLADO. Nao ha permissao de
# escrita em RDS, em fila ou em qualquer recurso de producao — a task nao
# fala com o banco, ela so fala HTTP com o ALB de staging.
data "aws_iam_policy_document" "executor_carga" {
statement {
effect = "Allow"
actions = ["cloudwatch:PutMetricData"]
# PutMetricData nao aceita recurso: e operacao de conta, nao de metrica
# especifica — por isso o "*" aqui, e em nenhum outro lugar da policy.
resources = ["*"]
condition {
test = "StringEquals"
variable = "cloudwatch:namespace"
values = ["Cadencia/TesteDeCarga"]
}
}
}
resource "aws_sfn_state_machine" "degraus" {
name = "${var.projeto}-degraus-de-carga"
role_arn = aws_iam_role.orquestrador.arn
# Cada estado dispara um degrau (task ECS RunTask), espera o tempo de
# estabilizacao, e o proximo estado le o registro publicado para decidir
# entre "Subir", "Confirmar" ou "Parar" — a mesma logica do metodo.
definition = templatefile("${path.module}/degraus.asl.json", {
cluster_arn = aws_ecs_cluster.principal.arn
task_definition_arn = aws_ecs_task_definition.executor_carga.arn
subnets = jsonencode(var.subnets_privadas)
})
}
Construir: o gerador de carga em degraus
O ponto do código abaixo não é a biblioteca de HTTP — é a lógica de estabilização e a decisão de continuar, confirmar ou parar. O laboratório usa uma task .NET para reaproveitar o mesmo runtime e a mesma instrumentação de OpenTelemetry do resto da Cadência; ferramentas dedicadas como k6 fazem o mesmo trabalho e valem a troca quando o time já as usa.
// GeradorDeCarga/Program.cs — aplica um degrau de carga, mede
// estabilizacao e publica o registro que decide o proximo passo.
// Nao e a aplicacao de producao: e um executavel a parte, isolado.
using System.Collections.Concurrent;
using System.Diagnostics;
using Amazon.CloudWatch;
using Amazon.CloudWatch.Model;
var alvoUrl = Environment.GetEnvironmentVariable("ALVO_URL_ISOLADO")
?? throw new InvalidOperationException("ALVO_URL_ISOLADO e obrigatorio");
var rpsAlvo = int.Parse(args[0]);
var duracaoSegundos = int.Parse(args[1]);
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
using var cw = new AmazonCloudWatchClient();
// DISPARO concorrente, nao sequencial: um laco que so espera a proxima
// requisicao terminar antes de comecar a seguinte tem throughput maximo
// de 1/latencia — sob saturacao, exatamente quando o teste mais precisa
// medir, o proprio gerador vira o gargalo. Aqui cada tick do timer DISPARA
// uma requisicao em paralelo (fire-and-track, nao fire-and-forget: o Task
// e guardado e aguardado no final) — a cadencia de disparo fica desacoplada
// da latencia de resposta.
var latencias = new ConcurrentBag<double>();
var erros = 0;
var emVoo = new ConcurrentBag<Task>();
var cronometro = Stopwatch.StartNew();
var intervaloEntreDisparos = TimeSpan.FromSeconds(1.0 / rpsAlvo);
using var limitador = new PeriodicTimer(intervaloEntreDisparos);
async Task DispararUmaAsync()
{
var inicio = Stopwatch.StartNew();
try
{
// A rota exercitada precisa refletir o mix real da campanha —
// so leitura mede uma arquitetura diferente da que existe (a
// hipotese declarada na abertura do modulo).
var resp = await http.GetAsync($"{alvoUrl}/api/pedidos/recentes");
if (!resp.IsSuccessStatusCode) Interlocked.Increment(ref erros);
}
catch (Exception)
{
Interlocked.Increment(ref erros);
}
latencias.Add(inicio.Elapsed.TotalMilliseconds);
}
while (cronometro.Elapsed < TimeSpan.FromSeconds(duracaoSegundos)
&& await limitador.WaitForNextTickAsync())
{
emVoo.Add(DispararUmaAsync()); // dispara e segue — nao bloqueia o proximo tick
}
await Task.WhenAll(emVoo); // so aguarda o que ainda estiver em voo ao fim do degrau
var total = latencias.Count;
var ordenadas = latencias.OrderBy(l => l).ToList();
var p99 = ordenadas[(int)(ordenadas.Count * 0.99)];
var taxaErro = (double)erros / total;
// Publica o degrau. O ORQUESTRADOR le este dado para decidir o proximo
// passo — nao ha decisao humana no laco, so na configuracao do criterio.
await cw.PutMetricDataAsync(new PutMetricDataRequest
{
Namespace = "Cadencia/TesteDeCarga",
MetricData = new List<MetricDatum>
{
new() { MetricName = "P99Ms", Value = p99, Unit = StandardUnit.Milliseconds },
new() { MetricName = "TaxaErro", Value = taxaErro, Unit = StandardUnit.None },
new() { MetricName = "RpsAplicado", Value = total / (double)duracaoSegundos, Unit = StandardUnit.CountSecond },
},
});
Console.WriteLine($"degrau={rpsAlvo}req/s p99={p99:F0}ms erro={taxaErro:P2}");
O SLA do teste não é o SLA de produção
O gerador aborta o degrau — não o teste inteiro — quando a taxa de erro ultrapassa o limite declarado. Isso evita que uma única camada saturada gaste o tempo de teste inteiro tentando "passar" um degrau que já respondeu à pergunta.
Implantar, e provar com a curva de carga
As provas abaixo seguem a ordem do método: primeiro descartar camadas saudáveis com dado, depois confirmar o gargalo, depois provar que a correção — e só ela — mudou o resultado.
| Prova | Comando | Resultado que aprova | O que reprova, e o que significa |
|---|---|---|---|
| 1 · Cache e disjuntor descartados no degrau que aperta | get-metric-data em CacheHitRate e no estado customizado do disjuntor, na janela do degrau 5 | acerto de cache acima de 85% com variação abaixo de 5 pontos; disjuntor permanece fechado (0 aberturas) | queda de acerto acima de 15 pontos aponta cache como candidato; qualquer abertura do disjuntor exige investigar o simulador antes de continuar |
| 2 · CPU descartada como gargalo | get-metric-statistics em ECSServiceAverageCPUUtilization, mesma janela | CPU média abaixo de 65% enquanto p99 e erro já pioraram | CPU acima de 85% na mesma janela reabre a hipótese de CPU, e a correção certa seria outra |
| 3 · O autoscaling funcionou como projetado | describe-scaling-activities no serviço, mesma janela | pelo menos uma atividade de escala por degrau, subindo o número de tasks | lista vazia significa que o L06 parou de funcionar, e o problema mudou de lugar antes deste laboratório começar |
| 4 · RDS confirmado com DatabaseConnections perto do teto | get-metric-statistics em DatabaseConnections contra MaxDatabaseConnectionsAllowed, mesma janela | conexões em 90% ou mais do teto no exato degrau em que p99 e erro pioram | conexões estáveis e abaixo de 70% do teto durante a piora descarta RDS — o gargalo está em outra camada, e a correção deste laboratório não se aplica |
| 5 · A correção resolve, e só ela | repetir o degrau que quebrou, agora contra o RDS Proxy, medindo p99, erro e DatabaseConnections | p99 e erro dentro do requisito no mesmo degrau que antes falhava; conexões físicas no RDS abaixo de 200, mesmo com mais tasks que antes | se o erro persistir, a causa não era conexão — reabra a investigação em vez de aumentar MaxConnectionsPercent às cegas |
Confirme o isolamento antes de aceitar qualquer número
Antes de confiar na curva de carga, confira que a contagem de pedidos reais em produção não se moveu durante a janela do teste, e que o log do simulador do L36 — não o do gateway real — registrou as tentativas de cobrança. Um número medido contra o ambiente errado é pior que nenhum número: ele parece confiável.
O que sai desta rodada é um número que se defende sozinho
A curva final não é "achamos que aguenta 300 req/s" — é "300 req/s com RDS Proxy configurado assim, medido em tal data, contra este mix de tráfego, com as outras três camadas confirmadas saudáveis no mesmo degrau". É essa cadeia de evidência, não o número isolado, que se assina num contrato.
Quebrar de propósito
Este exercício é conceitual — não reproduza a terceira falha de verdade
As duas primeiras falhas são seguras de provocar no seu ambiente isolado. A terceira — apontar o gerador para produção sem simulador — cria pedido e cobrança reais se executada. Ela está aqui para ser reconhecida pelo sintoma, não para ser reproduzida: se você precisa confirmar o comportamento, faça isso lendo o log do simulador, nunca desligando-o.
| Falha | Como provocar | Sintoma | Onde olhar | Correção |
|---|---|---|---|---|
| Carga direto no pico, sem degrau | aplique 300 req/s desde o primeiro segundo, sem passar pelos degraus intermediários | CPU, conexões e latência sobem juntas ao mesmo tempo, e nenhum sinal se distingue dos outros | o próprio registro do teste: todos os sinais cruzam o limiar no mesmo minuto | refaça com degraus e critério de estabilização — o problema é do desenho do teste, não do sistema |
| Corrigir a camada que a intuição aponta (CPU) sem confirmar | aumente CPU e memória da task e repita o mesmo degrau que falhou, sem medir DatabaseConnections antes | o teto de requisição por segundo não muda depois do ajuste, porque a camada nunca era CPU | repita a prova 4 (DatabaseConnections contra o teto) — se ainda está perto do limite, a correção foi na camada errada | siga a ordem do dado: descarte as três camadas saudáveis antes de escolher onde corrigir |
| Testar contra produção sem isolamento | aponte o ALB do gerador para o domínio de produção real, sem simulador no gateway de pagamento | pedidos reais são criados durante o teste, e o cliente real sente a latência degradada do degrau mais alto | contagem de pedidos em produção subindo durante a janela do teste; chamadas reais registradas no gateway de pagamento | nunca aponte o gerador para produção sem uma réplica isolada e sem o simulador do L36 no lugar da dependência real |
Durante um teste de carga em degraus, a CPU das tasks nunca passa de 55% e o serviço escalou de 4 para 18 tasks conforme a política do L06, mas o p99 dispara e a taxa de erro sobe no mesmo degrau. Qual é a explicação mais provável?
Segurança: o que muda quando existe um gerador de carga
| Risco | Probabilidade | Impacto | Prevenção | Detecção | Resposta |
|---|---|---|---|---|---|
| Gerador de carga com credencial que também alcança produção | média | alto | role exclusiva do executor, sem nenhuma permissão sobre recursos de produção — só a URL isolada e CloudWatch com namespace fixo | IAM Access Analyzer sobre a role do executor, revisando se ela nunca foi usada contra recurso de produção | revogar a role e reconstruir com o escopo mínimo; nenhuma permissão adicional além de PutMetricData |
| RDS Proxy com credencial fora do Secrets Manager | baixa | alto | auth_scheme = SECRETS é obrigatório na configuração do proxy — não existe caminho de variável de ambiente | AWS Config verificando que todo aws_db_proxy tem auth por segredo, não por senha embutida | girar o segredo imediatamente e recriar o proxy com a configuração correta |
| Gerador de carga exposto como vetor de negação de serviço | baixa | alto | a máquina de estados só dispara por execução autorizada de uma role específica, nunca por endpoint público | CloudTrail sobre StartExecution do Step Functions do teste, fora da janela agendada | suspender a máquina de estados e revisar quem tinha permissão de disparo |
| MaxConnectionsPercent alto demais sufoca o banco do jeito que o proxy deveria evitar | média | médio | seguir a margem de 1,3x o uso monitorado, nunca copiar o valor do exemplo | alarme em DatabaseConnectionsBorrowLatency acima de zero por período sustentado | reduzir MaxConnectionsPercent e investigar por que o uso monitorado mudou |
| Simulador do parceiro vaza para produção por engano de configuração | baixa | muito alto | flag de ambiente explícita e validada no pipeline antes de qualquer execução do teste | contagem de chamadas reais ao gateway de pagamento durante a janela do teste | abortar o teste, notificar o parceiro se houve cobrança real, e corrigir a validação antes de repetir |
Observabilidade: as perguntas que o painel tem de responder
- Qual das quatro camadas está mais perto do próprio teto agora?
- A escala automática do L06 está compensando a carga ou mascarando um problema a jusante?
- O disjuntor do L36 abriu por causa da carga de teste ou por uma falha real do parceiro simulado?
- O painel mostra os quatro sinais no mesmo instante, ou cada um em sua própria janela de tempo?
| Pergunta | Métrica ou consulta | O que significa mudar | Limiar inicial |
|---|---|---|---|
| O banco está perto do teto de conexões? | DatabaseConnections vs MaxDatabaseConnectionsAllowed, RDS | a distância entre os dois é a folga real disponível agora | alarme acima de 80% do teto |
| Existe fila para obter conexão do proxy? | DatabaseConnectionsBorrowLatency, RDS Proxy | qualquer valor sustentado acima de zero já significa fila, antes de virar erro visível | alarme em qualquer valor acima de zero por mais de 2 minutos |
| O cache ainda está absorvendo leitura? | CacheHitRate, ElastiCache | queda sustentada empurra carga para o banco com atraso, mascarando a causa raiz por alguns minutos | alarme abaixo de 80% |
| A frota está de fato escalando durante o degrau? | describe-scaling-activities, Application Auto Scaling | ausência de atividade durante um degrau em alta significa que o L06 parou de funcionar | primeira atividade em até 120 s do início do degrau |
Um painel só, não quatro
A regra prática é simples de enunciar e fácil de pular sob pressão: se você precisa abrir mais de uma aba do CloudWatch para responder "qual camada satura primeiro", o painel ainda não está pronto. As quatro métricas no mesmo gráfico, no mesmo eixo de tempo, é o que transforma correlação em conclusão.
Escala: 10, 10 mil, 1 milhão, e falha de AZ
| Volume | O que o teste revela | O que passa a doer | O que fazer |
|---|---|---|---|
| 10 req/s | nenhuma camada chega perto de saturar; o teste é dispensável neste regime | nada — é onde testar carga é puro custo de disciplina | manter o método documentado, mas rodar o teste só antes de mudança relevante |
| 300 req/s (o cenário deste laboratório) | RDS satura por conexão antes de CPU, cache ou disjuntor | o teto do sistema é menor que o teto teórico de qualquer camada isolada | RDS Proxy, e repetir o teste depois — é a resposta deste módulo |
| 10 mil req/s | uma única task geradora não produz carga suficiente, e um único RDS Proxy pode virar o novo teto | o próprio executor de carga precisa ser distribuído — várias tasks gerando em paralelo, coordenadas | gerador distribuído, RDS Proxy com mais capacidade, e reconsiderar réplica de leitura (L07) |
| 1 milhão req/s | a arquitetura da Cadência, como está, não é mais a pergunta certa | a Postgres em uma única instância deixa de ser a resposta, independentemente de proxy | fora do escopo deste laboratório — é redesenho de dados, não ajuste de conexão |
| Falha de AZ durante carga alta | não é medido por este laboratório — é um evento diferente de saturação gradual | perder capacidade justamente no pico é um cenário que o degrau sozinho não cobre | injeção de falha com hipótese escrita durante carga sustentada é o L57 |
O gerador de carga também tem teto, e ele é fácil de esquecer
A armadilha aparece muito antes de milhares de req/s se o disparo for sequencial: um laço que só dispara a próxima chamada depois de a anterior responder tem throughput MÁXIMO de 1/latência, não do RPS configurado — sob p99 de 812 ms, um laço sequencial não sustentaria nem 2 req/s, muito menos os 220 deste degrau. É por isso que o gerador acima dispara por tick de temporizador, sem esperar a resposta anterior — desacopla a cadência de disparo da latência do servidor. Mesmo assim, em escala bem maior (dezenas de milhares de req/s), a própria task .NET vira o gargalo — CPU do gerador, não do sistema medido. Meça também o gerador: se ele não sustenta o RPS alvo com folga, o resultado do degrau mede a capacidade do teste, não a da arquitetura.
Custo: o que este laboratório acrescenta e o que ele devolve
| Dimensão | Cobra por | Cuidado |
|---|---|---|
| Tasks extras durante os degraus | vCPU-segundo e GB-segundo, tanto da frota quanto do gerador | a área embaixo da curva de todos os degraus, não só do mais alto — um teste de 4 horas com 6 degraus cobra as 4 horas inteiras |
| RDS Proxy | hora provisionada, independente de tráfego | ele fica ligado 24 horas depois deste laboratório, porque virou parte da arquitetura de produção — não é custo só do dia do teste |
| Métricas de alta resolução do CloudWatch | dimensão de cobrança distinta da resolução padrão | só ligue resolução de 20 s durante a janela do teste; desligar depois evita pagar por granularidade que ninguém consulta no dia a dia |
| Máquina de estados e execuções do Step Functions | por transição de estado | um teste com muitos degraus curtos gera mais transições que um com poucos degraus longos — desprezível perto do custo de task, mas soma |
O custo oculto que sobrevive ao teste
O RDS Proxy não é ferramenta de teste — é a correção real, e por isso continua cobrando por hora depois que o teste termina, mesmo em janelas sem tráfego. Isso é esperado e correto: o preço de ter o teto medido e corrigido é ter mais uma peça provisionada o tempo todo, não só durante o experimento.
Well-Architected nos seis pilares
| Pilar | Situação ao fim deste laboratório | Risco que fica | Melhoria | Prioridade |
|---|---|---|---|---|
| Excelência operacional | teto de capacidade medido, com registro versionado de cada degrau | o número medido envelhece a cada deploy relevante | repetir o teste no pipeline e falhar o deploy quando o teto cair (L52, L54) | alta |
| Eficiência de desempenho | segue PERF05-BP04: ambiente, monitoramento, cenário, execução, análise | o mix de tráfego sintético pode divergir do real conforme o catálogo cresce | revalidar a hipótese do mix de leitura e escrita a cada trimestre | média |
| Confiabilidade | gargalo de conexão corrigido antes de virar incidente em campanha real | a hipótese de falha de AZ sob carga alta nunca foi exercitada junto com o teto medido | combinar injeção de falha de AZ com carga sustentada (L57) | alta |
| Segurança | gerador de carga com role exclusiva, sem alcance sobre produção | o simulador do parceiro é um novo componente, e sua própria segurança nunca foi revisada a fundo | incluir o simulador no escopo da próxima revisão de segurança | média |
| Otimização de custo | RDS Proxy dimensionado por medição, não por chute | a frota de teste liga tasks reais por horas a cada rodada | agendar o teste fora de horário de maior custo de computação, quando aplicável | baixa |
| Sustentabilidade | o teste evita superprovisionar "por garantia" nas quatro camadas | rodar o teste com frequência alta desperdiça energia sem ganho de informação proporcional | calibrar a frequência do teste pelo ritmo real de mudança do sistema, não por calendário fixo | baixa |
Evolução em níveis: o que muda, e o que passa a doer
A terceira arquitetura não é um desenho: é a resposta a QUANDO o método de medir capacidade precisa mudar de forma. Cada nível resolve um risco e compra outro.
Nenhum teste de carga. O teto é desconhecido, e a primeira medição é um incidente real.Degrau controlado, painel correlacionado, um gargalo confirmado e corrigido no ponto certo.O teste roda automaticamente a cada deploy relevante, e falha o pipeline quando o teto cai abaixo do exigido (L52, L54).Tráfego de sombra (shadow traffic) real, não sintético, valida o teto sob o padrão de uso genuíno em vez de um mix estimado.O teto de capacidade vira um contrato formal (SLO de capacidade) auditável entre times e fornecedores.Histórico de várias rodadas de teste correlaciona qual mudança de código historicamente moveu qual gargalo, e sugere onde testar primeiro.A ordem não é negociável, e o motivo é concreto
Automatizar o teste no pipeline (nível 3) sem primeiro ter um critério de estabilização confiável (nível 2) produz um gate que bloqueia deploy por ruído, não por regressão real. Quem pula direto para dado e IA (nível 6) sem ter rodado o teste mais de uma vez está treinando um modelo com uma amostra de tamanho um.
Onde IA entra nesta arquitetura, e onde não entra
| Pergunta | Resposta honesta para este módulo |
|---|---|
| Que problema a IA resolveria aqui? | nenhum, na rodada única deste laboratório — decidir "subir, ficar ou parar" um degrau é comparar um sinal medido contra um limiar declarado; não há ambiguidade que peça um modelo |
| Por que uma regra bastaria, e não uma regra ruim? | porque o critério de estabilização é objetivo e verificável (variância de p99 abaixo de um limiar por minutos seguidos), exatamente o tipo de decisão que uma regra simples resolve melhor que um modelo — mais rápido de auditar, e sem custo de treino |
| Onde IA eventualmente agrega | só depois de várias rodadas históricas de teste: correlacionar qual mudança de código moveu qual gargalo, e sugerir onde testar primeiro na próxima rodada — é observabilidade preditiva, tema da banda 9/10 desta série, e mesmo lá precisa de avaliação e caminho manual, porque prever errado custa bloquear um deploy legítimo |
Anti-padrões deste laboratório
| Anti-padrão | Por que alguém faz | Por que é problema | Sintoma em produção | Forma correta |
|---|---|---|---|---|
| Perguntar "quantos usuários simultâneos" em vez de "que RPS satura o quê" | é a pergunta que a diretoria faz, e é mais fácil repeti-la do que traduzi-la | "usuários simultâneos" não é uma unidade que nenhuma camada da arquitetura mede — a pergunta não tem resposta técnica | compromisso de capacidade assinado num número que ninguém sabe converter em requisição por segundo | traduzir para taxa de requisição por segundo e nomear qual camada foi observada naquela taxa |
| Carga direto no pico, sem degrau | economiza tempo de execução, e "simular o pior dia direto" parece mais realista | todos os sinais sobem juntos, e fica impossível separar saturação real de pico transitório | correção aplicada na camada errada, porque o sinal que "quebrou primeiro" foi só o mais lento a reagir, não o mais fraco | degraus com critério de estabilização declarado antes do teste |
| Corrigir a camada que a intuição aponta (CPU) sem confirmar com dado | é a métrica mais visível, a primeira do painel padrão, e mexer nela é a mudança de menor atrito | CPU baixa não significa capacidade sobrando — a task pode estar esperando o banco, não processando | o teto de requisição por segundo não muda depois do "upgrade" de CPU e memória | descartar cada camada com a métrica certa antes de tocar em qualquer configuração |
| Testar contra produção real sem isolamento | montar um ambiente de staging fiel dá trabalho, e "é só um teste rápido" parece inofensivo | gera pedido e cobrança reais, e o cliente sente a latência degradada do degrau mais alto | reclamação de cliente e chamada real ao gateway de pagamento durante a janela do teste | réplica de staging idêntica, e a dependência externa sempre em modo simulador |
| Corrigir as quatro camadas de uma vez, "por garantia" | parece mais seguro cobrir tudo do que arriscar ter escolhido a camada errada | sem dado isolando qual mudança teve efeito, a próxima rodada de teste não consegue atribuir causa a nada | o teto sobe, mas ninguém sabe replicar o resultado nem explicar por quê | uma correção por rodada, no ponto exato que o dado apontou |
| Rodar o teste uma vez e nunca mais | o teto medido parece definitivo, e repetir parece redundante | cada deploy pode mover o teto sem ninguém perceber, até o dia em que o contrato de SLA é exercido | incidente de capacidade meses depois de um teste que "provava" que o sistema aguentava | automatizar a repetição do teste no pipeline, a cada mudança relevante (L52, L54) |
Quando algo não funciona
| Sintoma | Causa provável | Como investigar | Onde olhar | Correção |
|---|---|---|---|---|
| Todas as métricas sobem juntas e nada se distingue | carga aplicada direto no pico, sem degrau | reveja o perfil de RPS que o gerador aplicou, não o sistema sob teste | o registro do próprio teste (rps_aplicado_medio por janela) | refaça com degraus e critério de estabilização declarado |
| DatabaseConnections nunca sobe, mesmo em degrau alto, mas o p99 piora | RDS Proxy com MaxConnectionsPercent baixo demais, gerando fila antes de erro visível | compare DatabaseConnectionsBorrowLatency com o degrau em que o p99 piorou | métricas do proxy, não da instância RDS diretamente | revisar MaxConnectionsPercent com a margem recomendada de 1,3x o uso monitorado |
| O disjuntor abre durante o teste, mesmo com o parceiro simulado saudável | o próprio simulador do L36 está sob a carga do teste e satura sozinho — um gargalo artificial que não existe em produção | meça a latência do simulador isolada do restante da cadeia | métricas do simulador, separadas das métricas do disjuntor | dimensionar o simulador para a carga do teste, ou desacoplar sua capacidade da capacidade medida |
| ECS nunca escala durante o degrau | reaparece o achado do L06: métrica de escala errada ou rótulo de recurso malformado | describe-scaling-activities durante a janela do degrau | atividades de escala vazias com CPU ou latência subindo ao mesmo tempo | reveja a configuração da política de escala do L06 antes de continuar este teste |
Limpeza: o que o destroy não leva
# Ordem: primeiro o aparato de TESTE, que so existe durante a rodada.
# O RDS Proxy NAO entra aqui — ele fica em producao, e essa e a decisao
# registrada na secao de decisoes.
terraform destroy -target=aws_sfn_state_machine.degraus
terraform destroy -target=aws_ecs_task_definition.executor_carga
terraform destroy -target=aws_iam_role.executor_carga
# Se o staging foi criado so para esta rodada (efemero), derrube tambem.
# Se e um staging permanente, mantenha e apenas zere os dados sinteticos.
terraform destroy -target=module.staging_efemero # so se aplicavel
| Recurso | Sai no destroy do teste? | Cobra parado? | Por que fica ou sai |
|---|---|---|---|
| Máquina de estados e task do executor | sim | não | é só o aparato do teste — não tem função fora de uma rodada |
| Ambiente de staging, se efêmero | sim | sim, RDS e ElastiCache cobram mesmo sem tráfego | decida antes se staging é permanente ou por demanda — improvisar depois custa mais |
| RDS Proxy | NÃO — permanece em produção | sim, cobra por hora provisionada mesmo sem tráfego de teste | é a correção real que o dado apontou, não um artefato do experimento |
| Log group de métricas de alta resolução do teste | sim, mas verifique a retenção configurada | não diretamente, mas acumula se ninguém definir retenção | defina retenção antes de rodar, senão vira custo esquecido em poucos meses |
| Registro da curva de carga (JSON por degrau) | não — é o artefato que você quer manter | custo de armazenamento desprezível | é o histórico que alimenta o nível 6 da evolução e a próxima rodada de comparação |
O que fica ligado depois deste laboratório, e por quê
Diferente da maioria dos laboratórios desta série, a limpeza aqui não remove tudo o que foi criado: o RDS Proxy é uma correção de produção, e desligá-lo devolveria a arquitetura ao estado que o teste provou quebrado. O que se remove é só o aparato de medição — o resultado da medição fica.
Resumo: problema, peça e motivo
| Problema | Peça | Por que ela, e não outra |
|---|---|---|
| Ninguém sabe o teto real da arquitetura | degrau controlado com critério de estabilização | só medição repetível separa saturação real de pico transitório — suposição não serve para assinar contrato |
| A intuição aponta CPU, e não é CPU | painel correlacionado com os quatro sinais no mesmo instante | descartar por dado é mais barato do que corrigir a camada errada e medir de novo do zero |
| O sucesso do L06 aperta o RDS | RDS Proxy com MaxConnectionsPercent derivado da medição | multiplexa conexão sem mexer na política de escala que já funciona — corrige o efeito, não a causa que estava certa |
- Definir o critério de estabilização antes de aplicar qualquer carga.
- Isolar o teste do cliente real — staging e simulador, nunca produção direta.
- Subir um degrau por vez e segurar até estabilizar.
- Ler os quatro sinais no mesmo instante, não em janelas separadas.
- Descartar as camadas saudáveis com dado antes de suspeitar de qualquer uma.
- Confirmar o candidato a gargalo repetindo o degrau isoladamente.
- Corrigir só o ponto que o dado apontou.
- Repetir o mesmo degrau depois da correção e comparar contra o registro anterior.
Perguntas frequentes
❓ Por que o autoscaling do ECS não evita que a arquitetura quebre sob carga?
❓ Quantos usuários simultâneos minha arquitetura aguenta?
❓ Por que testar carga direto contra produção, sem isolamento, é arriscado?
❓ O que é o MaxConnectionsPercent do RDS Proxy, exatamente?
❓ Por que CPU baixa na task não significa que sobra capacidade no sistema?
❓ Preciso derrubar o sistema por completo para achar o teto de capacidade?
❓ Por que o RDS Proxy continua em produção depois que o teste termina?
❓ O disjuntor de circuito do L36 substitui a necessidade de testar carga?
Fixando
Por que subir a carga direto para o pico esperado, em vez de em degraus que estabilizam antes de avançar, é um erro de método num teste de capacidade?
Depois de identificar que o RDS estava saturando por excesso de conexões, a equipe configurou o RDS Proxy com MaxConnectionsPercent igual exatamente ao pico de conexões medido no teste anterior, sem folga adicional. Qual é o problema dessa escolha?
Conhecimentos, próximo módulo e documentação
| Item | Conteúdo |
|---|---|
| Conhecimentos anteriores necessários | L06 (escala automática por métrica de chegada) e L36 (retry, jitter e disjuntor) concluídos e no ar |
| Conhecimentos adquiridos | o método do degrau com critério de estabilização; como descartar camada por dado antes de corrigir; por que o sucesso de uma política de escala pode apertar outra camada; RDS Proxy e MaxConnectionsPercent derivado de medição |
| Limitação que fica | o teto medido vale para esta versão do sistema; qualquer mudança relevante de código ou tráfego pode movê-lo sem avisar, e este laboratório não automatiza a repetição |
| Próximo exemplo recomendado | L52 — repetir este teste automaticamente no pipeline de entrega, falhando o deploy quando o teto medido cair abaixo do exigido |
| Também habilitado por este módulo | L57 (injeção de falha de AZ sob carga sustentada) combina este método com um cenário de falha; L54 (pipeline com credencial federada) é onde a repetição automática do teste se conecta ao deploy |
| Data da última validação técnica | 7 de agosto de 2026 |
Documentação oficial consultada: PERF05-BP04 Load test your workload — o processo de ambiente, monitoramento, cenário, execução e análise que estrutura o método deste laboratório; e RDS Proxy connection considerations — a definição de `MaxConnectionsPercent` como percentual de `max_connections`, a recomendação de margem de 1,3x o uso monitorado, e as métricas `DatabaseConnections`, `MaxDatabaseConnectionsAllowed` e `DatabaseConnectionsBorrowLatency`. Os valores de preço não aparecem neste módulo por decisão: use o AWS Pricing Calculator, porque preço varia por região e envelhece mais rápido que o conteúdo.
O que não foi verificado, e você deve conferir na sua conta
Os números de RPS, o tamanho de pool por task e o percentual final de MaxConnectionsPercent citados são os medidos no ambiente de exemplo da Cadência, e servem como ordem de grandeza — não como referência. O teto real da SUA arquitetura depende do seu pool por instância, da sua classe de instância RDS e do seu mix de leitura e escrita, e só o degrau rodado no seu ambiente responde por ele.
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…