Web uygulamamız .Net Framework 4.0'da çalışıyor. Kullanıcı arayüzü denetleyici yöntemlerini ajax çağrıları aracılığıyla çağırır.
REST servisini tedarikçimizden tüketmemiz gerekiyor. .Net 4.0'da REST hizmetini çağırmanın en iyi yolunu değerlendiriyorum. REST hizmeti Temel Kimlik Doğrulama Düzeni gerektirir ve hem XML hem de JSON'da veri döndürebilir. Büyük veri yükleme / indirme zorunluluğu yoktur ve gelecekte hiçbir şey göremiyorum. REST tüketimi için birkaç açık kaynak kodlu projeye baktım ve projede ek bağımlılığı haklı çıkaracak herhangi bir değer bulamadım. Değerlendirmeye başladı WebClient
ve HttpClient
. NuGet'ten .Net 4.0 için HttpClient'i indirdim.
Ben arasındaki farkların aramış WebClient
ve HttpClient
ve bu site bu tek HttpClient işleyebilir eşzamanlı aramalar söz ve DNS, çerez yapılandırma ve kimlik çözüldü yeniden kullanabilirsiniz. Farklılıklar nedeniyle kazanabileceğimiz pratik değerleri henüz göremiyorum.
Nasıl WebClient
(senkronizasyon çağrıları), HttpClient
(senkronizasyon ve asenkron) performanslarını bulmak için hızlı bir performans testi yaptım . ve işte sonuçlar:
HttpClient
Tüm istekler için aynı örneği kullanma (min - maks)
WebClient senkronizasyonu: 8 ms - 167 ms
HttpClient senkronizasyonu: 3 ms - 7228 ms
HttpClient asenkronu: 985-10405 ms
HttpClient
Her istek için yeni bir tane kullanma (min - maks)
WebClient senkronizasyonu: 4 ms - 297 ms
HttpClient senkronizasyonu: 3 ms - 7953 ms
HttpClient asenkronu: 1027 - 10834 ms
kod
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);
}
}
}
Sorularım
- REST çağrıları kabul edilebilir 3-4s içinde döner. Ajax çağrılarından çağrılan denetleyici yöntemlerinde REST hizmetine çağrılar başlatılır. Başlangıç olarak, çağrılar farklı bir iş parçacığında çalışır ve kullanıcı arayüzünü engellemez. Peki, senkronizasyon çağrılarına sadık kalabilir miyim?
- Yukarıdaki kod yerel kutumda çalıştırıldı. Ürün kurulumunda DNS ve proxy araması yapılacaktır.
HttpClient
Üzerinden kullanmanın herhangi bir avantajı var mıWebClient
? HttpClient
Eşzamanlılık bundan daha mı iyiWebClient
? Test sonuçlarından görüyorumWebClient
senkronizasyon çağrılarının daha iyi performans gösterdiğini .- Will
HttpClient
biz .Net 4.5 yükseltme eğer daha iyi bir tasarım tercihi? Performans kilit tasarım faktörüdür.
GetDataFromHttpClientAsync
Testiniz haksızlıktır, çünkü önce çalışır, diğer çağrılar potansiyel olarak veri toplama (yerel makinede veya hedefinizle aranızdaki herhangi bir şeffaf proxy'de olsun) avantajından yararlanır ve daha hızlı olur. Ayrıca, doğru koşullar altındavar response = httpClient.GetAsync("http://localhost:9000/api/values/").Result;
vida dişi dişlerini yormanız nedeniyle bir kilitlenmeye neden olabilir. ThreadPool iş parçacıklarındaki iş parçacığı havuzuna bağlı bir etkinliği engellememelisiniz,await
bunun yerine iş parçacığını havuza geri döndürür.