web-dev-qa-db-fra.com

Choisir entre HttpClient et WebClient

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 utiliser 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 peut renvoyer des données à la fois en XML et en JSON. Il n'y a aucune obligation de télécharger/télécharger des données volumineuses et je ne vois rien à l'avenir. J'ai jeté un coup d'œil à quelques projets de code source ouvert pour la consommation REST et je n'ai trouvé aucune valeur dans ces projets pour justifier une dépendance supplémentaire dans le projet. Commencé à évaluer WebClient et HttpClient. J'ai téléchargé HttpClient for .Net 4.0 de NuGet.

J'ai cherché des différences entre WebClient et HttpClient et ce site a mentionné qu'un seul HttpClient peut gérer des appels simultanés et qu'il peut réutiliser le DNS résolu, la configuration des cookies et l'authentification. Il me reste encore à voir les valeurs pratiques que nous pourrions acquérir en raison des différences.

J'ai fait un test de performance rapide pour déterminer le comportement de WebClient (appels de synchronisation), HttpClient (synchro et asynchrone). et voici les résultats:

Utilisation de la même instance HttpClient pour toutes les demandes (min - max)

Synchronisation WebClient: 8 ms - 167 ms
Synchronisation HttpClient: 3 ms - 7228 ms
HttpClient async: 985 - 10405 ms

Utiliser un nouveau HttpClient pour chaque requête (min - max)

Synchronisation WebClient: 4 ms - 297 ms
Synchronisation HttpClient: 3 ms - 7953 ms
HttpClient async: 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

  1. Les appels REST retournent en 3-4, ce qui est acceptable. Les appels au service REST sont initiés dans les méthodes du contrôleur qui sont appelées à partir d'appels ajax. Pour commencer, les appels sont exécutés dans un autre thread et ne bloquent pas l'interface utilisateur. Alors, puis-je juste rester avec les appels de synchronisation?
  2. Le code ci-dessus a été exécuté dans ma boîte locale. Dans la configuration de prod, la recherche de DNS et de proxy sera impliquée. Y a-t-il un avantage à utiliser HttpClient par rapport à WebClient?
  3. La concurrence de HttpClient est-elle meilleure que celle de WebClient? D'après les résultats du test, je constate que WebClient les appels de synchronisation fonctionnent mieux.
  4. HttpClient constituera-t-il un meilleur choix de conception si nous passons à .Net 4.5? La performance est le facteur clé de la conception.
197
user3092913

Je vis dans les mondes F # et Web API.

Il y a beaucoup de bonnes choses avec les API Web, en particulier sous la forme de gestionnaires de messages pour la sécurité, etc.

Je sais que le mien n’est qu’un seul avis, mais , je ne recommanderais que l’utilisation de HttpClient pour tout travail futur . Peut-être y a-t-il moyen de tirer parti de certains des autres éléments issus de _System.Net.Http_ sans utiliser directement cette assemblée, mais je ne peux pas imaginer comment cela fonctionnerait à l'heure actuelle.

En parlant de comparer ces deux

  • HttpClient est plus proche de HTTP que WebClient.
  • HttpClient n'était pas censé remplacer complètement Web Client, car il existe des éléments tels que la progression des rapports, le schéma d'URI personnalisé et les appels FTP fournis par WebClient, à la différence de HttpClient.
_+--------------------------------------------+--------------------------------------------+
|               WebClient                    |               HttpClient                   |
+--------------------------------------------+--------------------------------------------+
| Available in older versions of .NET        | .NET 4.5 only.  Created to support the     |
|                                            | growing need of the Web API REST calls     |
+--------------------------------------------+--------------------------------------------+
| WinRT applications cannot use WebClient    | HTTPClient can be used with WinRT          |
+--------------------------------------------+--------------------------------------------+
| Provides progress reporting for downloads  | No progress reporting for downloads        |
+--------------------------------------------+--------------------------------------------+
| Does not reuse resolved DNS,               | Can reuse resolved DNS, cookie             |
| configured cookies                         | configuration and other authentication     |
+--------------------------------------------+--------------------------------------------+
| You need to new up a WebClient to          | Single HttpClient can make concurrent      |
| make concurrent requests.                  | requests                                   |
+--------------------------------------------+--------------------------------------------+
| Thin layer over WebRequest and             | Thin layer of HttpWebRequest and           |
| WebResponse                                | HttpWebResponse                            |
+--------------------------------------------+--------------------------------------------+
| Mocking and testing WebClient is difficult | Mocking and testing HttpClient is easy     |
+--------------------------------------------+--------------------------------------------+
| Supports FTP                               | No support for FTP                         |
+--------------------------------------------+--------------------------------------------+
| Both Synchronous and Asynchronous methods  | All IO bound methods in                    |
| are available for IO bound requests        | HTTPClient are asynchronous                |
+--------------------------------------------+--------------------------------------------+
_

Si vous utilisez .NET 4.5, veuillez utiliser la qualité async avec HttpClient fournie par Microsoft aux développeurs. HttpClient est très symétrique par rapport aux frères côté serveur de HTTP, à savoir HttpRequest et HttpResponse.

Mise à jour: 5 raisons d'utiliser la nouvelle API HttpClient:

  • En-têtes fortement typés.
  • Caches, cookies et identifiants partagés
  • Accès aux cookies et aux cookies partagés
  • Contrôle de la mise en cache et du cache partagé.
  • Injectez votre module de code dans le pipeline ASP.NET. Code plus propre et modulaire.

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

204
Anant Dabhi

HttpClient est la plus récente des API et présente les avantages suivants:

  • a un bon modèle de programmation asynchrone
  • henrik F Nielson, l’un des inventeurs du protocole HTTP, a travaillé sur ce projet et a conçu l’API pour qu’il soit facile de suivre le standard HTTP, par exemple. générer des en-têtes conformes aux normes
  • est dans le .NET Framework 4.5, donc il a un certain niveau de support garanti pour le futur prévisible
  • possède également la version xcopyable/portable-framework de la bibliothèque si vous souhaitez l’utiliser sur d’autres plateformes - .Net 4.0, Windows Phone, etc.

Si vous écrivez un service Web qui appelle REST vers d'autres services Web, vous devriez utiliser un modèle de programmation asynchrone pour tous vos appels REST, afin de ne pas t frappé la famine de fil. Vous voudrez probablement aussi utiliser le dernier compilateur C # qui prend en charge async/wait.

Remarque: il n'est pas plus performant que je sache. C'est probablement un peu pareil si vous créez un test équitable.

56
Tim Lovell-Smith

Tout d'abord, 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.

J'ai effectué un test de performance rapide pour déterminer le comportement de WebClient (appels Sync), HttpClient (Sync et Async). et voici les résultats.

Je vois cela comme une énorme différence lorsque je pense à l’avenir, c’est-à-dire des processus longs, une interface utilisateur graphique réactive, etc.

3
Anthony Horne