.NET Core把HttpClient转用IHttpClientFactory
什么是HttpClient?
在.NET Core中要从服务器端发出请求(请求)的方式,如果以节点来说就是使用request或node-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。

浙公网安备 33010602011771号