ASP.NET Core-通過HttpClientFactory使用HttpClient


概述:

在.NET Framwork中使用HttpClient直接這樣使用 using(var client = new HttpClient()){} ,高並發時頻繁創建socket,連接來不及釋放,socket被耗盡,就會出現問題。HttpClient 實現了 IDispose 接口,但當你 Dispose 它時,它不會立即關閉所使用的 tcp 連接,而是將 tcp 連接置為 TIME_WAIT 狀態,240秒(4分鍾)后才真正關閉連接。對於高並發的場景,比如每秒 1000 個請求,每個請求都用到 HttpClient ,4分鍾內會堆積24萬個 tcp 連接,這樣的連接爆棚會拖垮服務器。

所以不用頻繁創建HttpClient對象,要復用,可以用單例或靜態,並且設置成長連接。但這樣使用有一點問題是DNS更新會失效

在Core中推薦使用HttpClientFactory創建HttpClient,目的也是復用HttpClient。顧名思義 HttpClientFactory 就是 HttpClient 的工廠,內部已經幫我們處理好了對 HttpClient 的管理,不需要我們人工進行對象釋放,同時可命名,支持自定義請求頭,支持DNS更新等等等。

 HttpClientFacotry內部存放了HttpClient的緩存,並且定時Dispose,防止DNS緩存時間過長

HttpClientFactory使用方法:

案例1,直接使用HttpClientFactory

1、在startup中注冊

   public void ConfigureServices(IServiceCollection services)
   {
       services.AddHttpClient("client_1",config=>  //這里指定的 name=client_1 ,可以方便我們后期服用該實例
       {
           config.BaseAddress= new Uri("http://client_1.com");
           config.DefaultRequestHeaders.Add("header_1","header_1");
       });
       services.AddHttpClient("client_2",config=>
       {
           config.BaseAddress= new Uri("http://client_2.com");
           config.DefaultRequestHeaders.Add("header_2","header_2");
       });
       services.AddHttpClient();
   }

2、Controller中使用

public class TestController : ControllerBase
{
 private readonly IHttpClientFactory _httpClient;
 public TestController(IHttpClientFactory httpClient)
 {
     _httpClient = httpClient;
 }

 public async Task<ActionResult> Test()
 {
     var client = _httpClient.CreateClient("client_1"); //復用在 Startup 中定義的 client_1 的 httpclient
     var result = await client.GetStringAsync("/page1.html");

     var client2 = _httpClient.CreateClient(); //新建一個 HttpClient
     var result2 = await client.GetStringAsync("http://www.site.com/XXX.html");

     return null;
 }
}

 

案例2:為單個HttpClient添加DelegatingHandler,攔截請求記錄日志

public class LoggingHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.Content != null)
            {
                Debug.WriteLine(await request.Content.ReadAsStringAsync());
            }
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
            if (response.Content != null)
            {
                Debug.WriteLine(await response.Content.ReadAsStringAsync());
            }
            return response;
        }
    }

ConfigureServices中注冊:

services.AddHttpClient("baidu", config =>  
            {
                config.BaseAddress = new Uri("https://www.baidu.com");
                config.DefaultRequestHeaders.Add("header_1", "header_1");

            }).AddHttpMessageHandler(()=>new LoggingHandler());

案例3:設置HttpClientHandler

            services.AddHttpClient("client1", client => { client.BaseAddress = new System.Uri("https://www.baidu.com"); })
                .ConfigurePrimaryHttpMessageHandler(() => new System.Net.Http.HttpClientHandler()
                {//設置HttpClientHandler,也就是InnerHandler
                    UseCookies = false
                });

 

案例4:注冊全局DelegatingHandler,攔截所有httpClient請求

實現接口IHttpMessageHandlerBuilderFilter,並注冊。看下面文章

https://blog.csdn.net/weixin_30236595/article/details/101066107

 

 

參考:

https://blog.zhuliang.ltd/2019/02/net-core/HttpClient-HttpClientFactory-InNetCore.html

https://blog.csdn.net/weixin_34249367/article/details/86134102 

 

未完待續...


免責聲明!

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



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