欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何利用HttpClientFactory实现简单的熔断降级

程序员文章站 2022-03-21 15:13:30
前言 在2.1之后,有不少新东西,其中httpclientfactory算是一个。httpclientfactory涉及的东西也不算少,三四种clients , 请求...

前言

在2.1之后,有不少新东西,其中httpclientfactory算是一个。httpclientfactory涉及的东西也不算少,三四种clients , 请求中间件,与polly的结合,生命周期等。

steeltoe的组件升级到2.1后,不少示例代码已经使用httpclientfactory了。当然这是个题外话。

这里主要讲的是与polly的结合,来完成简单的熔断降级。在这之前,还是先看看关于httpclientfactory最简单的用法。

httpclientfactory的简单使用

用个简单的控制台程序来演示

这里就只是获取一下状态码,没有获取实际的内容。

static async task<string> basicusage()
{
  var servicecollection = new servicecollection();
  servicecollection.addhttpclient();
  var services = servicecollection.buildserviceprovider();
  var clientfactory = services.getservice<ihttpclientfactory>();

  var client = clientfactory.createclient();
  var request = new httprequestmessage(httpmethod.get, "https://www.github.com");

  var response = await client.sendasync(request).configureawait(false);

  return response.statuscode.tostring();
}

其实主要的操作就是addhttpclient,然后通过httpclientfactory创建一个httpclient对象,有了httpclient对象,下面的操作应该就不用多说了。

然后在main方法调用

console.writeline($"basicusage, statuscode = {basicusage().getawaiter().getresult()}");

用法感觉并没有太多的差别。下面来看看与polly的结合。

httpclientfactory和polly的结合

polly的wiki页面已经有了这两者结合使用的文档了。

https://github.com/app-vnext/polly/wiki/polly-and-httpclientfactory

其实现在对于我们来说,要想对http请求使用polly的一些特性已经非常的简单了。

我们在使用的时候要添加microsoft.extensions.http.polly的nuget包。

先来看看使用polly的三种扩展方法

扩展方法 说明
addtransienthttperrorpolicy 主要是处理http请求的错误,如http 5xx 的状态码,http 408 的状态码 以及system.net.http.httprequestexception异常。
addpolicyhandler 自定义,和传统定义polly的方式保持一致
addpolicyhandlerfromregistry 从policy集合(也是自定义的)里面选择自己想要的。

后面的操作,是用的addpolicyhandler。

由于我们要实现熔断降级,所以,我们必不可少的要用到circuitbreakerpolicy和fallbackpolicy,同时为了方便演示,再加个timeoutpolicy。

由于涉及到多个policy,所以我们必须要确定他们的执行顺序!

polly的wiki页面有个示例,还配了一幅很详细的时序图。

一句话来说就是最先起作用的,还是最后添加的那个。

下面就新建一个api项目,用来演示一下。

修改configureservices方法,具体如下

public void configureservices(iservicecollection services)
{
  var fallbackresponse = new httpresponsemessage();
  fallbackresponse.content = new stringcontent("fallback");
  fallbackresponse.statuscode = system.net.httpstatuscode.toomanyrequests;

  services.addhttpclient("cb", x =>
  {
    x.baseaddress = new uri("http://localhost:8000");
    x.defaultrequestheaders.add("user-agent", "httpclientfactory-test");
  })
  //fallback
  .addpolicyhandler(policy<httpresponsemessage>.handle<exception>().fallbackasync(fallbackresponse, async b =>
  {
    logger.logwarning($"fallback here {b.exception.message}");
  }))
  //circuit breaker
  .addpolicyhandler(policy<httpresponsemessage>.handle<exception>().circuitbreakerasync(2, timespan.fromseconds(4), (ex, ts) =>
  {
    logger.logwarning($"break here {ts.totalmilliseconds}");
  }, () =>
  {        
    logger.logwarning($"reset here ");
  }))
  //timeout
  .addpolicyhandler(policy.timeoutasync<httpresponsemessage>(1));
   
  services.addmvc().setcompatibilityversion(compatibilityversion.version_2_1);
}

然后是在控制器去使用。

[route("api/[controller]")]
[apicontroller]
public class valuescontroller : controllerbase
{
  private static int mycount = 0;

  private readonly ihttpclientfactory _clientfactory;

  public valuescontroller(ihttpclientfactory clientfactory)
  {
    this._clientfactory = clientfactory;
  }

  // get api/values/timeout
  [httpget("timeout")]
  public actionresult<ienumerable<string>> timeout()
  {
    if (mycount < 3)//模拟超时
    {
      system.threading.thread.sleep(3000);
    }
    mycount++;

    return new string[] { "value1", "value2" };
  }

  // get api/values
  [httpget("")]
  public async task<string> getasync()
  {
    var client = _clientfactory.createclient("cb");
    
    var request = new httprequestmessage(httpmethod.get, "/api/values/timeout");
    var response = await client.sendasync(request);
    var content = await response.content.readasstringasync();

    return content;
  }
}

效果如下

如何利用HttpClientFactory实现简单的熔断降级

前面几次请求,会因为超时或熔断,从而我们得到的结果是fallback。

过了4秒钟后再请求,由于没有超时,正常拿到了结果,所以熔断器会被reset。

来看看日志

如何利用HttpClientFactory实现简单的熔断降级

比较清晰的看到了所有的操作。

总结

总体来说,httpclientfactory还是很不错的。尤其是它可以直接使用polly相关的特性。

部分示例代码: httpclientfactorydemo

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。