可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例。 这能带来以下好处:

  • 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例。 例如,可以注册 github 客户端,并将它配置为访问 GitHub。 可以注册一个默认客户端用于其他用途。
  • 通过委托 HttpClient 中的处理程序整理出站中间件的概念,并提供适用于基于 Polly 的中间件的扩展来利用概念。
  • 管理基础 HttpClientMessageHandler 实例的池和生存期,避免在手动管理 HttpClient 生存期时出现常见的 DNS 问题。
  • (通过 ILogger)添加可配置的记录体验,以处理工厂创建的客户端发送的所有请求。

在应用中可以通过以下多种方式使用 IHttpClientFactory

基本用法

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHttpClient();
}
    [Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHttpClientFactory _clientFactory;
public ValuesController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
} // GET api/values
[HttpGet]
public async Task<string> Get()
{
HttpClient client = _clientFactory.CreateClient(); //方法一:
//HttpRequestMessage request = new HttpRequestMessage
//{
// Method = new HttpMethod("get"),
// RequestUri = new System.Uri("http://localhost:5000/api/values"),
//};
//HttpResponseMessage response = await client.SendAsync(request);
//string res = await response.Content.ReadAsStringAsync();
//return res; //方法二:
string res = await client.GetStringAsync("http://localhost:5000/api/values");
return res;
}
}

命名客户端

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHttpClient("test", c =>
{
c.BaseAddress = new Uri("http://localhost:5000");
});
}
        public async Task<string> Get()
{
HttpClient client = _clientFactory.CreateClient("test");
//注册名叫 "test" 的客户端时,已经指定了该客户端的请求基地址,所以这里不需要指定主机名了
return await client.GetStringAsync("api/values");
}

类型化客户端

    public class TestHttpClient
{
public HttpClient Client { get; set; } public TestHttpClient(HttpClient client)
{
client.BaseAddress = new System.Uri("http://localhost:5000");
Client = client;
} public async Task<string> Get()
{
return await Client.GetStringAsync("api/values");
}
}
        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHttpClient<TestHttpClient>(c =>
{
//可以在这里设置,也可以在构造函数设置.
//c.BaseAddress = new System.Uri("http://localhost:5000");
});
}
    [Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly TestHttpClient _client; public ValuesController(TestHttpClient client)
{
_client = client;
} [HttpGet]
public async Task<string> Get()
{
return await _client.Get();
}
}

出站请求中间件

HttpClient 已经具有委托处理程序的概念,这些委托处理程序可以链接在一起,处理出站 HTTP 请求。 IHttpClientFactory 可以轻松定义处理程序并应用于每个命名客户端。 它支持注册和链接多个处理程序,以生成出站请求中间件管道。 每个处理程序都可以在出站请求前后执行工作。 此模式类似于 ASP.NET Core 中的入站中间件管道。 它提供了一种用于管理围绕 HTTP 请求的横切关注点的机制,包括缓存、错误处理、序列化以及日志记录。

要创建处理程序,需要定义一个派生自 DelegatingHandler 的类。 重写 SendAsync 方法,在将请求传递至管道中的下一个处理程序之前执行代码:

    public class ValidateHeaderHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!request.Headers.Contains("refuge"))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("not found refuge")
};
} return await base.SendAsync(request, cancellationToken);
}
}
        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddTransient<ValidateHeaderHandler>();//生存期必须是临时
services.AddHttpClient("test", c =>
{
c.BaseAddress = new Uri("http://localhost:5000");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();
}

HttpClient 和生存期管理

每次对 IHttpClientFactory 调用 CreateClient 都会返回一个新 HttpClient 实例:

        public IEnumerable<int> Get()
{
//测试生存期
for (int i = ; i < ; i++)
{
HttpClient client = i % ==
? _clientFactory.CreateClient("test")
: _clientFactory.CreateClient();
yield return client.GetHashCode();
}
}

CreateClient 方法内部会调用 CreateHandler 方法,后者创建 HttpMessageHandler,

源码如下:

    public HttpClient CreateClient(string name)
{
if (name == null)
throw new ArgumentNullException(nameof (name));
HttpClient httpClient = new HttpClient(this.CreateHandler(name), false);
HttpClientFactoryOptions clientFactoryOptions = this._optionsMonitor.Get(name);
for (int index = ; index < clientFactoryOptions.HttpClientActions.Count; ++index)
clientFactoryOptions.HttpClientActions[index](httpClient);
return httpClient;
}
    public HttpMessageHandler CreateHandler(string name)
{
if (name == null)
throw new ArgumentNullException(nameof (name));
ActiveHandlerTrackingEntry entry = this._activeHandlers.GetOrAdd(name, this._entryFactory).Value;
this.StartHandlerEntryTimer(entry);
return (HttpMessageHandler) entry.Handler;
}

而这个 _activeHandlers 的类型是 :

一个线程安全的键值对集合.

因此,实际上创建的 HttpMessageHandler 实例会汇集到池中.新建 HttpClient 实例时,可能会重用池中的 HttpMessageHandler 实例(如果生存期尚未到期的话).

由于每个处理程序通常管理自己的基础 HTTP 连接,因此需要池化处理程序.创建超出必要数量的处理程序可能会导致连接延迟. 部分处理程序还保持连接无期限地打开,这样可以防止处理程序对 DNS 更改作出反应.

处理程序的默认生存期为两分钟,可在每个命名客户端上重写默认值:

services.AddHttpClient("test").SetHandlerLifetime(TimeSpan.FromMinutes());

配置 HttpMessageHandler

有时候,我们需要控制客户端使用的内部 HttpMessageHandler .

            services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
AllowAutoRedirect = false,
});

ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求的更多相关文章

  1. ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述

    为了方便演示,以 .NET Core 控制台应用程序讲解. 我们新建一个控制台应用程序,安装 "Newtonsoft.Json" Nuget 包,然后右键点击该项目,选择" ...

  2. ASP.NET Core 2.2 基础知识(十六) SignalR 概述

    我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节. 就好像这个图: 所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microso ...

  3. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...

  4. ASP.NET Core 2.2 基础知识(十) Web服务器 - Kestrel

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  5. ASP.NET Core 2.2 基础知识(十五) Swagger

    安装 Nuget 包 注册 Swagger public void ConfigureServices(IServiceCollection services) { services.AddMvc() ...

  6. ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  7. ASP.NET Core 2.2 基础知识(十三) WebAPI 概述

    我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西 官方给出的模板: [Route("api/[controller]")] [ApiController] pub ...

  8. ASP.NET Core 2.2 基础知识(九) 使用托管服务实现后台任务

    在 ASP.NET Core 中,后台任务作为托管服务实现.托管服务是一个类,而且必须实现 IHostedService 接口,该接口定义了两个方法: StartAsync(CancellationT ...

  9. ASP.NET Core 2.2 基础知识(八) 主机 (未完待续)

    主机负责应用程序启动和生存期管理.共有两个主机 API : 1.Web 主机 : 适用于托管 Web 应用,基于 IWebHostBuilder ; 2.通用主机 : 适用于托管非 Web 应用. 基 ...

随机推荐

  1. GYM - 100814 C.Connecting Graph

    题意: 初始有n个点,m次操作.每次操作加一条边或者询问两个点第一次连通的时刻(若不连通输出-1). 题解: 用并查集维护每个点所在连通块的根.对于每次加边,暴力的更新新的根. 每次将2个块合并时,将 ...

  2. BZOJ1143 [CTSC2008]祭祀river 【二分图匹配】

    1143: [CTSC2008]祭祀river Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3236  Solved: 1651 [Submit] ...

  3. mobx基本概念

    mobx是一个简单可扩展的状态管理库,主要用来管理状态之间的依赖关系,可以使用在任何状态管理的场景,并不仅限于react. 结合mobx-react可以用在react中,结合mobx-vue可以用在v ...

  4. Ubuntu使用vim编辑器时出现上下左右键变成ABCD

    今天在配置安装php时,要打开配置文件做些修改,肯定是要使用到vim编辑器的,我按照之前的使用命令之类的,在用到上下左右键时居然出现了ABCD,这我就纳闷了,难道Ubuntu的vim编辑器和别的不一样 ...

  5. pycharm激活(JetBrains IDEA 系列产品通用xx方法(license server))

    http://xclient.info/a/f0b9738a-36fd-8a97-a966-0d3db497092d.html .打开激活窗口 .选择 Activate new license wit ...

  6. jquery从零起步学

    html: <HTML> <head> <meta http-equiv="content-type" content="text/html ...

  7. cglib

    参考:http://blog.csdn.net/zhoudaxia/article/details/30591941 <!-- https://mvnrepository.com/artifac ...

  8. CentOS7 Tomcat 启动过程很慢,JVM上的随机数与熵池策略

    1. CentOS7 Tomcat 启动过程很慢 在centos启动官方的tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的: <co ...

  9. wikioi 1245最小的N个和

    2013-09-08 10:12 LRJ的算法竞赛入门经典训练指南里有类似的题,原题要难很多,p189页 读入A,B两组中的所有数后,建立N个有序表: A1+B1<A2+B1<A3+B1& ...

  10. ie6浏览器兼容性

    1.ie6双倍边距bug 块状元素设置float(左浮动或有浮动),并且设置margin值之后,第一个浮动的元素其左侧margin值为正常的2倍,如图,可以看到第一个元素的左侧边距于其他元素两两之间的 ...