IT story

HttpClient와 WebClient 사이에서 결정

hot-time 2020. 5. 9. 09:18
반응형

HttpClient와 WebClient 사이에서 결정


우리의 웹 앱은 .Net Framework 4.0에서 실행됩니다. UI는 아약스 호출을 통해 컨트롤러 메소드를 호출합니다.

공급 업체의 REST 서비스를 사용해야합니다. .Net 4.0에서 REST 서비스를 호출하는 가장 좋은 방법을 평가하고 있습니다. REST 서비스에는 기본 인증 체계가 필요하며 XML과 JSON으로 데이터를 리턴 할 수 있습니다. 대용량 데이터를 업로드 / 다운로드 할 필요가 없으며 앞으로는 아무것도 보이지 않습니다. REST 소비를위한 오픈 소스 코드 프로젝트를 몇 가지 살펴 보았고 프로젝트의 추가 종속성을 정당화 할 가치가 없었습니다. 평가하기 시작 WebClient하고 HttpClient. NuGet에서 .Net 4.0 용 HttpClient를 다운로드했습니다.

나는 차이를 검색 WebClient하고 HttpClient그리고 이 사이트는 그 하나의 HttpClient를 처리 할 수있는 동시 통화를 언급하며 DNS, 쿠키 설정 및 인증을 해결 재사용 할 수 있습니다. 차이로 인해 얻을 수있는 실질적인 가치를 아직 보지 못했습니다.

WebClient(동기 호출), HttpClient(동기 및 비동기) 수행 방법을 찾기 위해 빠른 성능 테스트를 수행했습니다. 결과는 다음과 같습니다.

HttpClient모든 요청에 동일한 인스턴스 사용 (최소-최대)

WebClient 동기화 : 8ms -167ms
HttpClient 동기화 : 3ms
-7228ms HttpClient 비동기 : 985-10405ms

HttpClient각 요청에 새로운 사용 (최소-최대)

WebClient 동기화 :
4ms-297ms HttpClient 동기화 : 3ms-7953ms
HttpClient 비동기 : 1027-10834ms

암호

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

My Questions

  1. The REST calls return in 3-4s which is acceptable. Calls to REST service are initiated in controller methods which gets invoked from ajax calls. To begin with, the calls run in a different thread and doesn't block UI. So, can I just stick with sync calls?
  2. The above code was run in my localbox. In prod setup, DNS and proxy lookup will be involved. Is there any advantage of using HttpClient over WebClient?
  3. Is HttpClient concurrency better than WebClient ? From the test results, I see WebClient sync calls perform better.
  4. Will HttpClient be a better design choice if we upgrade to .Net 4.5? Performance is the key design factor.

I live in both the F# and Web API worlds.

There's a lot of good stuff happening with Web API, especially in the form of message handlers for security, etc.

I know mine is only one opinion, but I would only recommend use of HttpClient for any future work. Perhaps there's some way to leverage some of the other pieces coming out of System.Net.Http without using that assembly directly, but I cannot imagine how that would work at this time.

Speak­ing of com­par­ing these two

  • Http­Client is more closer to HTTP than Web­Client.
  • Http­Client was not meant to be a com­plete replace­ment of Web Client, since there are things like report progress, cus­tom URI scheme and mak­ing FTP calls that Web­Client pro­vides — but Http­Client doesn’t.
+--------------------------------------------+--------------------------------------------+
|               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                |
+--------------------------------------------+--------------------------------------------+

If you’re using .NET 4.5, please do use the async good­ness with Http­Client that Microsoft pro­vides to the devel­op­ers. Http­Client is very sym­met­ri­cal to the server side brethren of the HTTP those are HttpRe­quest and HttpResponse.

Update: 5 Rea­sons to use new Http­Client API:

  • Strongly typed headers.
  • Shared Caches, cook­ies and credentials
  • Access to cook­ies and shared cookies
  • Con­trol over caching and shared cache.
  • Inject your code mod­ule into the ASP.NET pipeline. Cleaner and mod­u­lar code.

Ref­er­ence

C# 5.0 Joseph Albahari

(Channel9 — Video Build 2013)

Five Great Reasons to Use the New HttpClient API to Connect to Web Services

WebClient vs HttpClient vs HttpWebRequest


HttpClient is the newer of the APIs and it has the benefits of

  • has a good async programming model
  • being worked on by Henrik F Nielson who is basically one of the inventors of HTTP, and he designed the API so it is easy for you to follow the HTTP standard, e.g. generating standards-compliant headers
  • is in the .Net framework 4.5, so it has some guaranteed level of support for the forseeable future
  • also has the xcopyable/portable-framework version of the library if you want to use it on other platforms - .Net 4.0, Windows Phone etc.

If you are writing a web service which is making REST calls to other web services, you should want to be using an async programming model for all your REST calls, so that you don't hit thread starvation. You probably also want to use the newest C# compiler which has async/await support.

Note: It isn't more performant AFAIK. It's probably somewhat similarly performant if you create a fair test.


Firstly, I am not an authority on WebClient vs. HttpClient, specifically. Secondly, from your comments above, it seems to suggest that WebClient is Sync ONLY whereas HttpClient is both.

I did a quick performance test to find how WebClient (Sync calls), HttpClient (Sync and Async) perform. and here are the results.

I see that as a huge difference when thinking for future, i.e. long running processes, responsive GUI, etc. (add to the benefit you suggest by framework 4.5 - which in my actual experience is hugely faster on IIS)

참고URL : https://stackoverflow.com/questions/20530152/deciding-between-httpclient-and-webclient

반응형