HttpClientFactory-向外請求的最佳

夢一回發表於2020-06-07

簡介

  • 它的元件包是Microsoft.Extensions.Http
  • 復原HttpClient帶來的問題

HttpClient相關問題

  • 雖然HttpClient類實現了IDisposable,但不是首選在using語句中宣告和例項化它,因為釋放HttpClient物件時,基礎套接字不會立即釋放,這可能會導致“套接字耗盡”問題 。因此,HttpClient 應進行一次例項化並在應用程式的生命週期中重複使用。 在負載較重的情況下,例項化每個請求的 HttpClient 類將耗盡可用的套接字數。 該問題會導致 SocketException 錯誤。 要解決此問題,可能的方法是將 HttpClient 物件建立為單一物件或靜態物件,在長期執行的程式中使用 HttpClient 的共享例項時,開發人員遇到的另一個問題。 在將 HttpClient 例項化為單一例項或靜態物件的情況下,它無法處理 DNS 更改,但是,問題實際上不是 HttpClient 本身,而是 HttpClient 的預設建構函式,因為它建立了一個新的實際 HttpMessageHandler 例項,該例項具有上面提到的“套接字耗盡”和 DNS 更改問題 。

參考解決內容

核心點

  • 管理內部HttpMessageHandler的生命週期,靈活應對資源問題和DNS重新整理問題。
  • 支援命名化,型別化配置,集中管理配置,避免衝突
  • 靈活的出站請求管道配置,輕鬆管理請求生命週期
  • 內建管道最外層和最記憶體日誌記錄器,有Information和Trace輸出

核心物件

  • HttpClient
  • HttpMessageHandler
  • SocketsHttpHandler
  • DelegatingHandler
  • IHttpClientFactory
  • IHttpClientBuilder

使用方式

  • 基本用法
  • 命名客戶端模式
  • 型別化客戶端模式
  • 生成的客戶端

基本用法

//首先,在Startup中的ConfigureService註冊我們的HttClient服務,僅僅一行程式碼就可以搞定
service.AddHttpClien();
//接著,我們通過依賴注入來請求IHttpClientFactory,並建立HttpClient例項,以下程式碼之後我們就可以放心使用HttpClient
public BasicUsageModel(IHttpClientFactory clientFactory)
{
  _clientFactory = clientFactory;
}
public async Task OnGet()
{
      var client = _clientFactory.CreateClient();
}

型別化客戶端

publi class XXXClient
{
      IHttpClientFactory _httpclientFatory;
      public XXXClient(IHttpClientFactory httpclientFatory)
      {
            _httpclientFatory=httpclientFatory;
      }
      public async Task<string> Get()
      {
            var client = _httpclientFatory.CreateClient();
            return await client.GetStringAsync("xxx.url");
      }
}
註冊
services.AddHttpClient<XXXClient>();

出站請求中介軟體

  • HttpClient具有委託處理程式概念。

建立委託處理程式

  • 派生自DelegatingHandler (將 HTTP 響應訊息的處理委託給另一處理程式(稱為“內部處理程式”)的 HTTP 處理程式的型別。)
  • 重寫SendAsync

程式碼

 public class xxxHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            //處理請求
           
            var result = await base.SendAsync(request, cancellationToken); //呼叫內部handler

            //處理響應

            return result;
        }
    }
      
 public void ConfigureServices(IServiceCollection services){
             services.AddSingleton<xxxHandler>();
            services.AddHttpClient("XXXServiceClient", client =>
            {
                client.DefaultRequestHeaders.Add("client-name", "namedclient");
                client.BaseAddress = new Uri("https://localhost:5003");
            }).SetHandlerLifetime(TimeSpan.FromMinutes(20))
            .AddHttpMessageHandler(provider => provider.GetService<xxxHandler>());
            services.AddScoped<xxxHandler>();
}
public class XXXServiceClient
    {
        IHttpClientFactory _httpClientFactory;

        const string _clientName = "NamedOrderServiceClient";  //定義客戶端名稱

        public XXXServiceClient(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
        public async Task<string> Get()
        {
            var client = _httpClientFactory.CreateClient(_clientName); //使用客戶端名稱獲取客戶端

            //使用client發起HTTP請求,這裡使用相對路徑來訪問
            return await client.GetStringAsync("/OrderService");
        }
    }

生命週期

  • 每次對 IHttpClientFactory 呼叫 CreateClient 都會返回一個新 HttpClient 例項。 每個命名客戶端都建立一個 HttpMessageHandler。 工廠管理 HttpMessageHandler 例項的生存期。
  • 處理程式的預設生存期為兩分鐘,可通過SetHandlerLifetime 重新設定。

相關文章