Skip to main content

Erro 104 no NGINX com .NET na visão do Kestrel | (104: Connection reset by peer) while reading response header from upstream | Ambiente .NET

  • Erro 104 no NGINX com .NET na visão do Kestrel | (104: Connection reset by peer) while reading response header from upstream | Ambiente .NET

Erro 104 no Nginx com Kestrel como Upstream

Contexto

Arquitetura comum em aplicações ASP.NET Core expostas via proxy reverso:

Cliente → Nginx → Kestrel (ASP.NET Core)

Esta documentação descreve o significado do erro 104 (Connection reset by peer) no Nginx, o comportamento do Kestrel nesse cenário e os limites de timeout e proteção aplicados pelo servidor.


O que é o erro 104 no Nginx

Exemplo de log:

recv() failed (104: Connection reset by peer) while reading response header from upstream
  • Código 104 corresponde ao erro ECONNRESET
  • Indica que o upstream (Kestrel) encerrou a conexão TCP abruptamente
  • O reset ocorre antes do envio dos headers da resposta

O encerramento da conexão é iniciado pelo Kestrel ou pelo processo que o hospeda, não pelo Nginx.


O que aconteceu com o Kestrel

O erro 104 indica que o Kestrel tomou a iniciativa de encerrar a conexão. As causas mais comuns são:

Abort da request pela aplicação

  • Exception não tratada durante o processamento
  • Middleware interrompendo a pipeline
  • Chamada explícita de HttpContext.Abort()
  • Cancelamento interno não tratado

Nesse caso, o Kestrel envia um TCP RST, resultando no erro 104 no Nginx.


Reinício ou término do processo

  • Crash do processo dotnet
  • OOM Kill
  • Reinício de container ou pod
  • Deploy com restart

Conexões abertas são encerradas imediatamente.


Violação de limites internos do Kestrel

O Kestrel possui limites de proteção que, ao serem violados, provocam o encerramento da conexão.


Timeouts e limites definidos pelo Kestrel

O Kestrel não impõe um timeout global para a duração total do processamento de uma request. Os limites são aplicados a fases específicas da comunicação HTTP.


RequestHeadersTimeout

options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
  • Valor padrão: 30 segundos
  • Tempo máximo para o recebimento completo dos headers
  • Ao estourar, a conexão é abortada

KeepAliveTimeout

options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
  • Valor padrão: 2 minutos
  • Tempo máximo de inatividade de uma conexão keep-alive

MinRequestBodyDataRate

options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 240, gracePeriod: TimeSpan.FromSeconds(5));
  • Valor padrão: 240 bytes por segundo após 5 segundos
  • Protege contra uploads excessivamente lentos
  • Violação resulta no encerramento da conexão

MinResponseDataRate

options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 240, gracePeriod: TimeSpan.FromSeconds(5));
  • Valor padrão: 240 bytes por segundo
  • Se a resposta não for consumida com velocidade mínima, a conexão é encerrada
  • Pode afetar streaming lento ou respostas grandes

MaxRequestBodySize

options.Limits.MaxRequestBodySize = 30_000_000;
  • Valor padrão aproximado: 30 MB
  • Requests acima desse limite são rejeitadas
  • Dependendo do estágio, pode ocorrer reset da conexão

O que o Kestrel não faz

  • Não encerra requests longas com base apenas no tempo de execução
  • Não aplica timeout global por controller ou action
  • Não cancela automaticamente o código em execução

O processamento continua até que o código respeite o token HttpContext.RequestAborted.


Diferença entre erros comuns no Nginx

CódigoOrigemDescrição
104KestrelReset da conexão TCP
504NginxTimeout de leitura do upstream
499ClienteCliente encerrou a conexão
502NginxBackend indisponível ou inválido

Pontos de diagnóstico

  • Logs do ASP.NET Core e do Kestrel
  • Eventos de restart de container ou pod
  • Métricas de memória e CPU
  • Comparação entre timeouts do Nginx e limites do Kestrel

Boas práticas operacionais

  • Propagar HttpContext.RequestAborted para serviços internos
  • Ajustar limites do Kestrel conforme o perfil da aplicação
  • Evitar processamento pesado síncrono em requests HTTP
  • Utilizar filas ou processamento assíncrono para tarefas longas

Documentações

Configuração do Kestrel - Definição de timeouts: 🔗 Clique aqui Classe onde contém o aborto por tempo limite do envio dos headers: 🔗 Clique aqui