我们有一个流量很大的网站。特别是在高峰时段,当人们快速浏览大量页面时,我们的日志中会出现如下所示的异常:
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Unexpected end of request content.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
at System.IO.StreamReader.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
at Newtonsoft.Json.JsonTextReader.ReadDataAsync(Boolean append, Int32 charsRequired, CancellationToken cancellationToken)
at Newtonsoft.Json.JsonTextReader.ParseValueAsync(CancellationToken cancellationToken)
[...]
我不想关注代码本身,因为它无关紧要。
在 ValueProviding for ASP.NET 期间有类似的事情:
var stream_reader = new StreamReader(context.ActionContext.HttpContext.Request.Body);
var json_reader = new JsonTextReader(stream_reader);
bool success = await json_reader.ReadAsync();
我从未能够在我的调试环境中复制这些错误。我有一种感觉,当用户更改页面时发生 XHR 请求时,就会发生这种情况。
一些浏览器只是停止整个请求,因此他们不再发送他们承诺的有效负载。
这些只是假设。我真的很难找到任何相关信息。
我找到了this帖子,但其中有很多零散的意见。
有些人正在等待 ASP.NET 的错误修复,但与此同时,这完全让我的日志充满了错误。
我可以安全地捕获此处的
BadHttpRequestException
异常并忽略它们吗?或者我可能会错过关键错误吗?有没有这方面的决定性信息?
我可以在这里安全地捕获 BadHttpRequestException 异常吗? 别理他们?或者我可能会错过关键错误吗?有没有 有什么决定性的信息吗?
根据您共享的代码片段和描述,我尝试重现您的问题。然而,正如您也提到的,它是间歇性发生的,在我这边也很难重现这个问题。
因为,这可能会因为很多原因而变得混乱。例如,缺少请求正文部分、格式错误或太大,它会抛出 BadHttpRequestException。发生这种情况的原因通常是网络问题、用户取消、内容类型错误、标头丢失或请求方法不正确。
因此,为了解决这个问题,很难为您提供任何直接的解决方案,相反,您可以继续记录通常发生的错误,尝试检查应用程序日志、事件查看器日志。
如果这个异常肯定会阻塞您的应用程序,您可以捕获错误并记录,最后忽略或抛出响应,这样就不会限制方法执行。
您可以执行以下操作:
public class BadReqeustHandlerController : ControllerBase
{
private readonly ILogger<BadReqeustHandlerController> _logger;
public BadReqeustHandlerController(ILogger<BadReqeustHandlerController> logger)
{
_logger = logger;
}
[HttpPost]
[Route("BadRequestBodyHandlerMethod")]
public async Task<IActionResult> BadRequestBodyHandlerMethod()
{
try
{
string requestBody;
using (var reader = new StreamReader(HttpContext.Request.Body))
{
requestBody = await reader.ReadToEndAsync();
}
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(requestBody);
return Ok(data);
}
catch (BadHttpRequestException ex) when (ex.Message.Contains("Unexpected end of request content"))
{
_logger.LogWarning("BadHttpRequestException: Unexpected end of request content - {Message}", ex.Message);
// Ignore this exception, as it's likely due to client disconnection
return StatusCode(StatusCodes.Status400BadRequest, "Client disconnected before the request could be completed.");
}
catch (JsonException ex)
{
_logger.LogWarning("JSON exception occurred: {Message}", ex.Message);
return StatusCode(StatusCodes.Status400BadRequest, "Malformed JSON request.");
}
catch (Exception ex)
{
_logger.LogError(ex, "An unexpected error occurred");
return StatusCode(StatusCodes.Status500InternalServerError, "An unexpected error occurred.");
}
}
}
注意: 正如您所看到的,当没有错误或异常时,该方法将毫无问题地执行。但是,虽然会立即出现任何问题
BadHttpRequestException
或 JsonException
,但它会立即记录错误并返回响应,而不会阻止操作。
输出:
注意: 请记住,这不是我之前告诉您的确切解决方案。除了上述 catch 中的异常处理程序之外,您还可以考虑使用 asp.net core 中间件 来处理任何类型的间歇性问题。