HttpClientFactory-向外请求的最佳

简介

  • 它的组件包是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 重新设置。
posted @ 2020-06-07 12:37  梦一回  阅读(2193)  评论(0编辑  收藏  举报