web-dev-qa-db-ja.com

HttpClientとWebClientの間の決定

当社のWebアプリは.Net Framework 4.0で動作しています。 UIはajax呼び出しを通してコントローラーメソッドを呼び出します。

ベンダーのRESTサービスを利用する必要があります。私は.NET 4.0でREST serviceを呼び出すための最良の方法を評価しています。 RESTサービスには基本認証方式が必要であり、XMLとJSONの両方でデータを返すことができます。巨大なデータをアップロード/ダウンロードする必要はありません。将来的には何も表示されません。私はREST消費のためのいくつかのオープンソースコードプロジェクトを調べましたが、プロジェクトに追加の依存関係を正当化するためにそれらの中に値を見つけることができませんでした。 WebClientおよびHttpClientの評価を開始しました。 NuGetからHttpClient for .Net 4.0をダウンロードしました。

私はWebClientHttpClientとの違いを探し、 このサイト 一つのHttpClientが同時呼び出しを扱え、解決されたDNS、cookie設定、そして認証を再利用できると述べました。違いによって私たちが得るかもしれない実用的な価値をまだ見ていません。

WebClient(同期呼び出し)、HttpClient(同期と非同期)のパフォーマンスを調べるために、簡単なパフォーマンステストを行いました。これが結果です。

すべての要求に同じHttpClientインスタンスを使用する(最小 - 最大)

Webクライアント同期:8 ms - 167 ms
HttpClient同期:3ミリ秒 - 7228ミリ秒
HttpClient非同期:985 - 10405 ms

リクエストごとに新しいHttpClientを使用する(最小 - 最大)

Webクライアント同期:4 ms - 297 ms
HttpClient同期:3 ms - 7953 ms
HttpClient非同期:1027 - 10834ミリ秒

コード

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);
        }
    }
}

私の質問

  1. REST呼び出しは3〜4秒で戻りますが、これは問題ありません。 RESTサービスへの呼び出しは、ajax呼び出しから呼び出されるコントローラーメソッドで開始されます。まず、呼び出しは別のスレッドで実行され、UIをブロックしません。それで、私はちょうど同期呼び出しに固執することができますか?
  2. 上記のコードは私のlocalboxで実行されました。製品セットアップでは、DNSとプロキシルックアップが関係します。 HttpClientよりWebClientを使用する利点はありますか?
  3. HttpClientの同時実行性はWebClientよりも優れていますか?テスト結果から、WebClient同期呼び出しのパフォーマンスが向上していることがわかります。
  4. .NET 4.5にアップグレードした場合、HttpClientはより良い設計上の選択になりますか?性能が重要な設計要素です。
190
user3092913

私はF#とWeb APIの両方の世界に住んでいます。

Web APIに関しては、特にセキュリティなどのためのメッセージハンドラの形で、たくさんの良いことが起こっています。

私の意見は1つの意見にすぎませんが、将来の作業にはHttpClientの使用をお勧めします。そのアセンブリを直接使わずにSystem.Net.Httpから出てくる他の部分を利用する方法があるかもしれませんが、現時点でそれがどのように機能するかは想像できません。

この二つを比較すると言えば

  • HttpClientはWebClientよりもHTTPに近いです。
  • レポートの進捗状況、カスタムURIスキーム、およびWebClientが提供するFTP呼び出しなどがあるため、HttpClientはWeb Clientの完全な代替品ではありません - しかし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                |
+--------------------------------------------+--------------------------------------------+

.NET 4.5を使用している場合は、Microsoftが開発者に提供しているHttpClientの非同期機能を使用してください。 HttpClientは、HTTPのサーバー側の兄弟HttpRequestとHttpResponseとは非常に対称的です。

更新日:新しいHttpClient APIを使用する5つの理由:

  • 強く型付けされたヘッダ.
  • 共有キャッシュ、Cookie、および資格情報
  • クッキーと共有クッキーへのアクセス
  • キャッシュと共有キャッシュを制御します。
  • コードモジュールをASP.NETパイプラインに挿入します。よりクリーンでモジュラーなコード.

参考文献

C#5.0ジョセフ・アルバハリ

(Channel 9 - Video Build 2013)

Webサービスに接続するために新しいHttpClient APIを使用する5つの大きな理由

WebClientとHttpClientとHttpWebRequest

197
Anant Dabhi

HttpClientは新しいAPIであり、以下の利点があります。

  • 良い非同期プログラミングモデルを持っている
  • 基本的にはHTTPの発明者の一人であるHenrik F Nielsonが取り組んでおり、彼はあなたがHTTP標準に従うのが簡単であるようにAPIを設計しました。規格準拠のヘッダを生成する
  • .NET Framework 4.5に含まれているので、それは予見可能な将来のためのサポートのいくつかの保証されたレベルを持っています
  • .NET 4.0、Windows Phoneなど、他のプラットフォームで使用する場合は、xcopyable/portable-frameworkバージョンのライブラリもあります。

他のWebサービスへのREST呼び出しを行うWebサービスを作成している場合は、すべてのREST呼び出しに非同期プログラミングモデルを使用することをお勧めします。スレッドの枯渇を打つ。また、非同期/待機サポートを備えた最新のC#コンパイラを使用することをお勧めします。

注:それはよりパフォーマンスの高いAFAIKではありません。あなたが公正なテストを作成するならば、それはおそらくいくぶん似たような性能を発揮します。

56

第一に、私はWebClientとHttpClientの関係についての権限ではありません。第二に、上のあなたのコメントから、それはHttpClientが両方であるのに対し、WebClientは同期のみであることを示唆しているようです。

WebClient(同期呼び出し)、HttpClient(同期および非同期)のパフォーマンスを調べるために、簡単なパフォーマンステストを行いました。これが結果です。

私は将来を考えているとき、すなわち長期実行プロセス、レスポンシブGUIなどと考えると大きな違いがあると思います。

3
Anthony Horne