Наше веб-приложение работает в .Net Framework 4.0. Пользовательский интерфейс вызывает методы контроллера через вызовы ajax.
Нам нужно воспользоваться услугой REST от нашего поставщика. Я оцениваю лучший способ вызвать службу REST в .Net 4.0. Службе REST требуется базовая схема аутентификации, и она может возвращать данные как в формате XML, так и в формате JSON. Нет необходимости загружать / скачивать огромные данные, и я ничего не вижу в будущем. Я взглянул на несколько проектов с открытым исходным кодом для потребления REST и не нашел в них никакой ценности, чтобы оправдать дополнительную зависимость в проекте. Начал оценивать WebClient
и HttpClient
. Я скачал HttpClient для .Net 4.0 с NuGet.
Я искал различия между WebClient
и, HttpClient
и на этом сайте упоминалось, что один HttpClient может обрабатывать одновременные вызовы и может повторно использовать разрешенный DNS, конфигурацию cookie и аутентификацию. Мне еще предстоит увидеть практические ценности, которые мы можем получить из-за различий.
Я сделал быстрый тест производительности, чтобы найти, как WebClient
(синхронизировать вызовы), HttpClient
(синхронизировать и асинхронно) выполняют. и вот результаты:
Использование одного и того же HttpClient
экземпляра для всех запросов (мин. - макс.)
Синхронизация WebClient: 8 мс - 167 мс
Синхронизация HttpClient: 3 мс - 7228 мс
Асинхронность HttpClient: 985 - 10405 мс
Использование нового HttpClient
для каждого запроса (мин. - макс.)
Синхронизация WebClient: 4 мс - 297 мс
Синхронизация HttpClient: 3 мс - 7953 мс
Асинхронность HttpClient: 1027 - 10834 мс
Код
public class AHNData
{
public int i;
public string str;
}
public class Program
{
public static HttpClient httpClient = new HttpClient();
private static readonly string _url = "http://localhost:9000/api/values/";
public static void Main(string[] args)
{
#region "Trace"
Trace.Listeners.Clear();
TextWriterTraceListener twtl = new TextWriterTraceListener(
"C:\\Temp\\REST_Test.txt");
twtl.Name = "TextLogger";
twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;
ConsoleTraceListener ctl = new ConsoleTraceListener(false);
ctl.TraceOutputOptions = TraceOptions.DateTime;
Trace.Listeners.Add(twtl);
Trace.Listeners.Add(ctl);
Trace.AutoFlush = true;
#endregion
int batchSize = 1000;
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = batchSize;
ServicePointManager.DefaultConnectionLimit = 1000000;
Parallel.For(0, batchSize, parallelOptions,
j =>
{
Stopwatch sw1 = Stopwatch.StartNew();
GetDataFromHttpClientAsync<List<AHNData>>(sw1);
});
Parallel.For(0, batchSize, parallelOptions,
j =>
{
Stopwatch sw1 = Stopwatch.StartNew();
GetDataFromHttpClientSync<List<AHNData>>(sw1);
});
Parallel.For(0, batchSize, parallelOptions,
j =>
{
using (WebClient client = new WebClient())
{
Stopwatch sw = Stopwatch.StartNew();
byte[] arr = client.DownloadData(_url);
sw.Stop();
Trace.WriteLine("WebClient Sync " + sw.ElapsedMilliseconds);
}
});
Console.Read();
}
public static T GetDataFromWebClient<T>()
{
using (var webClient = new WebClient())
{
webClient.BaseAddress = _url;
return JsonConvert.DeserializeObject<T>(
webClient.DownloadString(_url));
}
}
public static void GetDataFromHttpClientSync<T>(Stopwatch sw)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(_url).Result;
var obj = JsonConvert.DeserializeObject<T>(
response.Content.ReadAsStringAsync().Result);
sw.Stop();
Trace.WriteLine("HttpClient Sync " + sw.ElapsedMilliseconds);
}
public static void GetDataFromHttpClientAsync<T>(Stopwatch sw)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(_url).ContinueWith(
(a) => {
JsonConvert.DeserializeObject<T>(
a.Result.Content.ReadAsStringAsync().Result);
sw.Stop();
Trace.WriteLine("HttpClient Async " + sw.ElapsedMilliseconds);
}, TaskContinuationOptions.None);
}
}
}
Мои вопросы
- REST-вызовы возвращаются через 3-4 секунды, что приемлемо. Вызовы службы REST инициируются в методах контроллера, которые вызываются из вызовов ajax. Начнем с того, что вызовы выполняются в другом потоке и не блокируют пользовательский интерфейс. Итак, я могу просто придерживаться синхронизации вызовов?
- Приведенный выше код был запущен в моем localbox. В настройке prod будут задействованы DNS и прокси. Есть ли преимущество использования
HttpClient
болееWebClient
? - Является ли
HttpClient
параллелизм лучшеWebClient
? Из результатов теста я вижу, чтоWebClient
синхронизация вызовов работает лучше. - Будет
HttpClient
ли лучший выбор дизайна, если мы перейдем на .Net 4.5? Производительность является ключевым фактором дизайна.
GetDataFromHttpClientAsync
потому что он выполняется первым, другие вызовы получают выгоду от потенциальной возможности кэширования данных (будь то на локальном компьютере или на любом прозрачном прокси между вами и пунктом назначения) и будут быстрее. Кроме того, при правильных условияхvar response = httpClient.GetAsync("http://localhost:9000/api/values/").Result;
может привести к тупиковой ситуации из-за истощения потоков резьбы пула. Никогда не следует блокировать действие, которое зависит от пула потоков в потоках ThreadPool,await
вместо этого следует возвращать поток обратно в пул.Ответы:
Я живу в мире F # и Web API.
С Web API происходит много хорошего, особенно в виде обработчиков сообщений для безопасности и т. Д.
Я знаю, что мое мнение только одно, но я бы порекомендовал использовать его
HttpClient
для любой будущей работы . Возможно, есть какой-то способ использовать некоторые другие компонентыSystem.Net.Http
без непосредственного использования этой сборки, но я не представляю, как это будет работать в настоящее время.Говоря о сравнении этих двух
Если вы используете .NET 4.5, пожалуйста, используйте асинхронные свойства HttpClient, которые Microsoft предоставляет разработчикам. HttpClient очень симметричен по отношению к братьям на стороне сервера HTTP, это HttpRequest и HttpResponse.
Обновление: 5 причин использования нового API HttpClient:
Ссылка
C # 5.0 Джозеф Албахари
(Channel9 - Video Build 2013)
Пять великих причин использовать новый HttpClient API для подключения к веб-сервисам
WebClient против HttpClient против HttpWebRequest
источник
WebClient
похоже, теперь есть асинхронные методы.WebClient
что нет в наличии,.Net Core
ноHttpClient
есть.HttpClient является более новым из API, и он имеет преимущества
Если вы пишете веб-сервис, который выполняет вызовы REST для других веб-сервисов, вам следует использовать модель асинхронного программирования для всех ваших вызовов REST, чтобы вы не столкнулись с истощением потоков. Возможно, вы также захотите использовать новейший компилятор C #, который поддерживает async / await.
Примечание: это не более производительный AFAIK. Вероятно, это будет примерно так же эффективно, если вы создадите честный тест.
источник
HttpClientFactory
Важно оценить различные способы создания HttpClient, и частью этого является понимание HttpClientFactory.
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
Это не прямой ответ, я знаю - но лучше начинать здесь, чем заканчивать
new HttpClient(...)
везде.источник
Во-первых, я не являюсь авторитетом в WebClient против HttpClient, в частности. Во-вторых, из ваших комментариев выше, кажется, можно предположить, что WebClient синхронизирован ТОЛЬКО, тогда как HttpClient - оба.
Я вижу в этом огромную разницу, думая о будущем, то есть о длительно запущенных процессах, адаптивном графическом интерфейсе и т. Д. (Добавьте к преимуществу, которое вы предлагаете с помощью платформы 4.5, которая в моем реальном опыте значительно быстрее в IIS)
источник
WebClient
похоже, что в последних версиях .NET есть асинхронные возможности. Я хотел бы знать, почему он выглядит лучше, чем HttpClient в таких масштабных масштабах.У меня есть тест между HttpClient, WebClient, HttpWebResponse, а затем вызвать Rest Web Api
и результат Call Rest Web Api Benchmark
--------------------- Этап 1 ---- 10 Запрос
{00: 00: 17.2232544} ====> HttpClinet
{00: 00: 04.3108986} ====> WebRequest
{00: 00: 04.5436889} ====> WebClient
--------------------- Этап 1 ---- 10 Запрос - Малый размер
{00: 00: 17,2232544} ====> HttpClinet
{00: 00: 04,3108986} ====> WebRequest
{00: 00: 04,5436889} ====> WebClient
--------------------- Этап 3 ---- 10 запросов синхронизации - Малый размер
{00: 00: 15,3047502} ====> HttpClinet
{00: 00: 03,5505249} ====> WebRequest
{00: 00: 04,0761359} ====> WebClient
--------------------- Этап 4 ---- Запрос синхронизации 100 - Малый размер
{00: 03: 23,6268086} ====> HttpClinet
{00: 00: 47,1406632} ====> WebRequest
{00: 01: 01,2319499} ====> WebClient
--------------------- Этап 5 ---- 10 Запрос синхронизации - Максимальный размер
{00: 00: 58,1804677} ====> HttpClinet
{00: 00: 58,0710444} ====> WebRequest
{00: 00: 38,4170938} ====> WebClient
--------------------- Этап 6 ---- 10 Запрос синхронизации - Максимальный размер
{00: 01: 04,9964278} ====> HttpClinet
{00: 00: 59,1429764} ====> WebRequest
{00: 00: 32,0584836} ====> WebClient
_____ веб-клиент быстрее ()
// ------------------------- функции
источник
Возможно, вы могли бы думать о проблеме по-другому.
WebClient
иHttpClient
по существу разные реализации одной и той же вещи. Что я рекомендую, так это внедрение шаблона внедрения зависимостей. с контейнером IoC во всем приложении. Вы должны создать клиентский интерфейс с более высоким уровнем абстракции, чем низкий уровень HTTP-передачи. Вы можете написать конкретные классы, которые используют обаWebClient
иHttpClient
, а затем использовать контейнер IoC для внедрения реализации через config.То , что это позволит вам сделать будет переключаться между
HttpClient
иWebClient
легко , так что вы можете объективно тест в производственной среде.Итак, такие вопросы, как:
На самом деле можно получить объективный ответ путем переключения между двумя реализациями клиента с использованием контейнера IoC. Вот пример интерфейса, от которого вы можете зависеть, который не содержит никаких подробностей о
HttpClient
илиWebClient
.Полный код
Реализация HttpClient
Вы можете использовать,
Task.Run
чтобы сделатьWebClient
асинхронного запуска в своей реализации.Внедрение зависимостей, если все сделано правильно, помогает облегчить необходимость принятия решений низкого уровня заранее. В конечном счете, единственный способ узнать верный ответ - попробовать как в реальной среде, так и посмотреть, какой из них работает лучше всего. Вполне возможно, что это
WebClient
может работать лучше для некоторых клиентов, иHttpClient
может работать лучше для других. Вот почему абстракция важна. Это означает, что код можно быстро поменять местами или изменить с помощью конфигурации, не меняя основной дизайн приложения.источник
Непопулярное мнение с 2020 года:
Когда дело доходит до ASP.NET приложений я предпочитаю
WebClient
более ,HttpClient
потому что:источник