詳解.NET 開發(fā)中 HttpClient 的坑與最佳實踐
在 .NET 項目開發(fā)中,HttpClient 幾乎是調(diào)用外部 API 的必備工具。它使用簡單,但如果不了解其內(nèi)部機制,往往會踩坑,甚至導(dǎo)致 服務(wù)雪崩、端口耗盡 等嚴重問題。
今天我們就來盤點一下 HttpClient 中常見的坑,以及對應(yīng)的最佳實踐。
1.using導(dǎo)致端口耗盡
很多開發(fā)者習(xí)慣這樣寫:
using?(var?client =?new?HttpClient())
{
? ??var?response =?await?client.GetAsync(url);
}表面上這是標(biāo)準的 C# 資源釋放模式,但 HttpClient 內(nèi)部維護了 連接池。頻繁創(chuàng)建和釋放,會導(dǎo)致 端口耗盡(Socket Exhaustion),最終請求失敗。
? 最佳實踐:HttpClient 應(yīng)該 復(fù)用。
在 ASP.NET Core 中推薦使用 IHttpClientFactory 來統(tǒng)一管理生命周期:
builder.Services.AddHttpClient("MyClient", client =>
{
? ? client.BaseAddress =?new?Uri("https://api.example.com");
});2. 全局 Header 污染
如果你這樣設(shè)置 Header:
httpClient.DefaultRequestHeaders.Add("Authorization",?"Bearer xxx");注意!所有后續(xù)請求都會帶上這個 Header。在多用戶、多服務(wù)場景下可能導(dǎo)致嚴重問題。
? 最佳實踐:推薦在 請求級別 設(shè)置 Header。
var?request =?new?HttpRequestMessage(HttpMethod.Get,?"/data");
request.Headers.Authorization =?new?AuthenticationHeaderValue("Bearer", token);3. 忘記釋放HttpResponseMessage
很多時候我們寫:
var?response =?await?httpClient.GetAsync("/data");
var?content =?await?response.Content.ReadAsStringAsync();如果沒有手動 Dispose,連接會長時間占用。
? 最佳實踐:使用 using 語法確保釋放。
using?var?response =?await?httpClient.GetAsync("/data");
response.EnsureSuccessStatusCode();
var?content =?await?response.Content.ReadAsStringAsync();4. 超時沒設(shè)置
HttpClient 默認超時時間是 100 秒。在高并發(fā)環(huán)境下,如果目標(biāo)服務(wù)響應(yīng)緩慢,可能會導(dǎo)致請求堆積。
? 最佳實踐:設(shè)置合理的超時時間。
httpClient.Timeout = TimeSpan.FromSeconds(10);
或者使用 CancellationToken 精確控制:
using?var?cts =?new?CancellationTokenSource(TimeSpan.FromSeconds(5));
await?httpClient.GetAsync("/data", cts.Token);5. DNS 緩存問題
在早期 .NET Framework 中,HttpClient 單例會導(dǎo)致 DNS 緩存永不過期。域名變更后,服務(wù)依然請求舊的 IP。
在 .NET Core 已經(jīng)優(yōu)化了這一點,但如果是老項目,可以手動指定連接生命周期:
builder.Services.AddHttpClient("MyClient")
? ? .ConfigurePrimaryHttpMessageHandler(() =>
? ? ? ??new?SocketsHttpHandler
? ? ? ? {
? ? ? ? ? ? PooledConnectionLifetime = TimeSpan.FromMinutes(2)
? ? ? ? });6. 大文件請求導(dǎo)致內(nèi)存爆炸
很多人習(xí)慣使用 ReadAsStringAsync(),但如果返回的是大文件(如日志、視頻),會直接把內(nèi)存撐爆。
? 最佳實踐:采用 流式處理。
using?var?response =?await?httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); await?using?var?stream =?await?response.Content.ReadAsStreamAsync(); // 手動處理流
7. 缺少重試機制
網(wǎng)絡(luò)調(diào)用難免失敗,如果沒有重試機制,服務(wù)穩(wěn)定性會大打折扣。
? 最佳實踐:結(jié)合 Polly 添加重試策略。
builder.Services.AddHttpClient("MyClient")
? ? .AddPolicyHandler(Policy
? ? ? ? .Handle<HttpRequestException>()
? ? ? ? .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
? ? ? ? .WaitAndRetryAsync(3, retry => TimeSpan.FromSeconds(retry)));
到此這篇關(guān)于詳解.NET 開發(fā)中 HttpClient 的坑與最佳實踐的文章就介紹到這了,更多相關(guān).NET HttpClient的坑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解一款開源免費的.NET文檔操作組件DocX(.NET組件介紹之一)
本篇文章主要是介紹了一款開源免費的.NET文檔操作組件DocX,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-12-12
基于asp.net MVC 應(yīng)用程序的生命周期(詳解)
下面小編就為大家分享一篇基于asp.net MVC 應(yīng)用程序的生命周期詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
.NET中的MassTransit分布式應(yīng)用框架詳解
MassTransit是一款優(yōu)秀的分布式應(yīng)用框架,可作為分布式應(yīng)用的消息總線,也可以用作單體應(yīng)用的事件總線,這篇文章主要介紹了.NET中的MassTransit分布式應(yīng)用框架,需要的朋友可以參考下2022-10-10
Entity Framework Core實現(xiàn)軟刪除與查詢過濾器
這篇文章介紹了Entity Framework Core實現(xiàn)軟刪除與查詢過濾器的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02
Asp.net中使用Sqlite數(shù)據(jù)庫的方法
Sqlite是最近比較流行的數(shù)據(jù)庫了,擁有比Access高效快速,易操作易實施。完全不需要在客戶端進行任何的配置,只需要在站點中引用入DLL文件即可使用了。2009-11-11

