1.熔断器的开启--常用的熔断器方法:defaultFallback
// 可以造成熔断的方法@GetMapping("/sleep5/{id}")@HystrixCommand(defaultFallback = "sleepBreaker", commandProperties = {@HystrixProperty(name = "circuitBreaker.enabled", value = "true"), // 开启熔断器@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 当请求达到这个数量之后,才进行错误占比的计算。@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 半打开休眠时间,熔断之后过了这段休眠时间,就会半打开,尝试接口是否恢复,如果恢复就完全打开熔断器。@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") // 错误占比,当错误次数超过这个百分比,就会熔断。}) // commandProperties 的整个意思就是10秒中10次请求中有60%的请求出问题就熔断public String sleep5(@PathVariable("id") int id) throws Exception {if (id < 0) {throw new Exception("id 是负数,抛出异常!!");}return "访问正常 id:" + id + " port:" + port;}// 熔断时调用的方法public String sleepBreaker() {return "接口有问题,目前被熔断了...";}
1)传参正常情况:
2)问题情况:(errorThresholdPercentage设置为60%)
3)多次使用-1为参数访问,再用1做为参数再访问,也不会得到正常结果了,就是被熔断了:
是因为(sleepWindowInMilliseconds", value = "10000"), 半打开休眠时间10s,熔断之后过了这段休眠时间,就会半打开,尝试接口是否恢复,如果恢复就完全打开熔断器。
2.另一种熔断器方法:fallbackMethod
注解@HystrixCommand除了defaultFallback这个参数可以调默认降级方法外,还有一个fallbackMethod可以调用一个与原方法对应的参数相同的方法,用于提供更明确的提示。
// 感觉这个说法还算靠谱点// fallbackMethod: 设置HystrixCommand服务降级所使用的方法名称,注意该方法需要与原方法定义在同一个类中,并且方法签名也要一致// defaultFallback: 设置HystrixCommand默认的服务降级处理方法,如果同时设定了fallbackMethod,会优先使用fallbackMethod所指定的方法,需要注意的是defaultFallback该属性所指定的方法没有参数,需要注意返回值与原方法返回值的兼容性@GetMapping("/sleep/{id}")@HystrixCommand(fallbackMethod = "sleepFallbackMethod", defaultFallback = "sleepFallback") // 使用指定的降级方法public String sleep(@PathVariable("id") int id) {int a = 10 / 0; // 触发抛出异常return productApi.sleep() + port + " id: " + id;}// 参数签名必须与原方法相同public String sleepFallbackMethod(int id) {return "sleep 方法被 控制器中指定的方法sleepFallbackMethod 降级,参数是:" + id;}// 无参数public String sleepFallback() {return "sleepFallback 控制器中方法降级..." + port;}
三. 给多个方法指定默认的降级方法
有可能多个方法降级的提示只需要返回相同的内容,这时可以给控制器类增加注解:@DefaultProperties(defaultFallback = "通用的降级方法名")
@DefaultProperties(defaultFallback = "sleepFallbackDefault")
控制器内添加4个方法:需要有降级的方法只需添加注解@HystrixCommand,不需要指定降级方法名,会使用类上指定的默认降级方法。不添加注解的不会做降级处理。
@GetMapping("/sleep2")@HystrixCommand // 使用默认的降级方法public String sleep2() {return productApi.sleep() + port;}@GetMapping("/sleep3")@HystrixCommand // 使用默认的降级方法public String sleep3() {return productApi.sleep() + port;}// 不做降级处理,会出异常:java.net.SocketTimeoutException: Read timed out@GetMapping("/sleep4")public String sleep4() {return productApi.sleep() + port;}// 无参数public String sleepFallbackDefault() {return "sleepFallbackDefault 控制器中方法降级,默认的降级方法..." + port;}
可以看到sleep4方法没有指定注解,方法没有降级。为了防止出现这种情况出现,可以为Feign定义的接口(ProductApi)提供一个实现类,来定义接口中各方法的降级方法。
为Feign的接口实现一个类
步骤:
- 修改application.yml 启用 Feign 对 Hystrix的支持。
- 实现接口 ProductApi 的一个实现类。
- 为接口ProductApi的注解@FeignClient增加参数fallback
feign:hystrix:# 开启 Feign对Hystrix的支持enabled: true
添加 ProductApi 接口的实现类 ProductApiHystrix.java,并注入容器
package com.example.api.hystrix;import com.example.api.ProductApi; import org.springframework.stereotype.Component;@Component // 注入容器 public class ProductApiHystrix implements ProductApi{@Overridepublic String index() {return "ProductApiHystrix.index 降级方法...";}@Overridepublic String sleep() {return "ProductApiHystrix.sleep 降级方法...";}}
为接口ProductApi的注解@FeignClient增加参数fallback
@FeignClient(value = "PRODUCT-SERVICE", fallback = ProductApiHystrix.class)
重启并访问,可以看到控制器的方法没有做改变的情况下,达到了降级的目的:
测试:
到此,降级已经完成。