it-swarm.com.ru

System.Net.Http.HttpRequestException Ошибка при копировании содержимого в поток

Я использую HttpClient класс в .Net 4.5.2 Framework. Я делаю PostAsync со сторонним веб-сервисом. 80% времени работы этого поста, 20% времени наш ответ прерывается. В этой ситуации мы получаем следующее исключение: 

System.Net.Http.HttpRequestException: Ошибка при копировании содержимого в поток. ---> System.IO.IOException: невозможно прочитать данные из транспортное соединение: существующее соединение было принудительно закрыто удаленный хост. ---> System.Net.Sockets.SocketException: существующий соединение было принудительно закрыто удаленным хостом по адресу System.Net.Sockets.NetworkStream.BeginRead (буфер Byte [], Int32 Смещение, размер Int32, обратный вызов AsyncCallback, состояние объекта) --- Конец внутренней трассировки стека исключений --- at System.Net.Sockets.NetworkStream.BeginRead (буфер Byte [], смещение Int32 , Размер Int32, обратный вызов AsyncCallback, состояние объекта) в System.Net.FixedSizeReader.StartReading () в System.Net.Security._SslStream.StartFrameHeader (буфер Byte [], смещение Int32 .__, счетчик Int32, AsyncProtocolRequest asyncRequest) в System.Net.Security._SslStream.StartReading (буфер Byte [], Int32 Смещение, счетчик Int32, AsyncProtocolRequest asyncRequest) в System.Net.Security._SslStream.ProcessRead (буфер Byte [], смещение Int32 , Счетчик Int32, asyncRequest AsyncProtocolRequest) в System.Net.TlsStream.BeginRead (буфер Byte [], смещение Int32, размер Int32 , AsyncCallback asyncCallback, объект asyncState) в System.Net.ConnectStream.BeginReadWithoutValidation (буфер Byte [], смещение Int32, размер Int32, обратный вызов AsyncCallback, состояние объекта) в System.Net.ConnectStream.BeginRead (буфер Byte [], смещение Int32, размер Int32 .__, обратный вызов AsyncCallback, состояние объекта) в System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead (буфер Byte [] , Смещение Int32, счетчик Int32, обратный вызов AsyncCallback, состояние Object .__) в System.Net.Http.StreamToStreamCopy.StartRead ()

Последующий идентичный запрос выполняется . Это не тот запрос, который мы можем повторить, так как бизнес уже размещен. Так что это оставляет нас в неловкой ситуации.

Это мой код:

using (var httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.Authorization = authorizationHeader;
    HttpContent httpContent = new StringContent(someXml);

    //Exception occurs on next line...
    var response = await httpClient.PostAsync("https://thirdpartyendpoint", httpContent);
    var responseXml = await response.Content.ReadAsStringAsync();  
    //convert to Dto              
}

Сторонние службы успешно сохраняют записи в своей базе данных и не видят никаких очевидных исключений в их конце. Они отметили, что ошибочные запросы обычно занимали больше времени (около 18-30 секунд) для записи в базу данных, чем успешные запросы.

Спасибо за помощь

10
jonho

мы решили эту проблему с двумя изменениями кода:

  1. Избавьтесь от httpResponseMessage и просто работайте с простым DTO

     using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
        {
            return await CreateDto(httpResponseMessage);
        }
    
  2. Понизьте версию HTTP до версии 1.0 

    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(url))
    {
        Version = HttpVersion.Version10,
        Content = httpContent
    };
    
    await client.SendAsync(httpRequestMessage);
    

который имеет эффект добавления этого заголовка Http

    Connection: close 

а не это

    Connection: keep-alive
15
jonho

У меня была похожая проблема с использованием общего HttpClient, подключающегося к серверу для вызовов REST. В результате возникла проблема с несоответствием времени ожидания KeepAlive на клиенте и сервере. Тайм-аут на стороне клиента устанавливается параметром MaxServicePointIdleTime в ServicePointManager и по умолчанию равен 100 с. Время ожидания на стороне сервера было установлено на нашем сервере более коротким.

Сокращение времени ожидания на сервере по сравнению с клиентом привело к тому, что сервер время от времени закрывал соединение, когда клиент пытался подключиться. Это привело к сообщенному исключению.

Обратите внимание, что я в конечном итоге обнаружил проблему, потому что я также получил это исключение при тех же условиях:

System.Net.WebException: The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
0
Steve Wranovsky