zoukankan      html  css  js  c++  java
  • .Net核心中间件httpContext不支持并发读写 Concurrent reads or writes are not supported.

    .Net核心中间件httpContext不支持并发读写

    Concurrent reads or writes are not supported.

    writing is not allowed after writer was completed

    看到早上的日出,今天又是充满希望的一天,开开心心上班到中午,系统出现一个神奇的问题。国内度神上狂搜,结果哪,没什么结果....搬个梯子去google看看,可能梯子午睡还没醒,10个网页9个打不开.。也许真的是充满希望的一天,在google上只打开了两个网页,其中一个就是解决方案。

    环境:net core 5.0   web api  +  ES

    我在.Net核心中添加了一个中间件,该中间件记录了每个api请求和对nLog的响应。它对我来说很好用,即使没有发现任何问题。今天,我试图向API发出批量请求,但收到了异常,这是个很异常很有意思,第一次请求接口可正常访问,第二次出现异常“Concurrent reads or writes are not supported.”,这个错误,只有使用 Framework 程序访问才会出现。

     

     1 {
     2     "Timestamp":"2021-03-02T15:21:17.6426051+08:00",
     3     "Level":"Error",
     4     "MessageTemplate":"Unexpected exception in "{ClassName}.{MethodName}".",
     5     "Exception":"System.InvalidOperationException: Writing is not allowed after writer was completed.
       
     6         at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_NoWritingAllowed()
       
     7         at System.IO.Pipelines.Pipe.GetMemory(Int32 sizeHint)
       
     8         at System.IO.Pipelines.Pipe.DefaultPipeWriter.GetMemory(Int32 sizeHint)
       
     9         at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadBody()",
    10     "Properties":
    11     {
    12         "ClassName":"IISHttpContext",
    13         "MethodName":"ReadBody",
    14         "EventId":
    15         {
    16             "Id":3,
    17             "Name":"UnexpectedError"
    18         },
    19         "SourceContext":"Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer",
    20         "RequestId":"8000bab3-0000-ff00-b63f-84710c7967bb",
    21         "RequestPath":"/api/v1/ProductBatch/ProductBatchAdd"
    22     }
    23 }

    换了另一个日志记录,出现另一个错误“writing is not allowed after writer was completed”

    1 [18:00:37 ERR] Unexpected exception in "IISHttpContext.ReadBody".
    2 System.InvalidOperationException: Writing is not allowed after writer was completed.
    3    at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_NoWritingAllowed()
    4    at System.IO.Pipelines.Pipe.GetMemory(Int32 sizeHint)
    5    at System.IO.Pipelines.Pipe.DefaultPipeWriter.GetMemory(Int32 sizeHint)
    6    at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadBody()

    .Net核心中间件httpContext不支持并发读写

    我在这个水平上有些困惑

    1. .Net核心是否为每个请求创建单独的管道。我认为是的,因为HttpContext.Items对于每个请求周期都是唯一的。
    2. 如果是,那为什么我会收到并发错误。作为我的代码,首先记录请求,然后将上下文传递给下一个中间件,最后记录响应。

    请您分享更好的方法来解决此问题。

     1  public class LoggingMiddleware
     2 {
     3     readonly ILogger logger;
     4     readonly RequestDelegate next;
     5     public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
     6     {
     7         this.logger = logger;
     8         this.next = next;
     9     }
    10 
    11     public async Task Invoke(HttpContext context)
    12     {
    13         LogRequest(context);
    14         var originalBodyStream = context.Response.Body;
    15         using (var responseBody = new MemoryStream())
    16         {
    17             context.Response.Body = responseBody;
    18             await next(context).ConfigureAwait(false);
    19             LogResponse(context);
    20             await responseBody.CopyToAsync(originalBodyStream).ConfigureAwait(false);
    21         }
    22     }
    23     private async void LogRequest(HttpContext context)
    24     {
    25         var request = context.Request;
    26         request.EnableRewind();
    27         var buffer = new byte[Convert.ToInt32(request.ContentLength)];
    28         await request.Body.ReadAsync(buffer, 0, buffer.Length);
    29         string requestBody = Encoding.UTF8.GetString(buffer);
    30         request.Body.Seek(0, SeekOrigin.Begin);
    31         context.Items["Request"] = requestBody;     //Request is being used in Nlog config
    32         logger.LogInformation("Request received ......");       // Some information
    33 
    34         context.Items.Remove("Request");
    35     }
    36 
    37     private async void LogResponse(HttpContext context)
    38     {
    39         var response = context.Response;
    40         response.Body.Seek(0, SeekOrigin.Begin);
    41         var responseText = await new StreamReader(response.Body).ReadToEndAsync().ConfigureAwait(false);
    42         response.Body.Seek(0, SeekOrigin.Begin);
    43 
    44         context.Items["Response"] = responseText;
    45         logger.LogInformation("Returned response for url with status");     // Information
    46         context.Items.Remove("Response");
    47     }
    48 
    49 }

    主要问题出在“ await request.Body.ReadAsync(buffer, 0, buffer.Length); ” ,需要使用 await 修改为同步模式。

    参考

    https://stackoverflow.com/questions/58095947/net-core-middleware-httpcontext-concurrent-read-and-write-not-supported

  • 相关阅读:
    JS动态添加事件
    Asp.Net验证控件浅析
    word 文档如何加密
    scp 自动带密码参数复制文件到主机
    Zabbix监控Dell服务器相关硬件资源
    Zabbix的history相关数据表数据太大,执行表分区操作过程
    mysql日常操作
    linux下利用tcpdump抓包工具排查nginx获取客户端真实IP实例
    解决ssh登录很慢的问题以及jumpserver登录主机出现:Authentication timeout
    keepalived启动后报错:(VI_1): received an invalid passwd!的解决办法
  • 原文地址:https://www.cnblogs.com/ypeuee/p/14472724.html
Copyright © 2011-2022 走看看