ASP 实例 《ASP
发布时间:2022-09-14 12:53:53 所属栏目:Asp教程 来源:
导读: 调用IServiceCollection接口的AddHttpClient扩展方法进行服务注册的时候可以对HttpClient作相应的定制,比如可以设置超时时间、默认请求报头和网络代理等。如果应用会涉及针对众多不同类型API的调用,调用不同的
调用IServiceCollection接口的AddHttpClient扩展方法进行服务注册的时候可以对HttpClient作相应的定制,比如可以设置超时时间、默认请求报头和网络代理等。如果应用会涉及针对众多不同类型API的调用,调用不同的API可能需要采用不同的设置,比如局域网内部调用就比外部调用需要更小的超时设置。为了解决这个问题,我们对提供的设置赋予一个唯一的名称,在使用的时候针对这个标识提取对应的设置来创建HttpClient对象,为了方便描述,我们将这个唯一标识HttpClient设置的名称就称为HttpClient的名称。在接下来演示的实例中,我们将设置两个HttpClient来调用指向“”和“”这两个域名的API。为此我们需要在host文件中添加了如下的映射关系 127.0.0.1 www.foo.com 127.0.0.1 www.bar.com 在如下所示的演示实例中,我们为ASP.NET应用注册的终结点会返回包含请求的域名和路径。我们调用IServiceCollection接口的AddHttpClient方法注册了两个名称分别为“foo”和“bar”的HttpClient,并对它们的基础地址进行针对性的设置(S1205)。 using?System.Diagnostics; var?app?=?WebApplication.Create(args); app.Urls.Add("http://0.0.0.0:80"); app.MapGet("/{path}"?,? ????(HttpRequest?resquest,?HttpResponse?response) ????=>response.WriteAsync($"{resquest.Host}{resquest.Path}")); await?app.StartAsync(); var?services?=?new?ServiceCollection(); services.AddHttpClient("foo",?httpClient? ????=>?httpClient.BaseAddress?=?new?Uri("http://www.foo.com")); services.AddHttpClient("bar",?httpClient? ????=>?httpClient.BaseAddress?=?new?Uri("http://www.bar.com")); var?httpClientFactory?=?services ????.BuildServiceProvider() ????.GetRequiredService(); var?reply?=?await?httpClientFactory ????.CreateClient("foo").GetStringAsync("abc"); Debug.Assert(reply?==?"www.foo.com/abc"); reply?=?await?httpClientFactory ????.CreateClient("bar").GetStringAsync("xyz"); Debug.Assert(reply?==?"www.bar.com/xyz"); 我们将HttpClient的注册名称作为参数调用IHttpClientFactory工厂的Create方法得到对应的HttpClient对象。由于基础地址已经设置好了,所以在进行HTTP调用时只需要指定相对地址(“abc”和“xyz”)就可以了。 [S1206]强类型客户端 所谓“强类型客户端”指的针对具体场景自定义的用于调用指定API的类型,强类型客户端直接使用注入的HttpClient进行HTTP调用。对于上一个实例的应用场景,我们就可以定义如下两个客户端类型FooClient和BarClient,并使用它们分别调用指向不同域名的API。如代码片段所示,我们直接在其构造函数中注入了HttpClient对象,并在GetStringAsync方法中使用它来完成最终的HTTP调用。 public?class?FooClient { ????private?readonly?HttpClient?_httpClient; ????public?FooClient(HttpClient?httpClient)? ????????=>?_httpClient?=?httpClient; ????public?Task<string>?GetStringAsync(string?path)? ????????=>?_httpClient.GetStringAsync(path); } public?class?BarClient { ????private?readonly?HttpClient?_httpClient; ????public?BarClient(HttpClient?httpClient)? ????????=>?_httpClient?=?httpClient; ????public?Task<string>?GetStringAsync(string?path)? ????????=>?_httpClient.GetStringAsync(path); } 由于FooClient和BarClient对使用的HttpClient具有不同的要求,所以我们采用如下的方式调用IServiceCollection接口的AddHttpClient针对客户端类型对HttpClient进行针对设置,具体设置的依然是基础地址。由于AddHttpClient扩展方法会将作为泛型参数的TClient类型注册为服务,所以我们可以直接利用IServiceProvider对象提取对应的客户端实例。 [S1207]基于Polly的失败重试 在任何环境下都不可能确保次HTTP调用都能成功,所以在失败重试是很有必要的。失败重试是要讲究策略的,返回何种响应状态才需要重试?重试多少次?时间间隔多长?一提到策略化自动重试,大多数人会想到Polly这个开源框架,“Microsoft.Extensions.Http.Polly”这个NuGet包提供了IHttpClientFactory工厂和Polly的整合。在添加了这个包引用之后,我们将演示程序做了如下的修改。如代码片段所示,我们注册的终结点接收到的每三个请求只有一个会返回状态码为200的响应,其余两个响应码均为500。如果客户端能够确保失败后至少进行两次重试,那么就能保证客户端调用100%成功。 using?Polly; using?Polly.Extensions.Http; using?System.Diagnostics; var?app?=?WebApplication.Create(args); var?counter?=?0; app.MapGet("/",?(HttpResponse?response)? ????=>?response.StatusCode?=?counter++?%?3?==?0???200?:?500); await?app.StartAsync(); var?services?=?new?ServiceCollection(); services ????.AddHttpClient(string.Empty) ????.AddPolicyHandler(HttpPolicyExtensions ????????.HandleTransientHttpError() ????????.WaitAndRetryAsync(2,?_?=>?TimeSpan.FromSeconds(1))); var?httpClientFactory?=?services ????.BuildServiceProvider() ????.GetRequiredService(); while?(true) { ????var?request?=?new?HttpRequestMessage( ????????HttpMethod.Get,?"http://localhost:5000"); ????var?response?=?await?httpClientFactory ????????.CreateClient().SendAsync(request); ????Debug.Assert(response.IsSuccessStatusCode); } 如上面的代码片段所示,调用AddHttpClient扩展方法注册了一个默认匿名HttpClient(名称采用空字符串)之后,我们接着调用返回的IHttpClientBuilder对象的AddPolicyHandler扩展方法设置了失败重试策略。AddPolicyHandler方法的参数类型为IAsyncPolicy的参数,我们利用HttpPolicyExtensions类型的HandleTransientHttpError静态方法创建一个用来处理偶发错误(比如HttpRequestException异常和5XX/408响应)的PolicyBuilder对象。我们最终调用该对象的WaitAndRetryAsync方法返回所需的IAsyncPolicy对象,并通过参数设置了重试次数(两次)和每次重试时间间隔(1秒)。 在利用代表依赖注入容器的IServiceProvider对象得到IHttpClientFactory之后ASP 实例,我们在一个无限循环中利用它创建的HttpClient对本地承载的API发起调用,虽然服务端每三次调用只有一次是成功的,但是2次重试足以确保最终的调用是成功的,我们提供的调试断言证实了这一点。 (编辑:开发网_商丘站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐