256 votes

Besoin d'aide pour décider entre HttpClient et WebClient

Notre application web est en cours d'exécution .Net Framework 4.0. L'INTERFACE utilisateur des appels de méthodes de contrôleur à travers des appels ajax.

Nous avons besoin de consommer de REPOS, service de notre fournisseur. Je suis évaluer la meilleure façon de faire des appels de service REST en .Net 4.0. Le RESTE du service nécessite l'Authentification de Base Régime et il peut renvoyer des données en XML et JSON. Il n'est pas nécessaire pour le téléchargement/téléchargement de données énorme et je ne vois rien dans l'avenir. J'ai pris un coup d'oeil à l'open source, les projets de code pour le REPOS de la consommation et de ne pas trouver une valeur dans ceux de justifier de nouvelles dépendance dans le projet. De commencer à évaluer WebClient et HttpClient. J'ai téléchargé HttpClient .Net 4.0 à partir de NuGet.

J'ai cherché pendant des différences entre WebClient et HttpClient et ce site mentionné que seul HttpClient peut gérer les appels simultanés et il peut réutiliser résolu DNS, témoin de config et d'authentification. Je suis encore à voir les valeurs pratiques que nous pouvons avoir, en raison des différences.

J'ai fait un rapide test de performance de trouver comment WebClient (synchronisation des appels), HttpClient (synchronisation et asynchrone) effectuer. et voici les résultats:

En utilisant le même HttpClient exemple pour toutes les demandes (min - max)

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

À l'aide d'un nouveau HttpClient pour chaque demande (min - max)

WebClient sync: 4 ms - ms 297
HttpClient sync: 3 ms - ms 7953
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. Le RESTE des appels de retour dans 3-4s qui est acceptable. Les appels au REPOS service sont initiées dans les méthodes du controller qui est appelé à partir de les appels ajax. Pour commencer, les appels exécuter dans un thread différent et ne pas bloquer l'INTERFACE utilisateur. Donc, puis-je simplement s'en tenir à la synchronisation des appels?
  2. Le code ci-dessus a été exécuté dans mon localbox. En prod, d'installation, de DNS et proxy de recherche seront impliqués. Est-il un avantage de l'utilisation de HttpClient sur WebClient?
  3. Est - HttpClient de la simultanéité de mieux que de WebClient ? Des résultats du test, je vois WebClient de la synchronisation des appels de mieux performer.
  4. Va HttpClient être un meilleur choix de conception si nous avons de mise à niveau .Net 4.5? La Performance est la clé de la conception de facteur.

85voto

Tim Lovell-Smith Points 2635

HttpClient est la plus récente de l'Api et il a les avantages de la

  • a un bon modèle de programmation asynchrone
  • en train de travailler sur Henrik F Nielson, qui est en fait l'un des inventeurs de HTTP, de sorte que le rend facile de suivre le protocole HTTP
  • est dans la .Net framework 4.5, il a un certain niveau de soutien garanti pour un futur proche
  • a un xcopyable/versions portables .Net 4.0, Windows Phone etc.

Si vous êtes à la rédaction d'un service web qui vise à rendre le RESTE des appels à d'autres services web, vous devriez vous voulez à l'aide d'un modèle de programmation asynchrone pour tous vos appels de REPOS, de sorte que vous n'avez pas touché de threads. Vous avez sans doute aussi souhaitez utiliser le nouveau compilateur C# qui a async/await soutien.

Remarque: Il n'est pas plus performant autant que je sache. C'est sans doute un peu de la même façon performante si vous créez un test juste.

6voto

Anthony Horne Points 1165

Tout d'abord, je ne suis pas une autorité sur WebClient vs HttpClient, en particulier. Deuxièmement, à partir de votre commentaires ci-dessus, il semble suggérer que WebClient est Synchro alors que HttpClient est à la fois.

J'ai fait un rapide test de performance de trouver comment WebClient (Synchronisation des appels), HttpClient (Synchronisation et Asynchrone) effectuer. et voici les résultats.

Je vois que comme une énorme différence lorsque l'on pense pour l'avenir, c'est à dire long processus en cours d'exécution, sensible GUI, etc. (en complément de la prestation que vous suggérons par le framework 4.5 - qui, dans mon expérience réelle est extrêmement plus rapide sur IIS)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X