最近在進行開發過程中,基於都是介面開發,A站介面訪問B介面介面來請求資料,而在這個過程中我們使用的是HttpClient這個框架,當然也是微軟自己的框架,效能當前沒有問題,但如果你直接使用官方的寫法,在高併發時候,會有很大的效能隱患,因為它官方使用的是using的方式,而對於請求量比較大時,這種方法對TCP建立也會過高,即使用完馬上釋放也會有很多time_out的請求,所有決定把某個用到httpclient的元件做成靜態化的!
明細
統計
呼叫,中規中矩的寫法
using (var http = new HttpClient()) { var json = JsonConvert.SerializeObject(new { target_index = projectName, timestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), Level = level.ToString(), Message = message }); json = json.Replace("target_index", "@target_index").Replace("timestamp", "@timestamp"); var httpContent = new StringContent(json, Encoding.UTF8); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var result = http.PostAsync(apiLoggerUri, httpContent).Result; }
優化它,做成TCP長連結,所以請求走一個通道
private static readonly HttpClient _httpClient; private ApiLoggerOptions _config; static ApiLogger() { _httpClient = new HttpClient(); _httpClient.Timeout = new TimeSpan(0, 0, 10); _httpClient.DefaultRequestHeaders.Connection.Add("keep-alive"); }
keep-alive關鍵字可以理解為一個長連結,超時時間也可以在上面進行設定,例如10秒的超時時間,當然併發量太大,這個10秒應該會拋棄很多請求
傳送請求的程式碼沒有了using,即這個httpclient不會被手動dispose,而是由系統控制它,當然你的程式重啟時,這也就被回收了。
var json = JsonConvert.SerializeObject(new { target_index = projectName, timestamp = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), Level = level.ToString(), Message = message }); json = json.Replace("target_index", "@target_index").Replace("timestamp", "@timestamp"); var httpContent = new StringContent(json, Encoding.UTF8); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); _httpClient.PostAsync(apiLoggerUri, httpContent).Wait();
通過上面的改造,我們我係統效能得到了改善,TCP的連線數也降下來了
所以對於長連結的多路複用技術,相對於請求過多的情況還是最省資源的!