HttpClient所引爆的Sockets Port耗盡問題

最近在跨單位合作某通訊軟體API時再度觸及到這個議題,擔心某同事會寫出爆掉的程式碼,因此寫了此篇文章真實的驗證以利日後查閱。

HttpClient不慎引發Sockets資源耗盡

從2015-2016年之間我在文章中一直呼籲,如果你不確定你的HttpClient將要怎麼的被使用,那就最好不要用!不要以為用using Statement就可以安全下樁,這反而是引爆你的Socket 65535個連接埠耗盡的關鍵點。原因就是因為IDisposable在實作關閉時,依照TCP協定的規定必須實作等候MSL(Maximum Segment Lifetime)時間延遲,以確保另一通訊端關閉連接,以至於形成TIME-WAIT,這就是爆掉的原因。

驗證程式碼如下,隨便開個ASPX把方法丟進去就知道效果。

protected void uBtn_Click(object sender, EventArgs e)
{
  uMsg.Text = "";
  for (int i = 0; i < 10; i++)
  { //這裡很自以為是地用了using嘍!
    using (var oHC = new System.Net.Http.HttpClient())
    {
      var oResult = oHC.GetAsync("https://api.myjson.com/bins/nx06k").GetAwaiter().GetResult();
      uMsg.Text += oResult.Content.ReadAsStringAsync().Result;
    }
  }
}

結果很簡單,用netstat看就知道效果,不多不少共10個TIME-WAIT,想想看當你的程式碼被執行一萬次會怎樣?

雖然微軟建議往HttpClient遷移,但是如果你懶得另行設計Singleton或Lazy(T)的話,我建議還是留在最完整與強大的HttpWebRequest尤佳。

相關參考:

System.Net.Http.HttpClient TIME_WAIT System.Net.HttpWebRequest TCP Sockets Ports