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

HttpClient

使用HttpClient能夠很方便的請求Web API,但在使用時有一些須要注意的地方,否則會給你的程序帶來毀滅性的問題。html

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:\Users\wayne>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資源,並致使程序出現異常,不可正常訪問。socket

正確使用HttpClient

HttpClient裏面的方法都是線程安全的:async

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

因此你應當只實例化一個HttpClient對象,而且不須要去主動釋放它,它會在你程序退出的時候一塊兒被釋放掉。post

咱們對程序作如下修改再測試一下:測試

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/codesnipp...

相關文章
相關標籤/搜索