web-dev-qa-db-ger.com

Entscheidung zwischen HttpClient und WebClient

Unsere Web-App läuft in .Net Framework 4.0. Die Benutzeroberfläche ruft Controller-Methoden über Ajax-Aufrufe auf.

Wir müssen REST Service von unserem Lieferanten in Anspruch nehmen. Ich bewerte die beste Möglichkeit, REST Service in .Net 4.0 aufzurufen. Die REST erfordert das Standardauthentifizierungsschema und kann Daten sowohl in XML als auch in JSON zurückgeben. Es ist nicht erforderlich, große Datenmengen hoch- oder herunterzuladen, und ich sehe in Zukunft nichts. Ich habe mir einige Open-Source-Code-Projekte angesehen für REST Verbrauch und fand keinen Wert in denen, um zusätzliche Abhängigkeit im Projekt zu rechtfertigen. Begann WebClient und HttpClient auszuwerten. Ich lud HttpClient für .Net 4.0 von NuGet.

Ich habe nach Unterschieden zwischen WebClient und HttpClient und diese Seite gesucht und erwähnt, dass ein einzelner HttpClient gleichzeitige Aufrufe verarbeiten kann und aufgelöste DNS-, Cookie-Konfiguration und Authentifizierung wiederverwenden kann. Ich sehe noch keine praktischen Werte, die wir aufgrund der Unterschiede gewinnen könnten.

Ich habe einen schnellen Leistungstest durchgeführt, um herauszufinden, wie WebClient (Synchronisierungsaufrufe), HttpClient (Synchronisierung und Asynchronisierung) ausgeführt werden. und hier sind die Ergebnisse:

Verwenden derselben HttpClient -Instanz für alle Anforderungen (min - max)

WebClient-Synchronisierung: 8 ms - 167 ms
HTTP-Client-Synchronisierung: 3 ms - 7228 ms
HttpClient async: 985 - 10405 ms

Verwenden eines neuen HttpClient für jede Anfrage (min - max)

WebClient-Synchronisierung: 4 ms - 297 ms
HTTP-Client-Synchronisierung: 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);
        }
    }
}

Meine Fragen

  1. Die Aufrufe von REST kehren in 3-4s zurück, was akzeptabel ist. Aufrufe von REST Service werden in Controller-Methoden initiiert, die von Ajax-Aufrufen aufgerufen werden. Die Aufrufe werden in einem anderen Thread ausgeführt und blockieren die Benutzeroberfläche nicht. Kann ich mich also einfach an die Synchronisierungsaufrufe halten?
  2. Der obige Code wurde in meiner localbox ausgeführt. Bei der Einrichtung der Produkte wird die DNS- und Proxy-Suche durchgeführt. Gibt es einen Vorteil bei der Verwendung von HttpClient gegenüber WebClient?
  3. Ist die Nebenläufigkeit von HttpClient besser als die von WebClient? Aus den Testergebnissen geht hervor, dass die Synchronisierungsaufrufe von WebClient eine bessere Leistung erbringen.
  4. Wird HttpClient eine bessere Wahl für das Design sein, wenn wir ein Upgrade auf .Net 4.5 durchführen? Leistung ist der entscheidende Designfaktor.
197
user3092913

Ich lebe sowohl in der F # - als auch in der Web-API-Welt.

Mit der Web-API passiert eine Menge Gutes, insbesondere in Form von Message-Handlern für die Sicherheit usw.

Ich weiß, meine Meinung ist nur eine, aber Ich würde die Verwendung von HttpClient nur für zukünftige Arbeiten empfehlen . Vielleicht gibt es eine Möglichkeit, einige der anderen Teile, die aus System.Net.Http ohne diese Assembly direkt zu verwenden, aber ich kann mir nicht vorstellen, wie das zu diesem Zeitpunkt funktionieren würde.

Apropos Vergleich dieser beiden

  • HttpClient ist HTTP näher als WebClient.
  • HttpClient war nicht als vollständiger Ersatz für Web Client gedacht, da es vom WebClient bereitgestellte Dinge wie den Berichtsfortschritt, ein benutzerdefiniertes URI-Schema und das Tätigen von FTP-Aufrufen gibt, HttpClient jedoch nicht.
+--------------------------------------------+--------------------------------------------+
|               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                |
+--------------------------------------------+--------------------------------------------+

Wenn Sie .NET 4.5 verwenden, verwenden Sie die asynchrone Funktion von HttpClient, die Microsoft den Entwicklern bereitstellt. HttpClient ist sehr symmetrisch zu den Server-Brüdern des HTTP, das sind HttpRequest und HttpResponse.

Update: 5 Gründe für die Verwendung der neuen HttpClient-API:

  • Stark typisierte Überschriften.
  • Freigegebene Caches, Cookies und Anmeldeinformationen
  • Zugriff auf Cookies und freigegebene Cookies
  • Kontrolle über Caching und Shared Cache.
  • Injizieren Sie Ihr Codemodul in die ASP.NET-Pipeline. Sauberer und modularer Code.

Referenz

C # 5.0 Joseph Albahari

(Channel9 - Video Build 2013)

Fünf gute Gründe, die neue HttpClient-API für die Verbindung zu Webdiensten zu verwenden

WebClient vs HttpClient vs HttpWebRequest

204
Anant Dabhi

HttpClient ist die neuere der APIs und bietet die Vorteile von

  • hat ein gutes asynchrones Programmiermodell
  • henrik F. Nielson, der im Grunde genommen einer der Erfinder von HTTP ist, hat die API so entworfen, dass Sie leicht dem HTTP-Standard folgen können, z. Generieren von standardkonformen Headern
  • befindet sich im .Net-Framework 4.5, sodass für die absehbare Zukunft ein gewisses Maß an Support garantiert ist
  • hat auch die xcopyable/portable-framework-Version der Bibliothek, wenn Sie sie auf anderen Plattformen verwenden möchten - .Net 4.0, Windows Phone usw.

Wenn Sie einen Webdienst schreiben, der REST Aufrufe an andere Webdienste ausführt, sollten Sie für alle Ihre REST Aufrufe ein asynchrones Programmiermodell verwenden Sie möchten wahrscheinlich auch den neuesten C # -Compiler verwenden, der async/await-Unterstützung bietet.

Hinweis: Es ist nicht performanter AFAIK. Es ist wahrscheinlich etwas ähnlich performant, wenn Sie einen fairen Test erstellen.

56

Erstens bin ich keine Autorität für WebClient vs. HttpClient. Zweitens deuten Ihre obigen Kommentare darauf hin, dass WebClient NUR synchronisiert ist, während HttpClient beides ist.

Ich habe einen kurzen Leistungstest durchgeführt, um herauszufinden, wie die Leistung von WebClient (Synchronisierungsaufrufe), HttpClient (Synchronisierung und Asynchronisierung) ist. und hier sind die Ergebnisse.

Ich sehe das als einen großen Unterschied, wenn ich an die Zukunft denke, d. H. An lang laufende Prozesse, ansprechende Benutzeroberfläche usw.

3
Anthony Horne