前面学习了Ribbon和Feign的负载均衡、超时重试。本章我们一起学习当Ribbon结合Hystrix与Feign结合Hystrix实现服务的熔断和降级。
Hystrix是什么?
在微服务架构中,微服务之间互相依赖较大,相互之间调用必不可免的会失败。但当下游服务A因为瞬时流量导致服务崩溃,其他依赖于A服务的B、C服务由于调用A服务超时耗费了大量的资源,长时间下去,B、C服务也会崩溃。Hystrix就是用来解决服务之间相互调用失败,避免产生蝴蝶效应的熔断器,以及提供降级选项。Hystrix通过隔离服务之间的访问点,阻止它们之间的级联故障以及提供默认选项来实现这一目标,以提高系统的整体健壮性。
用来解决什么问题
用来避免由于服务之间依赖较重,出现个别服务宕机、停止服务导致大面积服务雪崩的情况。
ribbon结合hystrix
继续【服务消费者Feign(Greenwich.SR2)】来学习
pom
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类加上 @EnableHystrix 注解,开启熔断器
@EnableHystrix
@SpringBootApplication
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class);
}
}
新增getRibbonHystrix和执行回退getHystrixFall。回退方法需要和被执行回退的方法在同一个类中。
本文采用yml方式来配置Hystrix,也可以采用注解的方式来配置,但是如果有多个相同方法配置相同,代码就会冗余,请参考【 SpringCloud入门(三):服务消费者RestTemplate+Ribbon(Greenwich.SR2)】
DefaultProperties
@DefaultProperties
@RestController
public class RibbonController {
@Autowired
private RestTemplate restTemplate;
/**
* @description 降级
* @author hero良
* @param name
* @return
*/
@GetMapping("/getRibbonHystrix")
@HystrixCommand(defaultFallback = "getHystrixFall")
public String getRibbonHystrix(){
return restTemplate.getForObject("http://provider/appController/getRibbonHystrix", String.class);
}
/**
* 回退方法需要和执行它的方法在一个类中
* @description 降级回退
* @author hero良
* @param
* @return
*/
String getHystrixFall() {
return "我是回退方法 getRibbonHystrix";
}
yml配置
hystrix超时 > MaxAutoRetries+MaxAutoRetriesNextServer+(MaxAutoRetries * MaxAutoRetriesNextServer) + 1,不然还在尝试连接服务提供者,而熔断超时时间已经到了,直接熔断返回,就没有任何意义了
hystrix:
# === === === == 默认Command === === === ==
command:
default:
execution:
isolation:
# 调用隔离方式, 默认: 采用线程隔离, ExecutionIsolationStrategy:THREAD
strategy: THREAD
# 调用超时时间, 默认: 5 秒
thread:
timeoutInMilliseconds: 8000
# 使用信号量隔离时, 命令调用最大的并发数
semaphore:
maxConcurrentRequests: 10
#使用信号量隔离时, 命令fallback调用最大的并发数
fallback:
isolation:
semaphore:
maxConcurrentRequests: 10
# === === === == 熔断器 === === === ==
circuitBreaker:
# 熔断器在整个统计时间内是否开启的阀值, 默认20个请求
requestVolumeThreshold: 8
# 熔断器默认工作时间, 默认: 5 秒
sleepWindowInMilliseconds: 5
# 默认: 50%, 当出错率超过50% 后熔断器启动
errorThresholdPercentage: 50
# 是否强制开启熔断器阻断所有请求, 默认: false, 不开启
forceOpen: false
# 是否允许熔断器忽略错误, 默认false, 不开启
forceClosed: false
# === === === == 线程池 === === === ==
threadpool:
default:
# 配置线程池大小, 默认值10个
coreSize: 10
# 配置队列长度, 默认-1使用SynchronousQueue,其他值则使用LinkedBlockingQueue:不可动态修改:
maxQueueSize: -1
# 队列拒绝的阈值,可通过修改这个变量动态修改允许排队的长度: maxQueueSize=-1时不适用:
queueSizeRejectionThreshold: 5
# 线程生存时间, 默认1分钟
keepAliveTimeMinutes: 1
服务提供者
/**
* @description Hystrix熔断降级测试
* @author hero良
* @param
* @return
*/
@GetMapping("/getRibbonHystrix")
public String getRibbonHystrix(){
log.debug("************接受到请求*************");
try {
//这里的sleep是模拟让请求超时,因为RestTemplate的超时时间为2000,
//所有这里的sleep大于2000就可以
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello ,this is getRibbonHystrix";
}
使用postman来测试,看到接口并没有返回连接超时错误(注释掉启动类上的@EnableHystrix注解试一下),而是进入了我们指定的回退方法。
接下来我们停掉服务提供者再来测试,直接进入降级回退的方法。
feign结合hystrix
Feign整合断路器Hystrix相对比较简单的,Feign默认已经自带断路器Hystrix,不需要像Ribbon整合断路器Hystrix那样需要在pom添加依赖,也不需要在启动类添加注解。但是Feign自带断路器并没有打开,需要做些额外的配置。事实上,Spring Cloud默认已为Feign整合了Hystrix,只要Hystrix在项目的classpath中,Feign默认就会用断路器包裹所有方法。
继续【服务消费者Feign(Greenwich.SR2)】来学习
yml中开启断路由
#开启hystrix
feign:
hystrix:
enabled: true
新增getFeignHystrix测试熔断方法
@FeignClient(value = "provider", fallbackFactory = FeignHystrix.class)
public interface FeignClientService {
@GetMapping("/appController/getFeignHystrix")
String getFeignHystrix();
}
fallback定义类
/**
* 这个类不一定要和FeignClientService写在同一个类中
* @author hero良
* @className HystrixClientFallback
* @description
*/
public class HystrixClientFallback implements FeignClientService {
@Override
public String getFeignHystrix(String name) {
return "出错了";
}
fallbackFactory定义类,不只重写了方法,还能捕获异常
/**
* @author hero良
* @className FeignHystrix
* @description TODO
*/
@Slf4j
@Component
public class FeignHystrix implements FallbackFactory<FeignClientService> {
@Override
public FeignClientService create(Throwable throwable) {
//打印日志
log.info("fallback; throwable was: " + throwable.getMessage());
return new FeignClientService() {
@Override
public String getFeignHystrix(String name) {
return "进入hystrix的getFeignHystrix";
}
};
}
}
注: fallbackFactory相当于fallback的增强版,也就是说fallbackFactory的范围更广,到收集异常的边界处了。因此我们是可以利用fallbackFactory属性来打印fallback异常的。
为Feign禁用Hystrix
上面说过,在Spring Cloud中,只要Hystrix在项目的classpath中,Feign就会使用断路器包裹Feign客户端的所有方法。这样虽然方便,但是很多场景下并不需要该功能。
全局禁用Hystrix
只须在**pplication.yml** 中配置 **feign.hystrix.enabled=false** 即可
局部禁用
@Configuration
public class FeignDisableHystrixConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
借助Feign的自定义配置,可轻松为指定名称的Feign客户端禁用Hystrix。
在想要禁用Hystrix的@FeignClient引用该配置类即可
@FeignClient(value = "provider", /**fallback = HystrixClientFallback.class**/configuration = FeignHystrixConfiguration.class, fallbackFactory = FeignHystrix.class)
Ribbon的yml配置和Feign同样适用,这里就不贴代码了…