AV Chaos Monkey
Plataforma de engenharia do caos distribuída para teste de carga em sistemas de videoconferência. Simula mais de 1500 participantes WebRTC com streams H.264/Opus e injeta picos de caos na rede para validar a resiliência do sistema sob condições degradadas.
Arquitetura
-
Pipeline de Processamento de Mídia:
- FFmpeg converte vídeo de entrada para H.264 Annex-B e Ogg/Opus na inicialização
- NAL Reader analisa o stream H.264 (SPS/PPS/IDR/Slices)
- Opus Reader extrai quadros de áudio de 20ms do container Ogg
- Quadros armazenados em cache na memória, compartilhados entre todos os participantes (cópia zero)
- Reduz a CPU em ~90% vs. codificação por participante
-
Plano de Controle:
- Servidor HTTP (:8080) gerencia o ciclo de vida do teste via API REST
- Spike Scheduler distribui eventos de caos (par/aleatório/frente/trás/legado)
- Network Degrader aplica caos: perda de pacotes (1-25%), jitter (10-50ms), redução de bitrate (30-80%), queda de quadros (10-60%)
- Configuração de caos carregada aplicada ao pool de participantes
-
Pool de Participantes:
- Particionamento automático entre pods usando:
participant_id % total_partitions = partition_id
- Cada participante gera streams RTP (PT=96 vídeo, PT=111 áudio)
- ID do participante embutido no cabeçalho de extensão RTP (ID=1)
- Tamanho do pool: 1-100 (local), 100-500 (Docker), 500-1500 (Kubernetes)
-
Auto-Configuração Kubernetes:
- Pods detectam automaticamente o ID da partição pelo nome do pod:
orchestrator-3 → PARTITION_ID=3
- Alocação de porta:
base_port + (partition_id × 10000) + participant_index
- Exemplo: Partição 0 usa 5000-14999, Partição 1 usa 15000-24999
- StatefulSet com 10 réplicas, cada uma lidando com ~150 participantes
- Recursos: 1-4 CPU, 2-4Gi de memória por pod
- Configuração automática baseada nas especificações da máquina host
-
Cadeia de Relé UDP (apenas Kubernetes):
Pods Orchestrator (10×) → UDP :5000 → Pod udp-relay (Python)
→ TCP com prefixo de comprimento :5001 → kubectl port-forward 15001:5001
→ tools/udp-relay (Go) → UDP :5002 → Seu Receptor
- Por quê: kubectl port-forward só suporta TCP, não UDP
- Relé no cluster: Script Python agrega UDP de todos os pods, transmite como TCP com prefixo de 2 bytes de comprimento
- Relé local: Ferramenta Go converte o stream TCP de volta para pacotes UDP
- Agrega 1500 streams de participantes em uma única conexão
-
Infraestrutura WebRTC:
- Coturn StatefulSet: 3 réplicas iniciais, HPA escala de 1 a 10 com base na carga (~500 participantes/réplica)
- coturn-lb Service: Balanceia o tráfego TURN entre as réplicas
- webrtc-connector: Camada de proxy opcional (Deployment + HPA 2-10 réplicas), lida com sinalização SDP
- Modo Docker: Container Coturn único para testes locais
- Portas: 3478 (TURN), 49152-65535 (faixa de relé)
- Credenciais: webrtc/webrtc123
-
Integração com Cliente:
- Receptor UDP: Recebe o stream RTP agregado de todos os participantes via cadeia de relé
- Receptor WebRTC: Estabelece conexões WebRTC 1:1 via troca de SDP através de servidores TURN
- Ambos encaminham para seu sistema de videochamada em teste (SFU/MCU/Mesh)
-
Pilha de Observabilidade (Opcional):
- Prometheus: Coleta o endpoint
/metrics de todos os pods do orchestrator a cada 5s
- Grafana: Visualiza métricas via painel pré-configurado (admin/admin)
- Métricas expostas: contagem de participantes, pacotes enviados, bytes enviados, picos ativos, % de perda de pacotes, jitter, pontuação MOS
- Acesso: Prometheus em :30090, Grafana em :30030 (NodePort)
- Pods do orchestrator anotados para descoberta automática:
prometheus.io/scrape: "true"
Conceitos Principais
Simulação de Participante
Cada participante virtual gera streams de mídia reais:
- Vídeo: Unidades NAL H.264 de arquivos de vídeo reais, empacotadas conforme RFC 6184
- Áudio: Quadros Opus de containers Ogg, empacotados conforme RFC 7587
- RTP: Cabeçalhos compatíveis com padrões com extensões de ID do participante
- Temporização: Temporização precisa de quadros (30fps vídeo, pacotes de áudio de 20ms)
Injeção de Caos
Cinco tipos de pico simulam condições reais de rede:
- Perda de Pacotes: Descarta pacotes RTP na camada de aplicação (1-100%)
- Jitter de Rede: Adiciona variação de latência (latência base + jitter gaussiano)
- Redução de Bitrate: Limita a codificação de vídeo (30-80% de redução)
- Queda de Quadros: Pula quadros de vídeo (10-60% de taxa de queda)
- Limitação de Banda: Limita a taxa total de transferência
Estratégias de Distribuição
Os picos são distribuídos ao longo da duração do teste usando estratégias configuráveis:
- Uniforme: Espaçamento uniforme com jitter (carga previsível)
- Aleatório: Temporização imprevisível (caos realista)
- Concentrado no Início: Picos densos no início (teste de recuperação)
- Concentrado no Fim: Linha de base seguida de caos (teste de comparação)
- Legado: Temporizador de intervalo fixo (injeção em tempo de execução)
Particionamento
Implantações Kubernetes usam particionamento de participantes para escalonamento horizontal:
- Cada pod lida com
participant_id % total_partitions == partition_id
- Alocação de porta:
base_port + (partition_id * 10000) + participant_index
- Distribuição automática de carga entre 1-10 pods
- Escala para mais de 1500 participantes (150 por pod)
Executando o Sistema
1. Desenvolvimento Local (Go Nativo)
Melhor para: Desenvolvimento, depuração, testes de pequena escala (1-100 participantes)
# Iniciar orchestrator
go run cmd/main.go
# Em outro terminal: Iniciar receptor UDP
go run examples/go/udp_receiver.go 5002
# Editar config/config.json para definir num_participants: 10
# Executar teste de caos
go run tools/chaos-test/main.go -config config/config.json
O que acontece:
- Processo orchestrator único em
:8080
- Participantes enviam UDP para
127.0.0.1:5002
- Picos de caos injetados via API HTTP
- Métricas em tempo real exibidas a cada 2s
Configuração (config/config.json):
{
"base_url": "http://localhost:8080",
"media_path": "public/rick-roll.mp4",
"num_participants": 10,
"duration_seconds": 300,
"spikes": {
"count": 20,
"interval_seconds": 5,
"types": { "rtp_packet_loss": {...}, "network_jitter": {...} }
},
"spike_distribution": {
"strategy": "random",
"min_spacing_seconds": 5,
"jitter_percent": 15
}
}
2. Docker Compose (Containerizado)
Melhor para: Testes isolados, CI/CD, testes de médio porte (100-500 participantes)
Pré-requisitos:
- Docker Desktop com alocação de memória de 8-16GB
docker-compose instalado
# Construir e iniciar container orchestrator
./scripts/start_everything.sh build
# Em outro terminal: Iniciar receptor UDP
go run examples/go/udp_receiver.go 5002
# Editar config/config.json para definir num_participants: 100
# Executar teste de caos (direcionado ao container)
go run tools/chaos-test/main.go -config config/config.json
Limites de Recursos (editar docker-compose.yaml):
services:
orchestrator:
deploy:
resources:
limits:
cpus: "14.0"
memory: 6G # Aumentar para mais participantes
Guia de Dimensionamento:
| Memória Docker | Máx. Participantes | Núcleos CPU |
|---|
| 8 GB | ~100 | 4 |
| 16 GB | ~250 | 8 |
| 24 GB | ~400 | 12 |
| 32 GB | ~500 | 14 |