Skip to main content

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)

  1. Cliente → Nginx
  2. Nginx → API (upstream)
  3. API aceita conexão
  4. API começa a processar
  5. Algo dá errado (ex: thread starvation)
  6. API envia RST
  7. Nginx loga:
104: Connection reset by peer

Como diferenciar 104 de outros erros

ErroQuem causouSignificado
110 timeoutNginxbackend demorou demais
111 refusedbackendnem aceitou conexão
104 resetbackendaceitou, mas abortou
502Nginxresposta inválida
504Nginxtimeout

👉 104 é o mais “violento”: conexão morreu no meio


Como validar se é problema de threads

Correlacione:

  • muitos 104 no Nginx

  • aumento de latência

  • CPU não necessariamente 100%

  • métricas do .NET:

    • ThreadPool queue length ↑
    • Threads disponíveis ↓
  • logs com:

    • TaskCanceledException
    • TimeoutException
  • 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)