HttpClient выдает сообщение «Произошла ошибка при отправке запроса». - PullRequest
5 голосов
/ 07 мая 2020

У меня трехуровневая архитектура приложения.

Мой клиент -> Моя служба A (REST размещен в IIS) -> Служба другой команды X ( REST).

Service A - это ASP. Net 4.6.1 framework, а не ASP. Net Core.

Клиент обменивается данными с A с помощью HttpClient, а A - это общение с X с помощью HttpClient.

Клиент запускает почти 2500 вызовов моей службы для A и X.

Из 2500 вызовов служба A случайным образом (может быть 10 вызовов) не работает с исключением ниже . Это не воспроизводится.

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> 
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a 
receive. ---> System.IO.IOException: Unable to read data from the transport connection: An     
established connection was aborted by the software in your host machine. ---> 
System.Net.Sockets.SocketException: An established connection was aborted by the software in your 
host machine
at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags 
socketFlags, AsyncCallback callback, Object state)
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback 
callback, Object state)
 --- End of inner exception stack trace ---
at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace --

Вот моя услуга Звонок. A в IIS вызывает нижеприведенный блок кода и вызывается каждым запросом. X принимает учетные данные пользователя и возвращает данные в зависимости от пользователя, поэтому мы не разделяем HttpClient между вызовами.

var user = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
            System.Security.Principal.WindowsIdentity.RunImpersonated(user.AccessToken, () =>
      {
        static HttpClient Client = new HttpClient();
        static string CallX(string[] args)
        {
            HttpClientHandler handler = new HttpClientHandler
            {
                UseDefaultCredentials = true
            };    

            Client = new HttpClient(handler)
            {
                BaseAddress = new Uri("http://XserviceUrl/api/")
            };
            Client.Timeout = TimeSpan.FromSeconds(600);    
            var result = Client.PostAsync("Fake X controller"
                , new StringContent(JsonConvert.SerializeObject(args)
                , Encoding.UTF8, "application/json")).Result;    

            result.EnsureSuccessStatusCode();

            var json = result.Content.ReadAsStringAsync().Result;
            return DosomethingWithResult(json);    
        }
    });

Вещи, которые я пробовал:

Некоторые предлагаемые сообщения SO могут быть проблемой тайм-аута. Поэтому я добавил 600 секунд в Client и Service A. Я также изменил время ожидания запроса IIS с 2 минут по умолчанию на 10 (600 секунд).

Ответы [ 2 ]

3 голосов
/ 13 мая 2020

Я сталкиваюсь с той же проблемой в производственной среде. Аналогичная настройка и около 30к http-вызовов отправляются с клиента. Ошибки возникают очень редко и их очень сложно воспроизвести.

После прочтения множества сообщений я думаю, что это ошибка Microsoft при создании пула соединений в HttpClient (в моем решении я использую httpClientFactory). Вы можете посмотреть здесь https://github.com/dotnet/runtime/issues/26629

Подход, который использовался для решения этой проблемы, пока Microsoft не исправила проблему:

1) Политика повторных попыток. Был использован Polly, и когда возникает это исключение, вызов повторяется через пару секунд.

2) Увеличен тайм-аут запроса до 3 минут.

Кажется, сейчас все работает нормально, но как Я упоминал ранее, что трудно воспроизвести ошибку контролируемым образом.

1 голос
/ 15 мая 2020

Эти HTTP-запросы временами сложны, и, поскольку вы пытаетесь выполнить примерно 2500 вызовов к A и X, это не всегда необходимо каждый раз, когда вы получаете ответ «ОК», поскольку на это есть много факторов: -Установка соединения -Время ответа от целевых серверов и т. Д. c.

Повторите попытку неудачного запроса, сохраните тайм-аут, как это было, убедитесь, что вы добавили блок try-catch и повторите попытку неудачного запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...