asp.Net   发布时间:2022-04-07  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了谈谈Circuit Breaker在.NET Core中的简单应用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

<h2 id="前言">前言

由于微服务的盛行,不少公司都将原来细粒度比较大的服务拆分成多个小的服务,让每个小服务做好自己的事即可。

经过拆分之后,就避免不了服务之间的相互调用问题!如果调用没有处理好,就有可能造成整个系统的瘫痪,好比说其中一些基础服务出现了故障,那么用到这些基础服务的地方都是要做一定的处理的,不能让它们出现大面积的瘫痪!!!

正常情况下的解决方案就要对服务进行熔断处理,不能因为提供方出现了问题就让调用方也废了。

熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施。

对于这个问题,的Circuit Breaker是一个不错的选择。本文的示例代码也是基于它的。

Steeltoe是什么呢?Steeltoe可以说是构建微服务的一个解决方案吧。具体的可以访问它的官网:

回归正题,先来看看官方对Circuit Breaker的描述:

不难发现,Circuit Breaker可以让我们很好的处理失败的服务。它也包含了对Netflix HyStrix的.NET(CorE)实现。

关于熔断机制,有个非常经典的图(这里直接拿了官方文档的图),核心描绘的就是三种状态之间的变化关系。

title="谈谈Circuit Breaker在.NET Core中的简单应用" alt="谈谈Circuit Breaker在.NET Core中的简单应用" src="https://cn.js-code.com/res/2019/02-08/23/da61fb0939a6e722be696a67828f6c61.png">

说了那么多,下面还是来看个简单的例子来略微深入理解一下吧。

注:服务发现和服务注册不是本文的重点,所以这里不会使用Steeltoe相应的功能。

先定义一个简单的订单服务,这个服务很简单,就一个返回直接返回对应订单号的接口,这里用默认的ASP.NET Core Web API项目做一下调整就好了。

[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET api/values/123
    [httpGet("{iD}")]
    public String Get(String id)
    {
        return $"order-{iD}";
    }        
}

再来一个新服务去调用上面的订单服务。

先抛开熔断相关的,定义一个用于访问订单服务的service接口和实现。

public interface Iorderservice
{
    Task GetOrderDetailsAsync(String orderId);
}

public class orderservice : Iorderservice
{
public async Task GetOrderDetailsAsync(String orderId)
{
using (httpClient client = new httpClient())
{
return await client.GetStringAsync($"http://localhost:9999/api/values/{orderId}");
}
}
}

比较简单,就是发起http请求到订单服务,拿一下返回的结果。

忽略熔断的话,现在已经可以通过这个orderservice去拿到结果了。

[httpGet]
public async Task Get([Fromservices] services.Iorderservice service,String id = "0")
{
    return await service.GetOrderDetailsAsync(id);
}

结果如下:

title="谈谈Circuit Breaker在.NET Core中的简单应用" alt="谈谈Circuit Breaker在.NET Core中的简单应用" src="https://cn.js-code.com/res/2019/02-08/23/e5a7eb1c965259c18b9d51115241564f.png">

这是最最最最理想的情况!如果我们把订单服务停了,会发生什么事呢?

title="谈谈Circuit Breaker在.NET Core中的简单应用" alt="谈谈Circuit Breaker在.NET Core中的简单应用" src="https://cn.js-code.com/res/2019/02-08/23/e0036611ba769f5437b507eb3bf18e92.png">

十分尴尬,这个订单服务的调用方也废了。

当然,try-catch也是可以帮我们处理这个尴尬的问题,但这并不是我们想要的结果啊!

下面来看看引入Circuit Breaker之后如何略微优雅一点去处理这个问题。

定义一个GetOrderDetailsHyStrixCommand,让它继承HyStrixCommand

public class GetOrderDetailsHyStrixCommand : HyStrixCommand
{
    private readonly Iorderservice _service;
    private readonly ILogger _logger;
    private String _orderId;
public GetOrderDetailsHyStrixCommand(
    IHyStrixCommandoptions options,Iorderservice service,ILogger<GetOrderDetailsHyStrixCommand> logger
    ) : base(options)
{
    this._service = service;
    this._logger = logger;
    this.IsfallBACkUserDefined = true;
}

public async Task<String> GetOrderDetailsAsync(String orderId)
{
    _orderId = orderId;
    return await ExecuteAsync();
}

protected override async Task<String> RunAsync()
{
    var result = await _service.GetOrderDetailsAsync(_orderId);
    _logger.LogInformation("Get the result : {0}",result);
    return result;
}

protected override async Task<String> RunfallBACkAsync()
{
    //断路器已经打开
    if (!this._circuitBreaker.Allowrequest)
    {
        return await Task.FromResult("Please wait for sometimes");
    }

    _logger.LogInformation($"RunfallBACk");
    return await Task.FromResult<String>($"RunfallBACkAsync---OrderId={_orderID}");
}

}

这里有几个地方要注意:

  1. 构造函数一定要有IHyStrixCommandoptions这个参数
  2. RunAsync是真正执行调用的地方
  3. RunfallBACkAsync是由于某些原因不能拿到返回结果时会执行的地方,所谓的优雅降级。

接下来要做的是在Startup中进行注册。

public void Configureservices(IserviceCollection services)
{
    services.AddSingleton();
    services.AddHyStrixCommand("Order",Configuration);
services.AddMvc();

}

可以看到,在添加熔断命令的时候,还用到了Configuration这个参数,这就说明,我们还少了配置!!

配置是放到appsetTings.json里面的,下面来看一下要怎么配置:

{
  "hyStrix": {
    "command": {
      "default": {
        "circuitBreaker": {
          //是否启用,默认是true
          "enabled": true,//在指定时间窗口内,熔断触发的最小个数
          "requestVolumeThreshold": 5,//熔断多少时间后去尝试请求
          "sleepWindowInMilliseconds": 5000,//失败率达到多少百分比后熔断
          "errorThresholdPercentage": 50,//是否强制开启熔断
          "forceOpen": false,//是否强制关闭熔断
          "forceClosed": false
        },//是否启用fallBACk
        "fallBACk": {
          "enabled": true
        }
      }
    }
  }
} 

需要添加一个名字为hyStrix的节点,里面的command节点才是我们要关注的地方!

default,是默认的配置,针对所有的Command!如果说有某个特定的Command要单独配置,可以在command下面添加相应的命令节点即可。

其他配置项,都已经用注释的方式解释了。

下面这张动图模拟了订单服务从可用->不可用->可用的情形。

title="谈谈Circuit Breaker在.NET Core中的简单应用" alt="谈谈Circuit Breaker在.NET Core中的简单应用" src="https://cn.js-code.com/res/2019/02-08/23/e8d8d8674ea4cb875f9e570d7e29aa56.gif">

除了服务不可用,可能还有一种情况发生的概率会比较大,超时

举个例子,有一个服务平常都是响应很快,突然有一段时间不知道什么原因,处理请求的速度慢了很多,这段时间内经常出现客户端等待很长的时间,甚至超时了。

当遇到这种情况的时候,一般都会设置一个超时时间,只要在这个时间内没有响应就认为是超时了!

可以通过下面的配置来完成超时的配置:

{
  "hyStrix": {
    "command": {
      "default": {
        "execution": {
          "timeout": {
            "enabled": true
          },"isolation": {
            "strategy": "THREAD","thread": {
              //超时时间
              "timeoutInMilliseconds": 1000
            } 
          }
        },}
    }
  }
} 

这里也只是介绍了几个比较常用和简单的功能,它还可以合并多个请求,缓存请求等诸多实用的功能。总体来说,Steeltoe的熔断功能,用起来还算是比较简单,也比较灵活。

更多配置和说明可以参

本文的示例代码:

大佬总结

以上是大佬教程为你收集整理的谈谈Circuit Breaker在.NET Core中的简单应用全部内容,希望文章能够帮你解决谈谈Circuit Breaker在.NET Core中的简单应用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

标签: