您好,登錄后才能下訂單哦!
本篇文章為大家展示了HttpClientFactory如何在.NET Core 2.1中使用,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
什么是HttpClientFactory?
用ASP.NET團隊的話說:“an opinionated factory for creating HttpClient instances”(一個用于創建HttpClient實例的最佳實踐的工廠),并且是ASP.NET Core 2.1發布的新功能。根據大家以前使用HttpClient的經驗,您可能遇到一些困擾的問題,有時甚至沒有意識到您有問題(只是在并發并不大的場景沒觸發而已)。
第一個問題是當你在代碼中創建太多的HttpClients時,這反過來會產生兩個問題......
這是低效的,因為每個請求都有自己的遠程服務器連接池。這意味著您需要為每個創建的客戶端支付重新連接到該遠程服務器的成本。
更大的問題是如果你創建了很多HttpClient并使用到他們,你可以遇到Socket耗盡,而你基本上已經太快地使用了過多的Socket。您可以同時打開多個Socket是有限制的。當您dispose銷毀HttpClient時,它打開的連接在TIME_WAIT狀態下保持打開狀態最長240秒(如果來自遠程服務器的任何數據包仍然通過)。
HttpClient實現了IDisposable,這通常會導致開發人員在使用IDisposable對象時遵循正常模式,在using塊中創建它。這樣可以確保一旦完成對象并且它已經超出范圍,就可以正確銷毀對象。
因此,最優的方法是重用HttpClient實例,以便也可以重用連接。HttpClient是一個可變對象,但只要你沒有運行期改變它,它實際上是線程安全的并且可以共享。因此,一種常見的方法是將其注冊為具有DI框架的單例模式,或者創建包含static靜態實例的對象。
但是,這會產生新問題。以這種方式使用單個HttpClient將保持連接打開并且不遵守DNS生存時間(TTL)設置(總之就是同一個HttpClient實例只能有一個請求頭,在被請求方發生更改時,由于是單例不能做個性化改變,否則導致其他請求失敗)。現在連接將永遠不會獲得DNS更新,因此您正在與之通信的服務器將永遠不會更新其地址。在某些情況下,這是完全有可能的,在以上這種情況下,您可以平衡許多主機,這些主機可能隨著時間的推移而改變,或者可能使用Blue/Green 部署推出新服務。如果服務器消改變,則您的連接使用的IP可能不再響應您通過單個HttpClient發出的請求。
所以需要我們手動去管理每類服務器的HttpClient的實例來進行個性化請求頭的構造和發起請求!
HttpClientFactory旨在幫助您開始解決這些問題,并提供了一種新的機制來創建在幕后為我們正確管理的HttpClient實例。它將為我們“做管理HttpClient的事”,我們可以專注于業務!雖然在參考HttpClient時提到了上述問題,但事實上問題的根源實際上發生在HttpClient上,HttpClient使用了HttpClientHandler。HttpClientFactory管理處理程序的生命周期,以便我們有一個可以重用的池,同時還可以(Rotating)輪換它們以使DNS不會過時。
使用HttpClient的昂貴部分實際上是創建HttpClientHandler和連接。以這種HttpClientFacotry方式匯集這些內容意味著我們可以更高效利用資源最節省地使用我們系統上的socket。當您使用HttpClientFactory請求HttpClient時,實際上每次都會獲得一個新實例,這意味著我們不必擔心會改變它的狀態。此HttpClient可能(或可能不)使用池中的現有HttpClientHandler,從而使用現有打開的連接。
默認情況下,每個新創建的HttpClientHandler(派生自HttpMessageHandler)生命周期只有2分鐘。通過services.AddHttpClient()創建HttpClientFactory實例時,可以根據每一個命名的Client客戶機進行控制。達到生命周期后,處理程序將不會立即被釋放掉,而是放入過期的池中。任何依賴于HttpClientFactory的處理程序鏈的客戶端都可以繼續使用它而沒有任何問題。有一個后臺作業檢查過期的池,以查看處理程序的所有引用是否已在scope之外,此時可以將其釋放掉。處理程序鏈過期后對新客戶端的任何新請求都將獲得新的處理程序鏈。
這種方法運行得相當不錯,但.NET Core方面還有其他一些事情可能會進一步改善這種情況。.NET Core團隊開發了一個新的ManagedHandler,它可以更正確地管理DNS,原則上可以保持更長時間,這意味著可以更有效地共享連接。這個新的處理程序還被設計為在不同的操作系統中更加一致地運行。在該工作完成之前,上面的處理程序池是一個合理的解決方法。
如何使用HttpClientFactory
我們將首先創建一個簡單的WebAPI項目
接下來,我們需要轉到我們的Startup.cs文件并注冊一個服務。
services.AddHttpClient(); services.AddScoped(typeof(ClassInService));//此處無關HttpClient,請暫時忽視他
在幕后,這將注冊一些必需的服務,其中一個是IHttpClientFactory的實現。接下來,我們在業務中使用他
public class ClassInService { /// <summary> /// 構建器 /// </summary> /// <param name="clientFactory"></param> public ClassInService(IHttpClientFactory clientFactory) { _clientFactory = clientFactory; } }
private void HttpClientFactoryTest() { var client = _clientFactory.CreateClient("這是專門用來連接博客園的");//必須和services.AddHttpClient()中指定的名稱對應 var content = new StringContent($"SID={SID}&safeKey={111}"); content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); var response = client.PostAsync("MyBlogUrl", content); }
這里我們首先添加對IHttpClientFactory的依賴,它將由DI系統注入ClassInService。IHttpClientFactory允許我們請求和接收HttpClient實例。
我們使用HttpClientFactory創建客戶端。在幕后,HttpClientFactory將為我們創建一個新的HttpClient。但是等等,之前說過為每個請求使用新的HttpClient是很糟糕。但此處的創建的httpclient是在他所管理的池子中,并不每個請求都會是新的socket。
HttpClientFactory收集這些HttpClientHandler實例并管理它們的生命周期,以解決之前提到的一些問題。每次我們要求HttpClient時,我們都會得到一個新實例,它可能(或可能不)使用現有的HttpClientHandler。HttpClient本身并沒有問題。
一旦創建,由此創建的所有HttpClientHandler將被默認保持約2分鐘。這意味著針對同一個CreateClient的任何新請求都可以共享處理程序,因此也可以共享連接。當HttpClient存在時,它的處理程序將保持可用狀態,并且它將再次共享連接。
兩分鐘后,每個HttpClientHandler都標記為已過期。過期狀態只是標記它們,以便在創建任何新的HttpClient實例時不再使用它們。但是,它們不會立即銷毀,因為其他HttpClient實例可能正在使用它們。HttpClientFactory使用后臺服務監視過期的處理程序,一旦它們不再被引用,就可以正確釋放它們,也允許它們的連接被關閉。
上述內容就是HttpClientFactory如何在.NET Core 2.1中使用,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。