Escalabilidade e Capacidade
Escalonamento horizontal vs vertical, auto-scaling, capacity planning e load testing para preparar o sistema para a demanda.
O que é escalabilidade?
A escalabilidade é a capacidade de um sistema de lidar com um aumento na carga de trabalho sem degradar seu desempenho. Um sistema escalável pode crescer para atender mais usuários, mais requests ou mais dados sem a necessidade de redesenhá-lo.
Escalabilidade não é a mesma coisa que desempenho:
- Desempenho: quão rápido o sistema responde com a carga atual
- Escalabilidade: quão bem ele mantém seu desempenho quando a carga aumenta
Escalonamento vertical vs horizontal
Escalonamento vertical (scale up)
Consiste em adicionar mais recursos a uma máquina existente: mais CPU, mais RAM, mais disco.
Vantagens:
- Simples de implementar — não requer alterações na aplicação
- Não introduz complexidade de distribuição
Desvantagens:
- Tem um limite físico — não é possível escalar infinitamente
- Ponto único de falha — se a máquina cai, tudo cai
- Geralmente mais caro em grande escala
Escalonamento horizontal (scale out)
Consiste em adicionar mais instâncias do serviço e distribuir a carga entre elas.
Vantagens:
- Teoricamente ilimitado — é possível adicionar quantas instâncias forem necessárias
- Maior resiliência — se uma instância falha, as demais continuam funcionando
- Mais econômico em grande escala (commodity hardware)
Desvantagens:
- Requer que a aplicação seja stateless ou gerencie estado distribuído
- Introduz complexidade: balanceamento de carga, consistência de dados, sessões distribuídas
- Mais difícil de depurar
Quando usar cada um?
| Cenário | Recomendação |
|---|---|
| Banco de dados relacional | Vertical primeiro, depois read replicas |
| Serviços web stateless | Horizontal |
| Filas de mensagens | Horizontal (partições) |
| Cache | Horizontal (sharding) |
| Aplicação monolítica | Vertical primeiro, depois decompor |
Auto-scaling
O auto-scaling ajusta automaticamente o número de instâncias conforme a demanda atual.
Horizontal Pod Autoscaler (HPA) no Kubernetes
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-service
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Métricas para auto-scaling
- CPU utilization: a mais comum, escala quando a CPU ultrapassa um limite
- Memory utilization: útil para aplicações memory-intensive
- Request rate: escala com base no número de requests por segundo
- Queue depth: escala quando a fila de mensagens cresce
- Custom metrics: latência p99, erros por segundo, etc.
Boas práticas de auto-scaling
- Definir mínimos e máximos razoáveis: evitar escalar até 0 (cold start) ou até o infinito (custos)
- Cooldown periods: aguardar antes de escalar de volta para evitar oscilações
- Escalar de forma antecipada: se picos previsíveis são conhecidos (ex: Black Friday), pré-escalar
- Monitorar o auto-scaler: verificar se ele escala quando deve e não oscila
Capacity planning
O capacity planning é o processo de determinar quantos recursos o sistema precisa para lidar com a carga esperada.
Processo
- Definir métricas-chave: requests por segundo, usuários concorrentes, tamanho dos dados
- Medir a capacidade atual: quanta carga o sistema consegue suportar hoje
- Projetar o crescimento: com base em dados históricos e planos de negócio
- Calcular os recursos necessários: CPU, memória, armazenamento, largura de banda
- Adicionar margem de segurança: tipicamente 30-50% sobre a projeção
Exemplo prático
Situação atual:
- 1000 requests/segundo com 3 pods
- Cada pod maneja ~350 req/s antes de degradarse
- CPU promedio: 60%
Proyección a 6 meses:
- 3000 requests/segundo esperados
- Necesitamos: 3000 / 350 = ~9 pods
- Con margen de seguridad (30%): 12 pods
- Auto-scaling: min=9, max=15
Load testing
O load testing verifica se o sistema consegue lidar com a carga esperada e ajuda a identificar gargalos.
Tipos de load testing
- Load test: simula a carga esperada em condições normais
- Stress test: incrementa a carga além do esperado para encontrar o ponto de ruptura
- Spike test: simula picos repentinos de tráfego
- Soak test: mantém carga constante durante horas para detectar memory leaks e degradação gradual
Ferramentas populares
- k6: ferramenta moderna de load testing com scripts em JavaScript
- Apache JMeter: ferramenta clássica com interface gráfica
- Locust: load testing em Python, distribuído
- Artillery: load testing para APIs e microsserviços
- Gatling: load testing em Scala com relatórios detalhados
Exemplo com k6
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // ramp up a 100 usuarios
{ duration: '5m', target: 100 }, // mantener 100 usuarios
{ duration: '2m', target: 200 }, // subir a 200 usuarios
{ duration: '5m', target: 200 }, // mantener 200 usuarios
{ duration: '2m', target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% de requests < 500ms
http_req_failed: ['rate<0.01'], // menos de 1% de errores
},
};
export default function () {
const res = http.get('https://api.example.com/products');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
O que medir em load tests
- Throughput: requests por segundo que o sistema consegue suportar
- Latência: tempo de resposta (p50, p95, p99)
- Error rate: porcentagem de requests que falham
- Recursos: CPU, memória, conexões de DB durante o teste
- Ponto de ruptura: carga em que o sistema começa a degradar
Padrões de escalabilidade
Caching
Reduzir a carga em serviços e bancos de dados armazenando respostas frequentes:
- CDN: para assets estáticos e respostas cacheáveis
- Redis/Memcached: para dados de acesso frequente
- Cache de aplicação: para cálculos custosos
Database read replicas
Distribuir as leituras entre múltiplas réplicas do banco de dados enquanto as escritas vão para o primário.
Sharding
Dividir os dados horizontalmente entre múltiplas instâncias de banco de dados com base em uma chave de partição.
Event-driven architecture
Desacoplar serviços usando eventos assíncronos para absorver picos de carga sem saturar os serviços downstream.
Resumo
A escalabilidade requer planejamento e medição contínua. O escalonamento horizontal é preferível para serviços stateless, o auto-scaling automatiza a resposta à demanda, o capacity planning antecipa as necessidades futuras e o load testing valida se o sistema consegue lidar com a carga esperada.