Notre application Web s'exécute dans .Net Framework 4.0. L'interface utilisateur appelle les méthodes du contrôleur via des appels ajax.
Nous devons consommer le service REST de notre fournisseur. J'évalue la meilleure façon d'appeler le service REST dans .Net 4.0. Le service REST nécessite un schéma d'authentification de base et il peut renvoyer des données à la fois en XML et en JSON. Il n'y a aucune exigence pour le téléchargement / téléchargement de données énormes et je ne vois rien à l'avenir. J'ai examiné quelques projets de code open source pour la consommation REST et je n'ai trouvé aucune valeur dans ceux-ci pour justifier une dépendance supplémentaire dans le projet. Commencé à évaluer WebClient
et HttpClient
. J'ai téléchargé HttpClient pour .Net 4.0 à partir de NuGet.
J'ai cherché des différences entre WebClient
et HttpClient
et ce site a mentionné qu'un seul HttpClient peut gérer les appels simultanés et qu'il peut réutiliser le DNS résolu, la configuration des cookies et l'authentification. Je n'ai pas encore vu les valeurs pratiques que nous pourrions gagner en raison des différences.
J'ai fait un test de performance rapide pour trouver comment WebClient
(appels de synchronisation), HttpClient
(synchronisation et async) fonctionnent. et voici les résultats:
Utilisation de la même HttpClient
instance pour toutes les requêtes (min - max)
Synchronisation WebClient: 8 ms - 167 ms
Synchronisation HttpClient: 3 ms - 7228 ms
Async HttpClient: 985 - 10405 ms
Utiliser un nouveau HttpClient
pour chaque demande (min - max)
Synchronisation WebClient: 4 ms - 297 ms
Synchronisation HttpClient: 3 ms - 7953 ms
Async HttpClient: 1027 - 10834 ms
Code
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);
}
}
}
Mes questions
- Les appels REST reviennent en 3-4 secondes, ce qui est acceptable. Les appels au service REST sont lancés dans des méthodes de contrôleur qui sont appelées à partir d'appels ajax. Pour commencer, les appels s'exécutent dans un thread différent et ne bloquent pas l'interface utilisateur. Alors, puis-je rester avec les appels de synchronisation?
- Le code ci-dessus a été exécuté dans ma boîte locale. Dans la configuration de la prod, la recherche DNS et proxy sera impliquée. Y a-t-il un avantage à utiliser
HttpClient
plusWebClient
? - La
HttpClient
concurrence est-elle meilleure queWebClient
? D'après les résultats du test, je constate que lesWebClient
appels de synchronisation fonctionnent mieux. - Sera
HttpClient
un meilleur choix de conception si nous passons à .Net 4.5? La performance est le facteur clé de conception.
GetDataFromHttpClientAsync
car il s'exécute en premier, les autres invocations bénéficient potentiellement d'avoir des données cahed (que ce soit sur la machine locale ou tout proxy transparent entre vous et la destination) et seront plus rapides. De plus, dans les bonnes conditions,var response = httpClient.GetAsync("http://localhost:9000/api/values/").Result;
un blocage peut se produire car vous épuisez les threads de pool de threads. Vous ne devez jamais bloquer sur une activité qui dépend du pool de threads dans les threads ThreadPool, vous devez le faire à laawait
place pour qu'il renvoie le thread dans le pool.Réponses:
Je vis dans les mondes F # et Web API.
Il y a beaucoup de bonnes choses qui se passent avec l'API Web, en particulier sous la forme de gestionnaires de messages pour la sécurité, etc.
Je sais que la mienne n'est qu'une opinion, mais je ne recommanderais que son utilisation
HttpClient
pour tout travail futur . Peut-être existe-t-il un moyen de tirer parti de certaines des autres pièces qui sortentSystem.Net.Http
sans utiliser directement cet assemblage, mais je ne peux pas imaginer comment cela fonctionnerait pour le moment.En parlant de comparer ces deux
Si vous utilisez .NET 4.5, veuillez utiliser la qualité asynchrone avec HttpClient que Microsoft fournit aux développeurs. HttpClient est très symétrique par rapport aux frères côté serveur du HTTP, ce sont HttpRequest et HttpResponse.
Mise à jour: 5 raisons d'utiliser la nouvelle API HttpClient:
Référence
C # 5.0 Joseph Albahari
(Channel9 - Video Build 2013)
Cinq bonnes raisons d'utiliser la nouvelle API HttpClient pour se connecter aux services Web
WebClient vs HttpClient vs HttpWebRequest
la source
WebClient
Semble également avoir des méthodes asynchrones maintenant.WebClient
n'est pas disponible en.Net Core
mais l'HttpClient
est.HttpClient est la plus récente des API et présente les avantages de
Si vous écrivez un service Web qui effectue des appels REST vers d'autres services Web, vous devriez vouloir utiliser un modèle de programmation asynchrone pour tous vos appels REST, afin de ne pas frapper de faim. Vous souhaiterez probablement également utiliser le plus récent compilateur C # qui prend en charge async / attente.
Remarque: ce n'est pas un AFAIK plus performant. C'est probablement un peu plus performant si vous créez un test équitable.
la source
HttpClientFactory
Il est important d'évaluer les différentes manières de créer un HttpClient, et une partie de cela consiste à comprendre HttpClientFactory.
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
Ce n'est pas une réponse directe, je sais - mais il vaut mieux commencer ici que de se retrouver
new HttpClient(...)
partout.la source
Premièrement, je ne suis pas une autorité sur WebClient vs HttpClient, en particulier. Deuxièmement, d'après vos commentaires ci-dessus, il semble suggérer que WebClient est sync UNIQUEMENT alors que HttpClient est les deux.
Je vois cela comme une énorme différence lorsque l'on pense à l'avenir, c'est-à-dire des processus longs, une interface graphique réactive, etc. (ajouter à l'avantage que vous suggérez par le cadre 4.5 - qui, selon mon expérience réelle, est extrêmement plus rapide sur IIS)
la source
WebClient
semble avoir des capacités asynchrones dans les dernières versions de .NET. Je voudrais savoir pourquoi il semble surpasser HttpClient à une telle échelle.J'ai une référence entre HttpClient, WebClient, HttpWebResponse puis j'appelle Rest Web Api
et résultat Call Rest Web Api Benchmark
--------------------- Étape 1 ---- 10 Demande
{00: 00: 17.2232544} ====> HttpClinet
{00: 00: 04.3108986} ====> WebRequest
{00: 00: 04.5436889} ====> WebClient
--------------------- Étape 1 ---- Demande 10 - Petite taille
{00: 00: 17.2232544} ====> HttpClinet
{00: 00: 04.3108986} ====> WebRequest
{00: 00: 04.5436889} ====> WebClient
--------------------- Étape 3 ---- Demande de synchronisation 10 - Petite taille
{00: 00: 15.3047502} ====> HttpClinet
{00: 00: 03.5505249} ====> WebRequest
{00: 00: 04.0761359} ====> WebClient
--------------------- Étape 4 ---- Demande de synchronisation 100 - Petite taille
{00: 03: 23.6268086} ====> HttpClinet
{00: 00: 47.1406632} ====> WebRequest
{00: 01: 01.2319499} ====> WebClient
--------------------- Étape 5 ---- Demande de synchronisation 10 - Taille maximale
{00: 00: 58.1804677} ====> HttpClinet
{00: 00: 58.0710444} ====> WebRequest
{00: 00: 38.4170938} ====> WebClient
--------------------- Étape 6 ---- Demande de synchronisation 10 - Taille maximale
{00: 01: 04.9964278} ====> HttpClinet
{00: 00: 59.1429764} ====> WebRequest
{00: 00: 32.0584836} ====> WebClient
_____ WebClient est plus rapide ()
//-------------------------Les fonctions
la source
Vous pourriez peut-être penser le problème différemment.
WebClient
etHttpClient
sont essentiellement des implémentations différentes de la même chose. Ce que je recommande, c'est d'implémenter le modèle d'injection de dépendances avec un conteneur IoC dans toute votre application. Vous devez construire une interface client avec un niveau d'abstraction plus élevé que le transfert HTTP de bas niveau. Vous pouvez écrire des classes concrètes qui utilisent à la foisWebClient
etHttpClient
, puis utiliser le conteneur IoC pour injecter l'implémentation via config.Ce que cela vous permettrait de faire serait de basculer entre
HttpClient
etWebClient
facilement afin de pouvoir objectivement tester dans l'environnement de production.Donc des questions comme:
Peut effectivement être répondu objectivement en basculant entre les deux implémentations client à l'aide du conteneur IoC. Voici un exemple d'interface sur lequel vous pourriez compter et qui n'inclut aucun détail sur
HttpClient
ouWebClient
.Code complet
Implémentation de HttpClient
Vous pouvez utiliser
Task.Run
pour faireWebClient
fonctionner de manière asynchrone dans son implémentation.L'injection de dépendance, lorsqu'elle est bien faite, aide à atténuer le problème d'avoir à prendre des décisions de bas niveau dès le départ. En fin de compte, la seule façon de connaître la vraie réponse est d'essayer à la fois dans un environnement réel et de voir celle qui fonctionne le mieux. Il est tout à fait possible que
WebClient
cela fonctionne mieux pour certains clients etHttpClient
fonctionne mieux pour d'autres. C'est pourquoi l'abstraction est importante. Cela signifie que le code peut être rapidement échangé ou modifié avec la configuration sans changer la conception fondamentale de l'application.la source
Opinion impopulaire de 2020:
Quand il vient aux applications ASP.NET je préfère encore
WebClient
plusHttpClient
parce que:la source