• .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

  • 相关阅读:
    使用python和java两种方式来完成下载网页,并保存成文件,
    python 如何把 utf 8 字符串写入文件中_心若止水_百度空间
    如何在linux上架设PPPoE server?
    PHP学习之十三:变量函数
    iPhone开发:iOS Framework制作研究
    iPhone开发:浅析ObjectiveC的动态特性
    Windows Phone 7 开发之Microsoft.Phone.Tasks中的各项Task
    windows phone7 开发 使用系统资源
    Windows Phone 开发之 设备方向
    window phone开发之 WebClient 讲解
  • 原文地址:https://www.cnblogs.com/ypeuee/p/14472724.html
Copyright © 2020-2023  润新知