.netCore HttpClient正確用法


.netCore HttpClient正確用法

        HttpClient 這個組件從.net framework延續到.net Core,在使用時稍微不注意,將引發性能問題。實際上文檔已提及HttpClient 用於在應用程序的整個生存期內實例化一次並重復使用。

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads.This will result in SocketException errors.

讓我們再來驗證下,我們使用HttpClient請求這個網站https://www.yicai.com 首頁20次。

image

當某個同學是這么用的


public static async Task Main(string[] args)
{
     Console.WriteLine("Starting connections");
     for (int i = 0; i < 20; i++)
     {
         await RequestByUsing();
     }
     Console.WriteLine("Connections done");
     Console.ReadLine();
}

private static async Task RequestByUsing()
{
     using (var client = new HttpClient())
     {
         var result = await client.GetAsync(TEST_URL);
         Console.WriteLine(result.StatusCode);
     }
}


運行測試程序

dotnet run --project ./HttpclientTestapp/HttpclientTestapp.csproj


image

下載TCPViewer, 也可以使用NETSTAT,程序進程還在運行中,但還是 TCP TIME_WAIT這么多個 Remote Address 與之前我們PING是類似的,我們等待1分鍾還釋放。

實際影響生產環境性能。

image

什么是TIME_WAIT, 請回顧TCP的狀態圖, 圖來自https://www4.cs.fau.de/Projects/JX/Projects/TCP/tcpstate.html

image

TCP Connection Termination Procedure(TCP連接終止過程)

image

它們處於TIME_WAIT狀態,這意味着連接已在一端(我們的)關閉,但我們仍在等待是否有任何額外的數據包進入,因為它們可能已在網絡上的某個地方延遲。我們不可以停止程序。
當我們的代碼修改為

/// <summary>
/// static_client
/// </summary>
private static readonly HttpClient static_client = new HttpClient();
/// <summary>
/// TEST_URL
/// </summary>
private static readonly string TEST_URL = "https://www.yicai.com";

/// <summary>
/// HttpClient test main
/// </summary>
/// <see cref="https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.httpclient?view=netcore-2.2"/>
/// <param name="args">args</param>
/// <returns></returns>
public static async Task Main(string[] args)
{
     Console.WriteLine("Starting connections");
     for (int i = 0; i < 20; i++)
     {
         await StaticClientWay();
     }
     Console.WriteLine("Connections done");
     Console.ReadLine();
}

private static async Task StaticClientWay()
{
     var result = await static_client.GetAsync(TEST_URL);
     Console.WriteLine(result.StatusCode);
}

再次監控TCP請求,已沒有TIME_WAIT,只有Established,由於此域名解析IP變化

image

完整Testing代碼

目前微服務的時代,我們系統中服務之間相互通訊,還是有HTTP方式。當socket達到4000時,在峰值時將超過 5000 個,有效地壓垮了服務器上的可用資源,從而導致服務崩潰。實施更改后,正在使用的套接字從平均超過 4000 個下降到始終小於 400 個,並且通常在 100 個左右。

image

我們一直在努力解決的socket耗盡問題令人失望,我們不能低估這個錯誤是多么不明顯。多年來,我們習慣於釋放實現IDisposable的對象,許多重構工具(如R#和CodeRush)實際上會警告你。在這種情況下,處理HttpClient是錯誤的事情。

1. 使用 HttpClient 時靜態化
2. 請勿在使用dispose of or wrap的 HttpClient,除非明確地要查找特定行為。

除了HttpClient還有一些組件可以考慮

https://github.com/tmenier/Flurl

https://github.com/restsharp/RestSharp

https://github.com/App-vNext/Polly

由於這個Http連接始終保持連接狀態,所以當請求地址的DNS發生更新的時候並不會應用到這個Http連接上。這個問題在微服務,高可用時代更加常見

[Singeton HttpClient doesn't respect DNS changes](https://github.com/dotnet/corefx/issues/11224), 博友解決方案


今天先到這兒,希望對雲原生,技術領導力, 企業管理,系統架構設計與評估,團隊管理, 項目管理, 產品管管,團隊建設 有參考作用 , 您可能感興趣的文章:
領導人怎樣帶領好團隊
構建創業公司突擊小團隊
國際化環境下系統架構演化
微服務架構設計
視頻直播平台的系統架構演化
微服務與Docker介紹
Docker與CI持續集成/CD
互聯網電商購物車架構演變案例
互聯網業務場景下消息隊列架構
互聯網高效研發團隊管理演進之一
消息系統架構設計演進
互聯網電商搜索架構演化之一
企業信息化與軟件工程的迷思
企業項目化管理介紹
軟件項目成功之要素
人際溝通風格介紹一
精益IT組織與分享式領導
學習型組織與企業
企業創新文化與等級觀念
組織目標與個人目標
初創公司人才招聘與管理
人才公司環境與企業文化
企業文化、團隊文化與知識共享
高效能的團隊建設
項目管理溝通計划
構建高效的研發與自動化運維
某大型電商雲平台實踐
互聯網數據庫架構設計思路
IT基礎架構規划方案一(網絡系統規划)
餐飲行業解決方案之客戶分析流程
餐飲行業解決方案之采購戰略制定與實施流程
餐飲行業解決方案之業務設計流程
供應鏈需求調研CheckList
企業應用之性能實時度量系統演變

如有想了解更多軟件設計與架構, 系統IT,企業信息化, 團隊管理 資訊,請關注我的微信訂閱號:

MegadotnetMicroMsg_thumb1_thumb1_thu[2]

作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。 該文章也同時發布在我的獨立博客中-Petter Liu Blog。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM