Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core HTTP主体日志中间件性能瓶颈_Asp.net Core_Asp.net Core Webapi_Middleware - Fatal编程技术网

Asp.net core HTTP主体日志中间件性能瓶颈

Asp.net core HTTP主体日志中间件性能瓶颈,asp.net-core,asp.net-core-webapi,middleware,Asp.net Core,Asp.net Core Webapi,Middleware,我试图编写一个中间件,记录应用程序发送给客户端的每个请求和响应的主体。然而,应用程序的性能变得非常糟糕,以至于一个普通请求在80秒后收到响应 公共类日志中间件 { 私有请求委托_next; 专用只读ILogger\u记录器; 公共日志中间件(ILogger记录器,RequestDelegate next) { _记录器=记录器; _下一个=下一个; } 公共异步任务InvokeAsync(HttpContext上下文) { StringBuilder日志=新建StringBuilder(); 尝

我试图编写一个中间件,记录应用程序发送给客户端的每个请求和响应的主体。然而,应用程序的性能变得非常糟糕,以至于一个普通请求在80秒后收到响应

公共类日志中间件
{
私有请求委托_next;
专用只读ILogger\u记录器;
公共日志中间件(ILogger记录器,RequestDelegate next)
{
_记录器=记录器;
_下一个=下一个;
}
公共异步任务InvokeAsync(HttpContext上下文)
{
StringBuilder日志=新建StringBuilder();
尝试
{
//请求
log.Append($“A{context.Request.Method}请求到达{context.Request.Path}{context.Request.QueryString.ToString()}”);
log.Append($”\n请求时间(本地):{DateTime.Now.ToString(“r”)});
if(context.Request.Method.Equals(“POST”,StringComparison.OrdinalIgnoreCase))
{
context.Request.enableBuffer();
使用(var reader=newstreamreader(context.Request.Body,System.Text.Encoding.UTF8,true,1024,true))
{
string body=wait reader.ReadToEndAsync();
string bodyLog=!string.IsNullOrEmpty(正文)?正文:“空”;
追加($“\n正文:{bodyLog}”);
context.Request.Body.Seek(0,SeekOrigin.Begin);
}
}
//回应
var originalBodyStream=context.Response.Body;
使用(var responseBody=newmemorystream())
{
context.Response.Body=responseBody;
//调用下一个中间件
等待下一步(上下文);
var-response=context.response;
response.Body.Seek(0,SeekOrigin.Begin);
string responseText=等待新的StreamReader(response.Body).ReadToEndAsync();
string bodyLog=!string.IsNullOrEmpty(responseText)?responseText:“空”;
response.Body.Seek(0,SeekOrigin.Begin);
log.Append($”\n响应时间(本地):{DateTime.Now.ToString(“r”)});
log.Append($“\n响应状态:{context.Response.StatusCode}”);
追加($“\n正文:{bodyLog}”);
wait responseBody.CopyToAsync(originalBodyStream);
}
}
抓住
{
投掷;
}
最后
{
等待任务。运行(()=>
{
_logger.Log(Log.ToString());
返回Task.CompletedTask;
});
}
}
}
我不太清楚为什么会这样,但很明显我在这里做错了什么。我能做些什么来改进和优化代码,使其运行更流畅

除此之外,我还有一个自定义属性,用于验证目的的一些操作之上,它必须生成正文内容的散列。即使删除中间件(或属性),性能仍然很差,但它们都是日志记录和验证所必需的

公共类SignatureValidationAttribute:ActionFilterAttribute { public SignatureValidationAttribute(){} 公共重写无效OnActionExecuting(ActionExecutingContext上下文) { HttpRequest请求=context.HttpContext.request; IServiceProvider serviceProvider=context.HttpContext.RequestServices; if(request.Headers.TryGetValue(“签名”,out-StringValues)) { context.HttpContext.Request.enableBuffer(); 使用(var reader=newstreamreader(request.Body,System.Text.Encoding.UTF8,true,1024,true)) { request.Body.Seek(0,SeekOrigin.Begin); var jsonBody=reader.ReadToEnd(); request.Body.Seek(0,SeekOrigin.Begin); var signatureService=(ISignatureService)serviceProvider.GetService(typeof(ISignatureService));//MD5 string hash=signatureService.GenerateSignature(jsonBody,“SOMEKEY”); if(values.First()!=hash) { context.Result=新的未授权对象结果(新的 { ErrorMessage=“无效哈希” }); } } } } }
您是否调整了
StreamReader
的构造函数?当您试图读取响应正文(除非非常小)时,1kb的缓冲区大小似乎很小,并且在使用块的
结尾处处理流后,也会使流保持打开状态。同样在中间件的响应端,它似乎将
context.response.Body
设置为
new MemoryStream()
,然后将其作为
new StreamReader()
读取。我没有调整构造函数,是的,响应非常小,所以应该不是什么大问题-我从测试端点I 639B得到的响应。尽管如此,我还是会增加。至于
新的MemoryStream()
,是的,但是应用程序会写入新的流,这样我就可以从中读取多次。您是否调整了
StreamReader
的构造函数?当您试图读取响应正文(除非非常小)时,1kb的缓冲区大小似乎很小,并且在使用
块的
结尾处处理流后,也会使流保持打开状态。同样在中间件的响应端,它似乎设置了<