我正在尝试制作OwinMiddleware,它将捕获所有用户请求并将其记录到DB。它几乎可以正常工作,但在高负载时会落入System.ObjectDisposedException: Cannot access a disposed object
。
public override async Task Invoke(IOwinContext context)
{
try
{
if (GetMonitoringMode() == (int)MonitoringMode.TurnedOff)
{
await Next.Invoke(context);
return;
}
var userId = GetUserId(context);
if (userId is null || userId == 0)
{
await Next.Invoke(context);
return;
}
var startTime = DateTime.UtcNow;
var flatHeaders = context.Request.Headers?.ToDictionary();
var trimmedFlatHeaders = flatHeaders?.TrimSecretStrings(KnownHeaderNames.Authorization, SecretStringTrimLimit) ?? "null";
var requestBody = await GetRequestBody(context, false);
var trimmedRequestBody = requestBody?.TrimSecretStrings(SecretStringTrimLimit) ?? "null";
var stream = context.Response.Body;
var buffer = new MemoryStream();
context.Response.Body = buffer;
await Next.Invoke(context);
buffer.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(buffer);
var responseBody = await reader.ReadToEndAsync();
var trimmedResponseBody = responseBody?.TrimSecretStrings(SecretStringTrimLimit);
buffer.Seek(0, SeekOrigin.Begin);
await buffer.CopyToAsync(stream);
if (GetMonitoringMode() == (int)MonitoringMode.Partial) // Here it falls
{
trimmedRequestBody = "null";
trimmedResponseBody = null;
}
var endTime = DateTime.UtcNow;
// Create api call record
CreateApiCallRecord(new ApiCallRecord
{
ApiName = GetApiName(context),
Ip4Source = context.Request.RemoteIpAddress,
UserId = userId.Value,
StartTime = startTime,
EndTime = endTime,
Request = "{" +
$"\"Request\": {trimmedRequestBody}, " +
$"\"Headers\": {trimmedFlatHeaders}" +
"}",
Response = trimmedResponseBody
});
}
catch (Exception ex)
{
_logger.LogError($"{ex}");
return;
}
}
GetMonitoringMode
进行WCF调用。我发现关闭WCF客户端可能导致此问题的信息。在中间件的开始阶段也不能调用它,因此我尝试将其结果存储在变量中,但是它仍然以相同的方式下降,并带有相同的错误。
以下是一些日志:
Object name: 'Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerResponse'.
at Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerResponse.ResponseBodyStarted()
at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.OneTimeCallback.TryInvoke()
at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.<WriteAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ProjectName.UserActivityMonitoringMiddleware.<Invoke>d__2.MoveNext() in ...\UserActivityMonitoringMiddleware.cs:line 62
有什么解决方法吗?