Connection was a closed error between HttpClient and ASP.NET Core 2.0 webservice

I have an ASP.NET Core 2.0 web service that runs on IIS. One of the controller methods looks something like this:

[HttpGet()]
public IActionResult Test()
{
    // do some db updates and get data
    var result = DoSomeStuff();
    // serialize data to byte array
    var output = Serialize(result);

    return File(output, "application/octet-stream");
}

It performs some database updates, records of queries from a table, serializes data and sends them as an answer. Data is sent in binary format. I am using MessagePack-CSharp as a serializer.

Then I have a client application that communicates with this web service. This is the .NET Standard 2.0 library referenced by the .NET 4.6.1 console application. I use HttpClientto request and HttpResponseMessage.Content.ReadAsByteArrayAsync()to read the response (see the exact code below).

. cca. 80 cca. 140000 . . db , cca. 34 .

10 . webservice, . , ( , 4-5).

: ReadAsByteArrayAsync:

System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.ConnectStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
...
---> (Inner Exception #0) System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.ConnectStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
...

SO, (, ), , , . :

  • HTTP 1.0
  • Connection: close Connection: keep-alive
  • .

. , - , HttpClient ( ). System.Net.Http Nuget. . .NET Core Core HttpClient. . HttpWebRequest HttpClient. .

webservice VM. , . .

, ( 10 ):

private async void Test_Click(object sender, RoutedEventArgs e)
{
    try
    {
        var tasks = Enumerable.Range(1, 10).Select(async i => await Task.Run(async () => await GetContent(i))).ToList();

        await Task.WhenAll(tasks);

        MessageBox.Show(String.Join(Environment.NewLine, tasks.Select(t => t.Result.ToString())));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private async Task<Int32> GetContent(Int32 id)
{
    using (var httpClient = new HttpClient())
    {
        var url = "http://localhost/TestService/api/test";

        using (var responseMessage = await httpClient.GetAsync(url).ConfigureAwait(false))
        {
            // just read everything and return length
            // ReadAsByteArrayAsync throws sometimes an exception
            var content = await responseMessage.Content.ReadAsByteArrayAsync();
            return content.Length;
        }
    }
}

, Fiddler. , Fiddler , , ​​ (6 , 20 ,... 34 ). , . Wireshark, , RST/ACK , .

, . , , - . . :

info: Microsoft.AspNetCore.Server.Kestrel[28]
      Connection id "0HL89D9NUNEOQ", Request id "0HL89D9NUNEOQ:00000001": the connection was closed becuase the response was not read by the client at the specified minimum data rate.
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
      Connection id "0HL89D9NUNEOQ" disconnecting.
...
info: Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv[14]
      Connection id "0HL89D9NUNEOQ" communication error.
Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking.UvException: Error -4081 ECANCELED operation canceled

ASP.NET Core, . , IIS :

<system.applicationHost>
  <webLimits minBytesPerSecond="0"/>
</system.applicationHost>

Web.config, ( ASP.NET Core ?).

FileStreamResult FileContentResult, - .

. Thread.Sleep(8000) ( db), 50 . - , , . , db , , ( , ,...).

? , .

+4
1

, . Kestrel:

Kestrel , /. , . - , Kestrel ; . , - TCP.

- 240 5- .

. , RequestBody Response .

Program.cs :

var host = new WebHostBuilder() 
    .UseKestrel(options => 
    { 
        options.Limits.MinResponseDataRate = null;
    })

null , .

+2

Source: https://habr.com/ru/post/1686956/


All Articles