.Net Core使用HttpClient請求Web API注意事項

ZKEASOFT發表於2018-07-18

HttpClient

使用HttpClient可以很方便的請求Web API,但在使用時有一些需要注意的地方,不然會給你的程式帶來毀滅性的問題。

HttpClient是一個繼承了IDisposable介面的物件,所以在使用的時候,需要主動呼叫Dispose方法來釋放它。或者使用using

using(var client = new HttpClient())
{
    //do something with http client
}

  

這看起來似乎沒什麼問題。我們使用一些程式碼來測試一下它,我們將發起10個GET請求:

namespace ConsoleApplication
{
    public class Program
    {
        public static async Task Main(string[] args) 
        {
            Console.WriteLine("Starting connections");
            for(int i = 0; i<10; i++)
            {
                using(var client = new HttpClient())
                {
                    var result = await client.GetAsync("http://www.zkea.net");
                    Console.WriteLine(result.StatusCode);
                }
            }
            Console.WriteLine("Connections done");
        }
    }
}

  

輸出結果如下:

Starting connections
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
Connections done

  

看起來一切正常,但實際上並不是!我們使用netstat來檢視一下sockets的使用情況:

C:Userswayne>NETSTAT.EXE
...
  Proto  Local Address          Foreign Address        State
  TCP    10.211.55.6:12050      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12051      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12053      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12054      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12055      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12056      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12057      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12058      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12059      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12060      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12061      47.74.132.243:http  TIME_WAIT
  TCP    10.211.55.6:12062      47.74.132.243:http  TIME_WAIT
...

  

雖然應用程式已經退出,但是剛才發起的連線仍處於 TIME_WAIT 狀態。TIME_WAIT 狀態是指連線已經在一邊關閉,但仍在等待是否有其他資料包出現, 因為它們可能在網路上的某個地方被延遲,socket資源並沒有立即被回收。所以,如果你的程式(網站)的併發量很大,而每一次都例項化一個HttpClient物件,你的程式將會消耗掉伺服器上所有可用的socket資源,並導致程式出現異常,不可正常訪問。

正確使用HttpClient

HttpClient裡面的方法都是執行緒安全的:

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

  

所以你應當只例項化一個HttpClient物件,並且不需要去主動釋放它,它會在你程式退出的時候一起被釋放掉。

我們對程式做以下修改再測試一下:

namespace ConsoleApplication
{
    public class Program
    {
        private static HttpClient Client = new HttpClient();
        public static async Task Main(string[] args) 
        {
            Console.WriteLine("Starting connections");
            for(int i = 0; i<10; i++)
            {
                var result = await Client.GetAsync("http://aspnetmonsters.com");
                Console.WriteLine(result.StatusCode);
            }
            Console.WriteLine("Connections done");
            Console.ReadLine();
        }
    }
}

  

再看看socket使用情況,這下就一切正常了:

TCP    10.211.55.6:12254      47.74.132.243:http  ESTABLISHED

  

原文連結:http://www.zkea.net/codesnippet/detail/post-122.html

相關文章