HttpClient
HttpClient这个对象,虽然继承了IDisposable接口,但它是可以被共享的,且线程安全。建议在整个应用的生命周期内,复用HttpClient实例,而不是每次RPC请求的时候就实例化一个。
HttpClientFactory
HttpClientFacotry很高效,可以最大程度上节省系统socket。内部已经帮我们处理好了对HttpClient的管理。
HttpClientFactory的核心能力
- 管理内部 HttpMessageHandler 的生命周期,灵活应对资源问题和 DNS 刷新问题
- 支持命名化、类型化配置,集中管理配置,避免冲突
- 灵活的出站请求管道配置,轻松管理请求生命周期
- 内置管道最外层和最内层日志记录器,有 Information 和 Trace 输出
核心对象
- HttpClient
- HttpMessageHandler
- SocketsHttpHandler
- DelegatingHandler
- IHttpClientFactory
- IHttpClientBuilder
使用 HttpClientFactory
工厂模式
新建 TestServiceClient 类,使用 IHttpClientFactory 的 CreateClient 创建 HttpClient 并发起 HTTP请求:
public class TestServiceClient
{
IHttpClientFactory _httpClientFactory;
public TestServiceClient(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> Get()
{
var client = _httpClientFactory.CreateClient();
return await client.GetStringAsync("https://localhost:5555/WeatherForecast");
}
}
在Startup.cs中进行注册:
services.AddHttpClient();
services.AddScoped<TestServiceClient>();
使用:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly TestServiceClient _testServiceClient;
public ValuesController(TestServiceClient testServiceClient)
{
_testServiceClient = testServiceClient;
}
[HttpGet]
public async Task<string> Test()
{
return await _testServiceClient.Get();
}
}
命名客户端模式
新建 NamedServiceClient 类,使用 IHttpClientFactory 的 CreateClient 创建指定客户端名称的 HttpClient 并发起 HTTP请求:
public class NamedServiceClient
{
IHttpClientFactory _httpClientFactory;
const string _clientName = "NamedOrderServiceClient";
public NamedServiceClient(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> Get()
{
var client = _httpClientFactory.CreateClient(_clientName);
return await client.GetStringAsync("/WeatherForecast");
}
}
在Startup.cs中进行注册:
services.AddHttpClient("NamedServiceClient", client =>
{
client.DefaultRequestHeaders.Add("client-name", "namedclient");
client.BaseAddress = new Uri("https://localhost:5011");
}).SetHandlerLifetime(TimeSpan.FromMinutes(20));
services.AddScoped<NamedServiceClient>();
在注册时,可以初始化一些配置。如: DefaultRequestHeaders:配置请求头 BaseAddress:配置请求地址 SetHandlerLifetime:设置生命周期 …
使用:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly TestServiceClient _testServiceClient;
private readonly NamedServiceClient _namedServiceClient ;
public ValuesController(TestServiceClient testServiceClient,NamedServiceClient namedServiceClient)
{
_testServiceClient = testServiceClient;
_namedServiceClient = namedServiceClient;
}
[HttpGet]
public async Task<string> Test()
{
return await _namedServiceClient.Get();
}
}
类型化客户端模式
新建 NamedServiceClient 类,直接注入 HttpClient 并发起 HTTP请求:
public class TypedServiceClient
{
HttpClient _client;
public TypedServiceClient(HttpClient client)
{
_client = client;
}
public async Task<string> Get()
{
return await _client.GetStringAsync("/WeatherForecast");
}
}
在Startup.cs中进行注册:
services.AddHttpClient<TypedServiceClient>(client =>
{
client.BaseAddress = new Uri("https://localhost:5011");
});
在注册时,可以初始化一些配置。如: DefaultRequestHeaders:配置请求头 BaseAddress:配置请求地址 SetHandlerLifetime:设置生命周期 …
使用:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly TestServiceClient _testServiceClient;
private readonly NamedServiceClient _namedServiceClient;
private readonly TypedServiceClient _typedServiceClient;
public ValuesController(TestServiceClient testServiceClient, NamedServiceClient namedServiceClient, TypedServiceClient typedServiceClient)
{
_testServiceClient = testServiceClient;
_namedServiceClient = namedServiceClient;
_typedServiceClient = typedServiceClient;
}
[HttpGet]
public async Task<string> Test()
{
return await _typedServiceClient.Get();
}
}
自定义 DelegatingHandler
定义 RequestIdDelegatingHandler 类继承 DelegatingHandler ,实现管道的方式处理外向请求的通用逻辑:
public class RequestIdDelegatingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("x-guid", Guid.NewGuid().ToString());
var result = await base.SendAsync(request, cancellationToken);
return result;
}
}
在Startup.cs中进行注册:
services.AddSingleton<RequestIdDelegatingHandler>();
services.AddHttpClient<TypedServiceClient>(client =>
{
client.BaseAddress = new Uri("https://localhost:5011");
}).AddHttpMessageHandler(provider => provider.GetService<RequestIdDelegatingHandler>());
|