Aplikasi web kami berjalan di .Net Framework 4.0. UI memanggil metode pengontrol melalui panggilan ajax.
Kita perlu mengkonsumsi layanan REST dari vendor kami. Saya mengevaluasi cara terbaik untuk memanggil layanan REST di .Net 4.0. Layanan REST memerlukan Skema Otentikasi Dasar dan dapat mengembalikan data dalam XML dan JSON. Tidak ada persyaratan untuk mengunggah / mengunduh data besar dan saya tidak melihat apa pun di masa depan. Saya melihat beberapa proyek kode sumber terbuka untuk konsumsi REST dan tidak menemukan nilai pada mereka untuk membenarkan ketergantungan tambahan dalam proyek. Mulai mengevaluasi WebClient
dan HttpClient
. Saya mengunduh HttpClient untuk .Net 4.0 dari NuGet.
Saya mencari perbedaan antara WebClient
dan HttpClient
dan situs ini menyebutkan bahwa HttpClient tunggal dapat menangani panggilan bersamaan dan dapat menggunakan kembali DNS, konfigurasi cookie, dan otentikasi yang diselesaikan. Saya belum melihat nilai-nilai praktis yang dapat kita peroleh karena perbedaan.
Saya melakukan tes kinerja cepat untuk mengetahui kinerja WebClient
(sinkronisasi panggilan), HttpClient
(sinkronisasi dan asinkron). dan inilah hasilnya:
Menggunakan HttpClient
contoh yang sama untuk semua permintaan (minimal maks)
Sinkronisasi WebClient: 8 ms - 167 ms
HttpSinkronisasi klien: 3 ms - 7228 ms
HttpClient async: 985 - 10405 ms
Menggunakan yang baru HttpClient
untuk setiap permintaan (minimum)
Sinkronisasi WebClient: 4 ms - 297 ms
HttpSinkronisasi klien: 3 ms - 7953 ms
HttpClient async: 1027 - 10834 ms
Kode
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);
}
}
}
Pertanyaan saya
- Panggilan REST kembali dalam 3-4 yang dapat diterima. Panggilan ke layanan REST dimulai dengan metode pengontrol yang dipanggil dari panggilan ajax. Untuk mulai dengan, panggilan berjalan di utas yang berbeda dan tidak memblokir UI. Jadi, bisakah saya tetap dengan panggilan sinkronisasi?
- Kode di atas dijalankan di kotak lokal saya. Dalam pengaturan prod, DNS dan pencarian proxy akan terlibat. Apakah ada keuntungan menggunakan
HttpClient
lebihWebClient
? - Apakah
HttpClient
konkurensi lebih baik daripadaWebClient
? Dari hasil pengujian, saya melihatWebClient
panggilan sinkronisasi berkinerja lebih baik. - Akankah
HttpClient
menjadi pilihan desain yang lebih baik jika kita meningkatkan ke .Net 4.5? Kinerja adalah faktor desain utama.
GetDataFromHttpClientAsync
karena berjalan terlebih dahulu, pemanggilan lainnya mendapatkan manfaat dari berpotensi memiliki data cahed (baik itu di mesin lokal atau proxy transparan antara Anda dan tujuan) dan akan lebih cepat. Selain itu, dalam kondisi yang tepatvar response = httpClient.GetAsync("http://localhost:9000/api/values/").Result;
dapat menyebabkan kebuntuan karena Anda melelahkan ulir threadpool. Anda seharusnya tidak pernah memblokir aktivitas yang bergantung pada kumpulan utas di utas ThreadPool, Anda harus memblokirnyaawait
sehingga mengembalikan utas kembali ke kumpulan.Jawaban:
Saya tinggal di dunia F # dan Web API.
Ada banyak hal baik terjadi dengan Web API, terutama dalam bentuk penangan pesan untuk keamanan, dll.
Saya tahu pendapat saya hanya satu pendapat, tetapi saya hanya akan merekomendasikan penggunaan
HttpClient
untuk setiap pekerjaan di masa depan . Mungkin ada beberapa cara untuk memanfaatkan beberapa karya lain yang keluarSystem.Net.Http
tanpa menggunakan perakitan itu secara langsung, tetapi saya tidak bisa membayangkan bagaimana itu akan bekerja pada saat ini.Berbicara tentang membandingkan keduanya
Jika Anda menggunakan .NET 4.5, silakan gunakan async goodness dengan HttpClient yang disediakan Microsoft untuk pengembang. HttpClient sangat simetris dengan sisi server, saudara-saudara dari HTTP yaitu HttpRequest dan HttpResponse.
Pembaruan: 5 Alasan untuk menggunakan HttpClient API baru:
Referensi
C # 5.0 Joseph Albahari
(Channel9 - Video Build 2013)
Lima Alasan Besar untuk Menggunakan API HttpClient Baru untuk Menyambungkan ke Layanan Web
WebClient vs HttpClient vs HttpWebRequest
sumber
WebClient
Tampaknya juga memiliki metode async sekarang.WebClient
tidak tersedia di.Net Core
tetapiHttpClient
.HttpClient adalah yang terbaru dari API dan memiliki manfaat
Jika Anda menulis layanan web yang membuat panggilan REST ke layanan web lain, Anda harus menggunakan model pemrograman async untuk semua panggilan REST Anda, sehingga Anda tidak mengalami kekosongan utas. Anda mungkin juga ingin menggunakan kompiler C # terbaru yang memiliki dukungan async / menunggu.
Catatan: Ini bukan AFAIK lebih banyak pemain. Ini mungkin agak berkinerja sama jika Anda membuat tes yang adil.
sumber
Pertama, saya bukan otoritas di WebClient vs HttpClient, khususnya. Kedua, dari komentar Anda di atas, tampaknya menyarankan bahwa WebClient adalah HANYA Sinkronisasi sedangkan HttpClient keduanya.
Saya melihat itu sebagai perbedaan besar ketika memikirkan masa depan, yaitu proses yang berjalan lama, GUI responsif, dll. (Menambah manfaat yang Anda sarankan oleh kerangka 4.5 - yang dalam pengalaman saya yang sebenarnya jauh lebih cepat pada IIS)
sumber
WebClient
tampaknya memiliki kemampuan async dalam versi .NET terbaru. Saya ingin tahu mengapa tampaknya mengungguli HttpClient pada skala besar.HttpClientFactory
Sangat penting untuk mengevaluasi berbagai cara Anda dapat membuat HttpClient, dan bagian dari itu adalah memahami HttpClientFactory.
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
Ini bukan jawaban langsung yang saya tahu - tetapi Anda lebih baik memulai di sini daripada berakhir di
new HttpClient(...)
mana - mana.sumber
Saya memiliki patokan antara HttpClient, WebClient, HttpWebResponse lalu panggil Rest Web Api
dan hasil Tolak Tolok Ukur Api Web Rest
--------------------- Tahap 1 ---- 10 Permintaan
{00: 00: 17.2232544} ====> HttpClinet
{00: 00: 04.3108986} ====> WebRequest
{00: 00: 04.5436889} ====> WebClient
--------------------- Tahap 1 ---- 10 Permintaan - Ukuran Kecil
{00: 00: 17.2232544} ====> HttpClinet
{00: 00: 04.3108986} ====> WebRequest
{00: 00: 04.5436889} ====> WebClient
--------------------- Tahap 3 ---- 10 Permintaan sinkronisasi - Ukuran Kecil
{00:00: 15.3047502} ====> HttpClinet
{00: 00: 03.5505249} ====> WebRequest
{00: 00: 04.0761359} ====> WebClient
--------------------- Tahap 4 ---- Permintaan 100 sinkronisasi - Ukuran Kecil
{00: 03: 23.6268086} ====> HttpClinet
{00: 00: 47.1406632} ====> WebRequest
{00: 01: 01.2319499} ====> WebClient
--------------------- Tahap 5 ---- 10 Permintaan sinkronisasi - Ukuran Maks
{00: 00: 58.1804677} ====> HttpClinet
{00: 00: 58.0710444} ====> WebRequest
{00: 00: 38.4170938} ====> WebClient
--------------------- Tahap 6 ---- 10 Permintaan sinkronisasi - Ukuran Maks
{00: 01: 04.9964278} ====> HttpClinet
{00: 00: 59.1429764} ====> WebRequest
{00: 00: 32.0584836} ====> WebClient
_____ WebClient Lebih cepat ()
// ------------------------- Fungsi
sumber
Mungkin Anda bisa memikirkan masalah dengan cara yang berbeda.
WebClient
danHttpClient
implementasi pada dasarnya berbeda dari hal yang sama. Apa yang saya sarankan adalah menerapkan pola Injeksi Ketergantungan dengan Kontainer IoC di seluruh aplikasi Anda. Anda harus membangun antarmuka klien dengan tingkat abstraksi yang lebih tinggi daripada transfer HTTP tingkat rendah. Anda bisa menulis kelas konkret yang menggunakan keduanyaWebClient
danHttpClient
, dan kemudian menggunakan wadah IoC untuk menyuntikkan implementasi melalui konfigurasi.Apa yang memungkinkan Anda lakukan adalah beralih di antara
HttpClient
danWebClient
dengan mudah sehingga Anda dapat menguji secara objektif di lingkungan produksi.Jadi pertanyaan seperti:
Sebenarnya dapat dijawab secara objektif dengan beralih di antara dua implementasi klien menggunakan wadah IoC. Berikut adalah contoh antarmuka yang mungkin Anda andalkan yang tidak menyertakan detail tentang
HttpClient
atauWebClient
.Kode lengkap
Implementasi HttpClient
Anda dapat menggunakan
Task.Run
untukWebClient
menjalankan asinkron dalam implementasinya.Ketergantungan Injeksi, ketika dilakukan dengan baik membantu meringankan masalah karena harus membuat keputusan tingkat rendah di muka. Pada akhirnya, satu-satunya cara untuk mengetahui jawaban yang benar adalah mencoba keduanya dalam lingkungan hidup dan melihat mana yang paling baik. Sangat
WebClient
mungkin untuk bekerja lebih baik untuk beberapa pelanggan, danHttpClient
mungkin bekerja lebih baik untuk orang lain. Inilah sebabnya mengapa abstraksi itu penting. Ini berarti kode dapat dengan cepat ditukar, atau diubah dengan konfigurasi tanpa mengubah desain dasar aplikasi.sumber
Pendapat tidak populer dari tahun 2020:
Ketika datang ke ASP.NET aplikasi saya masih lebih suka
WebClient
lebihHttpClient
karena:sumber