美文网首页
18,深入Hystrix断路器执行原理

18,深入Hystrix断路器执行原理

作者: 滔滔逐浪 | 来源:发表于2019-02-01 11:52 被阅读78次

https://www.jianshu.com/p/c2ab1ea4983d

深入Hystrix断路器执行原理

RequestVolumeThreshold

HystrixCommandProperties.Setter()
     .withCircuitBreakerRequestVolumeThreshold(int)

表示在滑动窗口中,至少有多个请求,才肯那个出发断路。
Hystrix经过断路器的流量超过了一定的阀值,才有可能出发断路。比如说,要求在10s内经过断路器的流量必须达到20个,而实际超过断路器的流量才10个,那么根本不会去判断要不要断路。

ErrorThresholdPercentage

HystrixCommandProperties.Setter()
    .withCircuiBreakerErrorYhresholdPercentage(int)

表示异常比例达到多少,才会触发断路,默认为50(%).
如果断路器统计到异常调用的占比超过了一定的阀值,比如说在10s内,经过断路器的流量达到了30个,同时其中的异常访问数量也达到了一定的比例,比如60%的请求都是异常(报错/超时/reject),就会开启断路。

SleepWindowlnMilliseconds

HystrixCommandProperties.Setter()
  .withCircuitBreakerSleepWindowInMilliseconds(int)

断路开启,也就是由close转换到open状态(close->open).那么在之后sleepWindowInMilliseconds时间内,所有经过该断路器的请求全部都会被断路,不调用后端服务,直接走fallback降级机制。

而在该参数时间以后,断路器会变为half-open扳开闭状态,尝试让一条请求经过断路器,看能不能正常调用。如果调用成功了,那么就自动恢复,断路器转为close状态。

Enabled

   HystrixCommandProperties.Setter()
        .wiithCircuitBreakerEnabled(boolean)

控制是否允许断路器工作,包括跟踪依赖服务调用的健康状况,以及对于异常过多时是否允许触发断路。默认值为true.

ForceOpen

HystrixCommandProperties.Setter()
     .withCircuitBreakerEnabled(boolean)

控制是否允许断路器工作,包括跟踪依赖服务调用的健康情况,以及对异常情况过多时,是否允许触发断路。默认值为true.

ForceOpen

HystrixCommandProperties.Setter()
    .withCircuitBreakerForceOpen(boolean)

如果设置为true的话,直接强迫打开断路器相当于手动断路了,手动降级,默认值为false。

ForceClosed

HystrixCommandProperties.Setter()
    .withCircuitBreakerForceClosed(boolean)

如果设置为true,直接强迫关闭断路器,相当于手动停止断路了,手动升级,默认值为false.
实例Demo

HystrixCommand配置参数

在GetProductInfoCommand中配置Setter断路器相关参数。
1,滑动窗口中,最少20个请求,才肯那个触发断路
2,异常比例达到40%时,才触发断路
3,短路后3000ms内,所有请求都被reject,直接走fallback降级,不会调用run()方法。3000ms过后,变为half-open状态。

run()方法中,我们判断下productld是否为-1,是的话,直接跑出异常。这么写,我们之后测试的时候就可以传入productld=-1模拟服务执行异常了。

在降级逻辑中,我们直接给他返回降级商品就好了。

 public class GetProductInfoCommand extends HystrixCommand<ProductInfo>{
private Long productId;
private static final HystrixCommandKey KEY=HystrixCommandKey.Factory.asKey("GetProductInfoCommand");


public GetProductInfoCommand(Long productId){
  super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService"))
 .andCommandKey(KEY)
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
   //是否允许断路器工作
.withCircuiBreakerEndabled(true)
//滑动窗口中,最少有多少个请求,才可能触发断路
.withCircuitBreakerRequestVolumeThreshold(20)
//异常比例达到多少,才触发断路,默认为50%
.withCircuitBreakerErrorThresholdPercentage(40)
//断路器后多少时间内直接reject请求,之后进入half-open状态,默认为5000ms
.withCircuitBreakerSleepWindowInMilliseconds(3000)));
this.productId =productId;

}
protected ProductInfo run() throws Exception{

 System.out.println("调用接口查询商品数据,productId="+productId);
if(productId ==-1L){
   throw new Exception();
}

       String url = "http://localhost:8081/getProductInfo?productId=" + productId;
       String response = HttpClientUtils.sendGetRequest(url);
       return JSONObject.parseObject(response, ProductInfo.class);

}
protected productInfo getFallback(){
   ProductInfo productInfo =new ProductInfo();
productInfo.setName("降级商品");
   return productInfo;
}
}

断路测试类

我们在测试类中,前30次请求,传入productId =1,然后休眠3s,之后70次请求,传入producytId=1;

@SpringBootTest
@RunWith(SpringRunner.class)
public class CircuitBreakerTest{
@Test
public void testCircuitBreaker(){
    String baseURL = "http://localhost:8080/getProductInfo?productId=";
for(int i =0; i<30; ++i){
    //传入-1,会抛出异常,然后走降级逻辑
HttpClientUtils.sendGetRequest(baseURL+"-1);
}  
        TimeUtils.sleep(3);
System.out.println("After sleeping.... ");
  for(int i=31;i<100;i++){
   //传入1,走服务正常调用
HttpClientUtils.sendGetRequest(baseURL+"1");
}


}


}


测试结果

测试结果,我们可以明显看出系统断路与恢复的整个过程

调用接口查询商品数据,productId=-1
ProductInfo(id=null, name=降级商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null)
// ...
// 这里重复打印了 20 次上面的结果


ProductInfo(id=null, name=降级商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null)
// ...
// 这里重复打印了 8 次上面的结果


// 休眠 3s 后
调用接口查询商品数据,productId=1
ProductInfo(id=1, name=iphone7手机, price=5599.0, pictureList=a.jpg,b.jpg, specification=iphone7的规格, service=iphone7的售后服务, color=红色,白色,黑色, size=5.5, shopId=1, modifiedTime=2017-01-01 12:00:00, cityId=1, cityName=null, brandId=1, brandName=null)
// ...
// 这里重复打印了 69 次上面的结果

前 30 次请求,我们传入的 productId 为 -1,所以服务执行过程中会抛出异常。我们设置了最少 20 次请求通过断路器并且异常比例超出 40% 就触发断路。因此执行了 21 次接口调用,每次都抛异常并且走降级,21 次过后,断路器就被打开了。
之后的 9 次请求,都不会执行 run() 方法,也就不会打印以下信息。
调用接口查询商品数据,productId=-1

而是直接走降级逻辑,调用 getFallback() 执行。
休眠了 3s 后,我们在之后的 70 次请求中,都传入 productId 为 1。由于我们前面设置了 3000ms 过后断路器变为 half-open 状态。因此 Hystrix 会尝试执行请求,发现成功了,那么断路器关闭,之后的所有请求也都能正常调用了。

相关文章

网友评论

      本文标题:18,深入Hystrix断路器执行原理

      本文链接:https://www.haomeiwen.com/subject/zeklsqtx.html