Erro 104 no NGINX com .NET - Visão 3 | (104: Connection reset by peer) while reading response header from upstream | Ambiente .NET
- Erro 104 no NGINX com .NET - Visão 3 | (104: Connection reset by peer) while reading response header from upstream | Ambiente .NET
O erro 104: Connection reset by peer no Nginx é um dos mais importantes para diagnosticar problemas de backend sob carga — especialmente em cenários de esgotamento de threads.
O que significa “104” tecnicamente
104é o código POSIX para ECONNRESET- Significa que o lado remoto (o upstream / sua API) enviou um RST (reset) no socket TCP
- Em termos simples: 👉 a conexão foi abruptamente encerrada pelo backend, não de forma normal (FIN)
Diferença crítica: FIN vs RST
- FIN (normal) → conexão encerrada de forma controlada
- RST (erro) → conexão derrubada imediatamente, sem finalizar corretamente
O erro 104 é sempre RST, ou seja, algo deu errado no backend.
Como isso aparece no log do Nginx
Exemplo típico:
recv() failed (104: Connection reset by peer) while reading response header from upstream
Ou:
upstream prematurely closed connection while reading response header from upstream
Isso indica que:
- o Nginx já estava lendo a resposta
- mas o backend matou a conexão no meio
Cenários comuns que geram o 104
1. Crash ou recycle da aplicação
- ASP.NET reinicia (deploy, OOM, falha)
- conexões abertas são resetadas
👉 Sintoma:
- picos de 104 em massa
- logs de restart no backend
2. Thread pool starvation (muito relevante no seu caso)
Quando todas as threads estão ocupadas:
-
requisições começam a ficar presas
-
o servidor entra em comportamento degradado
-
pode ocorrer:
- timeout interno
- abort de request
- reset de conexão
👉 O backend basicamente “desiste” da conexão
3. Timeout interno do backend
Exemplo:
- timeout do Kestrel
- timeout de middleware
- timeout de downstream (DB, HTTP)
Quando o timeout dispara:
- a conexão pode ser encerrada com RST
4. Aplicação abortando a request explicitamente
Em .NET:
HttpContext.Abort();
ou exceptions não tratadas no pipeline
👉 isso frequentemente gera reset
5. Saturação de recursos (CPU, memória, sockets)
- fila de conexão cheia
- GC agressivo
- pressão de memória
👉 o runtime pode encerrar conexões para se recuperar
Inclusive, problemas de memória e pressão de GC podem levar a comportamentos instáveis e resets sob carga
6. Problemas de rede (menos comum)
- firewall fechando conexão
- keepalive inválido
- proxies intermediários
Mas em sistemas internos, normalmente não é isso.
Linha do tempo do erro (visão real)
- Cliente → Nginx
- Nginx → API (upstream)
- API aceita conexão
- API começa a processar
- Algo dá errado (ex: thread starvation)
- API envia RST
- Nginx loga:
104: Connection reset by peer
Como diferenciar 104 de outros erros
| Erro | Quem causou | Significado |
|---|---|---|
| 110 timeout | Nginx | backend demorou demais |
| 111 refused | backend | nem aceitou conexão |
| 104 reset | backend | aceitou, mas abortou |
| 502 | Nginx | resposta inválida |
| 504 | Nginx | timeout |
👉 104 é o mais “violento”: conexão morreu no meio
Como validar se é problema de threads
Correlacione:
-
muitos
104no Nginx -
aumento de latência
-
CPU não necessariamente 100%
-
métricas do .NET:
- ThreadPool queue length ↑
- Threads disponíveis ↓
-
logs com:
TaskCanceledExceptionTimeoutException
-
uso de
.Result/.Wait()
O livro destaca que problemas de concorrência e uso incorreto do thread pool são causas frequentes de degradação em aplicações de alto throughput.
Diagnóstico direto (prático)
Se você está vendo muito 104:
- 80% das vezes → problema na aplicação
- 15% → timeout mal configurado
- 5% → rede
E em sistemas como o seu (alta concorrência + mensageria + SignalR):
👉 o mais provável é starvation ou saturação interna
Se quiser, posso te montar um checklist direto para produção:
- como provar que é starvation
- quais métricas coletar no .NET
- e como mitigar (sem cair em thread explosion)