使用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
裏面的方法都是線程安全的: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