.NET Core把HttpClient转用IHttpClientFactory

什么是HttpClient?

在.NET Core中要从服务器端发出请求(请求)的方式,如果以节点来说就是使用requestnode-fetch来发出请求。而在.NET中发出请求也有很多方法

  • HttpClient:.NET Core内建支持,推荐使用
  • RestSharp:NuGet第三方套件
  • Flurl.Http:NuGet第三方套件
  • HttpWebRequest:兼容旧版本,包装HttpClient,不推荐使用
  • Web客户端:原生支持,过时方法,不推荐使用

如何使用HttpClient

在.NET Core的Startup.cs中加入

public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpClient();
}

我自己使用时通常包装一次,直接把HttpClient DI(依赖注入)给自己包装的助手

public class HttpClientHelper
{
  private readonly HttpClient _client;
  
  public HttpClientHelper(HttpClient client)
  {
    _client = client;
  }
  public async Task<T> Send()
  {
    var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
    var response = await _client.SendAsync<T>(request);
    return response
  }
}

这样在Startup.cs就可以对我自己的Helper AddHttpClient

public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpClient<HttpClientHelper>();
}

为什么要转用IHttpClientFactory?

从.NET Core 2.1开始增加IHttpClientFactory,帮你管理HttpClient所有实体,导致因为开过多的实体造成性能低落,或者使用过多的连线造成资源替代问题。

虽然HttpClient实作了释放(IDispose)介面,但就算释放HttpClient,伺服器的连线并不会立即关闭,因为每次产生一个HttpClient实体,就会有相对应的HttpMessageHandler实体产生,而HttpClient是被使用者释放,但HttpMessageHandler却不会立即被释放,造成连线中断占用,且卷曲造成连线资源消耗。

IHttpClientFactory统一管理了HttpClient与HttpMessageHandler,让连线问题得以解决。

如何转用IHttpClientFactory

官方文件表示

上述使用中词释义的IHttpClientFactory就是重构现有应用程式的好方法。不会这影响使用HttpClient的方式。现有在应用程式中建立HttpClient实例的位置,使用CreateClient的呼叫来取代这些专案。

简单来说,就是要你直接用IHttpClientFactory替换原本的HttpClient,并使用CreateClient方法产生HttpClient,可以简单地替换。

public class HttpClientHelper
{
  private readonly IHttpClientFactory _clientFactory;
  
  public HttpClientHelper(IHttpClientFactory clientFactory)
  {
    _clientFactory = clientFactory;
  }
public async Task<T> Send()
  {
    var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
    var client =  _clientFactory.CreateClient();
    var response = await _client.SendAsync<T>(request);
    return response
  }
}

上面就是用惯性的HttpClient方法替代为IHttpClientFactory的范例。

 

遇到的雷是什么?

原本我使用HttpClient的时候,自己包装的HttpClientHelper因为已经通过AddHttpClient把HttpClientHelper丢给service,所以我并没有另外注册为Singleton,让其他Service可以直接DI这个HttpClientHelper,到这边都没有问题。

但一转用IHttpClientFactory后,如果只是单纯改写HttpClientFactory,应用程序一启动会造成执行期间错误

Unable to resolve service for type while attempting to activate

如何解决

把HttpClientHelper手动注册为Singleton即可解决问题

public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpClient<HttpClientHelper>();
  services.AddSingleton<HttpClientHelper>();
}

如果有需要也可以注册为Scoped

posted @ 2021-02-26 14:17  003建站  阅读(214)  评论(1)    收藏  举报