Комментарии 12
По этой теме еще вот www.nimaara.com/2016/11/01/beware-of-the-net-httpclient
и вот aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong с вариантами как исправить код.
и вот aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong с вариантами как исправить код.
0
А можно на пальцах рассказать, зачем для чисто серверных операций использовать именно HttpClient, а не HttpWebRequest? Мне всегда казалось, что HttpClient нужен чтоб странички грузить «как в браузере».
0
С точки зрения HTTP протокола, между API, которое возвращает JSON, и обычными страницами, отдающими клиенту HTML, принципиальной разницы нет — это просто разные типы контента. Соответственно, нет и разделения на то, какие типы контента какими классами лучше всего получать. Что выбрать, HttpWebRequest или HttpClient, скорее зависит от удобства, гибкости и производительности который дает каждый их них.
HttpWebRequest очень низкоуровневый, каждый запрос нужно конструировать заново, и на это уходит заметно больше кода, чем на те же действия через HttpClient. При этом, если надо в юнит-тестах сделать мок вместо реальных обращений по сети, то с HttpWebRequest это будет проблематичным: по-хорошему придется вокруг этого класса делать фабрику и в коде использовать ее методы вместо явного создания HttpWebRequest. По сути HttpClient — и есть своего рода фабрика запросов. Она конечно же добавляет своего оверхеда в плане производительности, но для 99% случаев я думаю этим можно пренебречь. В то же время HttpClient значительно упрощает реализацию многих сценариев работы с HTTP и по сути является фасадом к более низкоуровневым классам, таким как HttpWebRequest. Но как и в любой абстракции, в нем есть неявные моменты, которые и описаны в статье.
HttpWebRequest очень низкоуровневый, каждый запрос нужно конструировать заново, и на это уходит заметно больше кода, чем на те же действия через HttpClient. При этом, если надо в юнит-тестах сделать мок вместо реальных обращений по сети, то с HttpWebRequest это будет проблематичным: по-хорошему придется вокруг этого класса делать фабрику и в коде использовать ее методы вместо явного создания HttpWebRequest. По сути HttpClient — и есть своего рода фабрика запросов. Она конечно же добавляет своего оверхеда в плане производительности, но для 99% случаев я думаю этим можно пренебречь. В то же время HttpClient значительно упрощает реализацию многих сценариев работы с HTTP и по сути является фасадом к более низкоуровневым классам, таким как HttpWebRequest. Но как и в любой абстракции, в нем есть неявные моменты, которые и описаны в статье.
+7
HttpWebRequest не поддерживает Timeout для асинхронных операций
stackoverflow.com/a/26214865/136138
stackoverflow.com/a/26214865/136138
+1
Для загрузки страничек «как в браузере» есть headless браузеры.
А HttpClient — это тот же HttpWebRequest, но с более удобным API.
А HttpClient — это тот же HttpWebRequest, но с более удобным API.
+1
>Если нужна как можно более быстрая реакция на изменение IP адреса, например, как в случае балансировки через DNS round-robin
Разве ДНС не возвращает сразу несколько ИП-ов, в которые резолвится домен (getaddrinfo)? Сам HttpClient не сможет переключаться между ними, без доп. запросов к ДНС?
Разве ДНС не возвращает сразу несколько ИП-ов, в которые резолвится домен (getaddrinfo)? Сам HttpClient не сможет переключаться между ними, без доп. запросов к ДНС?
0
С DNS можно сразу получить несколько IP, но в общем случае round-robin работает на базе поведения DNS сервера — либо с каждым запросом возвращается другой IP адрес (по кругу), либо возвращается полный список, но каждый раз с разным порядком адресов (https://en.wikipedia.org/wiki/Round-robin_DNS, blogs.technet.microsoft.com/networking/2009/04/17/dns-round-robin-and-destination-ip-address-selection). Я на практике не наблюдал, чтобы HttpClient при работе с доменом, зарегистрированным на несколько IP адресов, сам бы перебирал их с каждым новым подключением.
0
спасибо, очень интересная и познавательная статья.
побольше бы таких.
буквально на днях делали обмен с использованием HttpClient, нас сильно озадачила скорость передачи данных на локальной тачке и по сети, а все дело оказалось как раз в количестве одновременных подключений, ну и на грабли с утечкой подключений то же наступили ))))
побольше бы таких.
буквально на днях делали обмен с использованием HttpClient, нас сильно озадачила скорость передачи данных на локальной тачке и по сети, а все дело оказалось как раз в количестве одновременных подключений, ну и на грабли с утечкой подключений то же наступили ))))
0
Вот ещё интересное наблюдение ко всему, что наследуется от WebRequest.
Задача:
передать на сайт данные с помощью POST запроса с компьютера, с доступом в сеть через прокси;
Выставляем параметры прокси и аутентификации из настроек сети (System.Net.WebProxy.GetDefaultProxy(), System.Net.CredentialCache.DefaultNetworkCredentials)
Отправляем POST-запрос, если объем переданных данных меньше 100 кБ, все ОК (сначала возвращается 407, потом 200)
Если объем больше — только 407, данные не передаются, на клиент возвращается только таймаут операции. Грешили на прокси, но там таких ограничений не стояло. Подозреваю, что это все же ошибка многопоточности в C#, но могу провести расследование, если кому интересно.
Задача:
передать на сайт данные с помощью POST запроса с компьютера, с доступом в сеть через прокси;
Выставляем параметры прокси и аутентификации из настроек сети (System.Net.WebProxy.GetDefaultProxy(), System.Net.CredentialCache.DefaultNetworkCredentials)
Отправляем POST-запрос, если объем переданных данных меньше 100 кБ, все ОК (сначала возвращается 407, потом 200)
Если объем больше — только 407, данные не передаются, на клиент возвращается только таймаут операции. Грешили на прокси, но там таких ограничений не стояло. Подозреваю, что это все же ошибка многопоточности в C#, но могу провести расследование, если кому интересно.
+1
Позвольте такой вопрос, косвенно связанный с темой:
Есть, к примеру, 100 устройств, распределенных по сети, которые, допустим, два раза в секунду шлют данные на сервер. Данные — строка из ~20 символов. Сервер, в свою очередь, тоже шлет данные на все устройства раз в 3 сек- хертбит. Какую схему сетевого взаимодействия в этом случае корректнее будет применить — постоянно держать открытым tcp-канал, открывать tcp-канал для отправки сообщения и закрывать его за собой или перейти к http-запросам? Испытания/замеры скорости не показали радикальной разницы. Искал ответы на разных тематических форумах, но аргументированного ответа не нашел, решил, что раз наткнулся на эту тему, то это знак.
Есть, к примеру, 100 устройств, распределенных по сети, которые, допустим, два раза в секунду шлют данные на сервер. Данные — строка из ~20 символов. Сервер, в свою очередь, тоже шлет данные на все устройства раз в 3 сек- хертбит. Какую схему сетевого взаимодействия в этом случае корректнее будет применить — постоянно держать открытым tcp-канал, открывать tcp-канал для отправки сообщения и закрывать его за собой или перейти к http-запросам? Испытания/замеры скорости не показали радикальной разницы. Искал ответы на разных тематических форумах, но аргументированного ответа не нашел, решил, что раз наткнулся на эту тему, то это знак.
0
На таком масштабе радикальной разницы не будет. Я так понимаю, подключение не использует SSL, т.е. дополнительные затраты на SSL handshake при установке соединения не идут. Сервер легко выдержит 100 одновременных постоянных подключений, а сдругой стороны — передача данных не настолько частая, чтобы установка соединения вносила какую-то заметную задержку (при условии что канал не настолько плохой, что и 20 байт не всегда быстро доходят, если доходят вообще :)).
В целом, если нет перспективы роста на десятки-сотни тысяч соединений (и даже при такой перспективе тоже могут быть варианты с постоянными соединениями), я бы держал постоянно открытое TCP соединение и по нему бы общался, пересоздавая в случае сбоев.
В целом, если нет перспективы роста на десятки-сотни тысяч соединений (и даже при такой перспективе тоже могут быть варианты с постоянными соединениями), я бы держал постоянно открытое TCP соединение и по нему бы общался, пересоздавая в случае сбоев.
0
Шикарная статья, большое спасибо
-1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Публикации
Изменить настройки темы
Подводные камни HttpClient в .NET