Resposta a Incidentes para Serviços Go
Serviços Go em produção falham em padrões reconhecíveis.
Busque em todas as páginas da documentação
Serviços Go em produção falham em padrões reconhecíveis.
Engenheiros de plantão que conhecem esses padrões gastam minutos na triagem em vez de horas adivinhando.
Esta página constrói o modelo mental para resposta a incidentes em binários compilados e com coleta de lixo: o que verificar primeiro, como os sinais do runtime Go diferem de pilhas interpretadas e quando estabilizar o tráfego antes de fazer o profiling.
database/sql) para encontrar a causa raiz.Um pool de conexões em MaxOpenConns, uma tempestade de GC após um deploy, ou um vazamento de goroutine podem parecer "latência misteriosa" até que você saiba qual dashboard e perfil abrir.
Fazer profiling sob carga extrema pode piorar os sintomas se a amostragem for mal configurada.
Um incidente é uma degradação não planejada que ameaça SLOs ou a confiança do usuário: erros elevados, timeouts, indisponibilidade de dados ou exposição de segurança.
Resposta a incidentes é o trabalho coordenado para restaurar o serviço e aprender o que quebrou.
Para serviços Go, o runtime oferece concorrência barata e gerenciamento automático de memória.
Esses pontos fortes se tornam passivos quando goroutines bloqueiam para sempre, alocações aumentam o tempo de pausa do GC, ou sql.DB espera enfileiradas atrás de pools esgotados.
Respondedores experientes tratam incidentes Go como uma árvore de sintomas, não como uma caça a um único bug:
Dor visível ao usuário Primeiras perguntas
────────────────────────────────────────────────────────────
Pico de 5xx / timeouts Deploy recente? Upstream saudável?
p99 alto, erros estáveis GC, locks, espera no pool, IO lento?
Memória subindo Vazamento de heap, vazamento de goroutine, cache?
Pods OOMKilled Limite vs. conjunto de trabalho, GOMEMLIMIT
Timeouts de DB em todo lugar Estatísticas sql.DB, conexões do servidorMitigação reduz a dor do cliente: rollback, escalar réplicas, descarregar carga, desativar um feature flag ou falhar aberto em caminhos não críticos.
Diagnóstico explica por que a mitigação funcionou e o que corrigir permanentemente.
Durante SEV-1, faça ambos em paralelo - mas nunca deixe a análise de causa raiz perfeita bloquear um rollback conhecido e bom.
A triagem de incidentes Go segue uma sequência repetível que se mapeia para ferramentas que você já deve expor em staging e produção.
1. Confirme o escopo e a severidade.
Verifique a taxa de erros, os percentis de latência e a saturação (CPU, memória, conexões abertas) por serviço e região.
Correlacione com eventos de deploy, pushes de configuração, expiração de certificados e páginas de status de dependências.
2. Estabilize se o orçamento de erro estiver sendo consumido.
Faça rollback do último binário se a correlação for forte.
Rollbacks Go são rápidos quando artefatos são versionados e migrações são retrocompatíveis.
Escale horizontalmente apenas quando o gargalo for trabalho de handler limitado por CPU, não contenção de pool de DB ou locks.
3. Leia logs estruturados com IDs de requisição.
Linhas JSON de slog ou zap devem incluir trace_id, request_id, nome do handler e cadeias de error.
Pilhas de pânico em Go são snapshots single-threaded - capture-as de logs centralizados, não apenas do tail de kubectl logs.
4. Abra diagnósticos do runtime.
| Sinal | Onde | O que ele diz |
|---|---|---|
| Perfil de CPU | /debug/pprof/profile | Funções quentes sob carga |
| Perfil de Heap | /debug/pprof/heap | Locais de alocação, memória retida |
| Dump de Goroutine | /debug/pprof/goroutine?debug=2 | Pilhas bloqueadas, padrões de vazamento |
sql.DB.Stats | Exportador de métricas | Contagem de espera, ocioso vs. em uso |
runtime/metrics | /debug/vars ou OTel | Pausa do GC, heap ativo |
Os perfis devem ser tirados durante a carga representativa.
Um pod ocioso com perfil de CPU é ruído.
5. Restrinja a classe da falha.
GOMAXPROCS vs limite de CPU, pool de threads, limites de epoll.GOMEMLIMIT, churn de alocação em caminhos quentes.context ausentes.// Ilustrativo: exporta pressão do pool durante um incidente
stats := db.Stats()
log.Printf("db open=%d inUse=%d idle=%d wait=%d waitDur=%s",
stats.OpenConnections, stats.InUse, stats.Idle,
stats.WaitCount, stats.WaitDuration)6. Comunique e documente.
Atualizações no canal de incidentes: impacto, hipótese atual, mitigação em andamento, próximo horário de verificação.
Salve arquivos de perfil, links de dashboards e SHAs de deploy para o post-mortem.
Kubernetes e Go adicionam particularidades específicas da plataforma.
Contêineres OOMKilled frequentemente significam que o heap mais as pilhas de goroutine excederam limits.memory sem alinhamento com GOMEMLIMIT.
Probes de Liveness que atingem handlers que realizam trabalho real podem amplificar a carga durante incidentes.
A Readiness deve falhar quando as dependências estiverem não saudáveis para que os load balancers parem de enviar tráfego.
Incidentes multi-serviço exigem pensamento sobre o raio de explosão.
Uma camada compartilhada de Redis ou Postgres pode fazer com que todos os microserviços Go pareçam doentes simultaneamente.
Exemplares de trace do OpenTelemetry ajudam a provar se a latência é trabalho do handler local ou esperas de grpc downstream.
Game days e runbooks convertem este modelo mental em memória muscular.
Pratique rollback, coleta de perfis sob carga e modelos de template de passagem de plantão antes que as páginas de produção toquem.
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
| Rollback primeiro | Alívio rápido do usuário | Pode esconder bug latente | Forte correlação de deploy |
| Escalar para fora | Botão simples | Piora problemas de pool/lock | Trabalho stateless limitado por CPU |
| Profiling em produção | Pilhas de verdade | Precisa de autenticação, adiciona custo de amostragem de CPU | Mistério de latência após deploy estável |
| Descarregar tráfego | Protege o caminho principal | Funcionalidade reduzida | Interrupção parcial, pronto para flag |
Contextos regulatórios e empresariais exigem linhas do tempo de incidentes imutáveis.
Automatize a captura da versão Go (runtime.Version()), GOMAXPROCS e metadados de build nas respostas /healthz para pacotes de suporte.
A correção é cancelamento, limites de pool ou mudança de código apoiada por perfis.
OOM é comum quando os limites ignoram o custo de pilha e fora do heap.
Delve é para falhas reprodutíveis em dev/staging.
Confirme o impacto no usuário e a violação do SLO.
Verifique a taxa de erros, latência p99 e deploys recentes.
Faça rollback ou escale se a correlação for óbvia.
Abra os logs do serviço para pilhas de pânico e mensagens de timeout upstream.
Binários Go são processos únicos com goroutines leves.
Dumps de goroutine e pprof são padrão.
Não há formato de dump de heap JVM separado - use perfis de heap e GOMEMLIMIT em vez disso.
O pooling de conexões é explícito via database/sql, não gerenciado por ORM por padrão.
Após a mitigação estabilizar os erros ou em um pod canário recebendo tráfego de produção.
Amostre 20-30 segundos enquanto a carga continua.
Evite profiling de heap completo em MemProfileRate = 1 em todas as réplicas simultaneamente.
RED: taxa de requisições, erros, histogramas de duração.
Mais específicos de Go: contagem de goroutines, pausa do GC, heap em uso, contagem de espera sql.DB, e CPU/memória do processo vs limites.
Não.
Use definições de SEV: impacto em toda a base de clientes SEV-1 recebe escalonamento imediato; problemas SEV-3 apenas internos podem esperar o horário comercial com um proprietário documentado.
Mudanças em GOMAXPROCS, novos timeouts padrão, locks de migração, feature flags ou diferentes variáveis de ambiente GOMEMLIMIT alteram o comportamento do runtime sem mudanças na lógica.
Compare configuração e metadados de artefatos, não apenas o código fonte.
Mitigação restaura SLOs temporariamente (rollback, escala, descarregar carga).
Correção previne recorrência (dimensionamento de pool, cancelamento de contexto, índice de consulta).
Ambos pertencem à linha do tempo; apenas a correção fecha o ticket de engenharia.
Compare as estatísticas sql.DB.Stats().WaitCount do aplicativo com as contagens de conexões do servidor de banco de dados e logs de consultas lentas.
Se o aplicativo espera em db.Conn enquanto a CPU do DB está ociosa, suspeite de má configuração do pool ou falta de deadlines de context nos handlers.
Sim, em localhost ou portas de admin autenticadas.
Nunca exponha /debug/pprof na internet pública.
O profiling de CPU adiciona uma pequena sobrecarga; coordene o profiling de heap para um pod de cada vez.
Linha do tempo, SHA do deploy, versão Go, passos de mitigação, links ou arquivos de perfil, gráficos de estatísticas sql.DB, tendência da contagem de goroutines e tickets concretos de acompanhamento com proprietários.
Passe o bastão quando as mitigações estiverem estáveis, as evidências salvas e o próximo horário de verificação documentado.
O próximo plantonista precisa de perguntas abertas, não de uma sessão de depuração ao vivo sem contexto.
O detector de corrida é para CI e reprodução local.
Sintomas de produção que correspondem a corridas (valores errados não determinísticos) devem acionar uma reprodução em staging com go test -race, não -race em produção.
sql.DBVersões de Stack: Esta página foi escrita para Go 1.26.x (padrão Green Tea GC, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026