加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_商丘站长网 (https://www.0370zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

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次重试足以确保最终的调用是成功的,我们提供的调试断言证实了这一点。
 

(编辑:开发网_商丘站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!