Décider entre HttpClient et WebClient

notre application web tourne dans .net Framework 4.0. Les méthodes du contrôleur des appels de L'interface utilisateur via les appels ajax.

nous avons besoin de consommer le service de repos de notre vendeur. Je suis en train d'évaluer la meilleure façon d'appeler le service de repos à .Net 4.0. Le service REST nécessite un système 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 télécharger/télécharger d'énormes données et je ne vois rien à l'avenir. J'ai jeté un oeil à quelques code source ouvert projets pour la consommation de repos et n'a pas trouvé de valeur dans ceux 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 traiter des appels concurrents et qu'il peut réutiliser des DNS résolus, la configuration des cookies et l'authentification. Je suis encore à voir les valeurs pratiques que nous pouvons avoir, en raison des différences.

j'ai fait un test de performance rapide pour trouver comment WebClient (Appels sync), HttpClient (sync et async) effectuer. et voici les résultats:

utilisant la même instance HttpClient pour toutes les requêtes (min-max)

WebClient sync: 8 ms - 167 ms

HttpClient sync: 3 ms-7228 ms

HttpClient async: 985-10405 ms

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

WebClient sync: 4 ms-297 ms

HttpClient sync: 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:TempREST_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. Le RESTE des appels de retour dans 3-4s qui est acceptable. Les appels au REPOS le service est initié dans des méthodes de controller qui sont invoquées par les appels ajax. Pour commencer, les appels s'exécutent dans un fil différent et ne pas bloquer l'INTERFACE utilisateur. Je peux rester avec les appels sync?
  2. le code ci-dessus a été exécuté dans ma boîte locale. Dans la configuration prod, DNS et proxy la recherche sera impliquée. Y a-t-il un avantage à utiliser HttpClient plutôt que WebClient ?
  3. Est HttpClient la simultanéité de mieux que WebClient ? D'après les résultats des tests, je vois que les appels de synchronisation WebClient fonctionnent mieux.
  4. est-ce que HttpClient sera un meilleur choix de conception si nous passons à .Net 4.5? La Performance est le facteur clé de la conception.
162
demandé sur Cœur 2013-12-12 01:20:41

3 réponses

je vis dans les mondes F# et Web API.

il se passe beaucoup de bonnes choses 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 recommande l'utilisation de HttpClient pour tout travail futur . Peut-être y a-t-il un moyen de tirer parti des autres pièces de System.Net.Http sans utiliser directement cet assemblage, mais je ne peux pas imaginez comment cela pourrait fonctionner en ce moment.

en parlant de comparer ces deux

  • HttpClient est plus proche de HTTP que de WebClient.
  • HttpClient n'était pas censé être un remplacement complet d'un Client Web, car il y a des choses comme report progress, custom URI scheme et faire des appels FTP que WebClient fournit - mais HttpClient ne le fait pas.

enter image description here

si vous utilisez .NET 4.5, s'il vous plaît utilisez la bonté async avec HttpClient que Microsoft fournit aux développeurs. HttpClient est très symétrique aux frères du côté serveur du HTTP qui sont HttpRequest et HttpResponse.

mise à jour: 5 Raisons d'utiliser la nouvelle API HttpClient:

  • en-têtes fortement dactylographiés.
  • Caches partagées, cookies et lettres de créance
  • accès aux cookies et cookies partagés
  • contrôle de la mise en cache et du cache partagé.
  • injectez votre module de code dans le ASP.NET pipeline. Code plus propre et modulaire.

référence

C # 5.0 Joseph Albahari

(Channel 9 - Vidéo Build 2013)

Cinq Grands Raisons d'utiliser la nouvelle API HttpClient pour se connecter aux services Web

WebClient vs HttpClient vs HttpWebRequest

172
répondu Anant Dabhi 2016-10-11 09:29:09

HttpClient est le plus récent des API et il a les avantages de

  • a un bon modèle de programmation async
  • étant travaillé par Henrik F. Nielson qui est essentiellement l'un des inventeurs de HTTP, et il a conçu L'API de sorte qu'il est facile pour vous de suivre la norme HTTP, par exemple la production de headers conformes aux normes
  • est dans le cadre de .net 4.5, donc il a un certain niveau garanti de soutien pour le forseeable avenir
  • a aussi la version xcopyable/portable-framework de la bibliothèque Si vous voulez l'utiliser sur d'autres plateformes - .Net 4.0, Windows Phone etc.

si vous écrivez un service web qui fait des appels REST vers d'autres services web, vous devriez vouloir utiliser un modèle de programmation async pour tous vos appels REST, de sorte que vous ne touchez pas la famine de fil. Vous voulez probablement aussi utiliser le plus récent compilateur C# qui a le support async/wait.

Remarque: Il n'est pas plus performant autant que je sache. Il est probablement aussi performant si vous créez un test juste.

52
répondu Tim Lovell-Smith 2015-07-07 17:19:59

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 seulement alors que HttpClient est les deux.

j'ai fait un test de performance rapide pour trouver comment WebClient (Sync calls), HttpClient (Sync et Async) fonctionnent. et voici les résultats.

je vois cela comme une énorme différence en pensant pour l'avenir, c.-à-d. à long terme processus, GUI responsive, etc. (ajoutez à l'avantage que vous suggérez par le cadre 4.5 - qui dans mon expérience réelle est considérablement plus rapide sur IIS)

2
répondu Anthony Horne 2014-06-07 19:06:04