Наше веб-приложение работает в .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
для всех запросов (min-max)
Синхронизация WebClient: 8 мс - 167 мс
Синхронизация HttpClient: 3 мс - 7228 мс
HttpClient async: 985 - 10405 мс
Используя новый HttpClient
для каждого запроса (min - max)
Синхронизация WebClient: 4 мс - 297 мс
Синхронизация HttpClient: 3 мс - 7953 мс
HttpClient async: 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 звонки. Начнем с того, что вызовы выполняются в другом потоке и не блокирует пользовательский интерфейс. Итак, могу ли я просто придерживаться вызовов синхронизации?
- Вышеупомянутый код был запущен в моем локальном блоке. В настройке prod DNS и прокси-сервер
поиск будет задействован. Есть ли преимущество использования
HttpClient
надWebClient
? - Является ли
HttpClient
concurrency лучше, чемWebClient
? Из результатов теста я вижу, чтоWebClient
вызовы синхронизации выполняются лучше. - Будет ли
HttpClient
лучшим выбором дизайна, если мы перейдем на .Net 4.5? Производительность является ключевым фактором проектирования.