04基于Hystrix的服务熔断和降级
2021-01-02 本文已影响0人
攻城老狮
一 Hystrix理解
用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
二 基于RestTemplate的服务降级
2.1 某个业务方法上提供降级处理
当通过传统的restTemplate或者Ribbon的方式远程调用时,可以使用该方法实现服务降级
- 引入hystrix的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 在启动类上开启熔断器的支持
@EnableCircuitBreaker //开启熔断器
- 配置降级的服务逻辑
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
@HystrixCommand(fallbackMethod = "fallback") //配置该请求的服务降级方法
public Product getProductById(@PathVariable Long id){
Product product = restTemplate.getForObject("http://product/product/" + id, Product.class);
return product;
}
//服务降级方法逻辑
public Product fallback(Long id){
Product product = new Product();
product.setProductName("调用失败,触发熔断降级方法,id:"+id);
return product;
}
}
2.2 类全局的服务降级方法
- 注:全局的降级方法要有同一的返回类型,否则不同方法的返回值不一致会出现问题
@RestController
@RequestMapping("/order")
@DefaultProperties(defaultFallback = "fallback") //类全局的服务降级方法
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
@HystrixCommand //表示需要使用Hystrix服务
public Product getProductById(@PathVariable Long id){
Product product = restTemplate.getForObject("http://product/product/" + id, Product.class);
return product;
}
//全局服务降级方法逻辑
public Product fallback(){
Product product = new Product();
product.setProductName("调用失败,触发全局的熔断降级方法");
return product;
}
}
2.3 Hystrix超时设置
请求默认超过1秒后还未获得调用服务的数据时,Hystrix将会直接调用服务降级方法。通过配置可以改变该参数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
三 基于Feign的服务降级
Fegin默认已为Feign整合了hystrix,所以添加Feign依赖后就不用在添加hystrix
- Feign中已经内置了hystrix,但是默认是关闭,需要在yaml中配置开启hystrix的支持
feign:
hystrix: #在feign中开启hystrix熔断
enabled: true
- 配置FeignClient接口的实现类
@Component //加入Spring容器
public class ProductFeignClientFallback implements ProductFeignClient {
@Override
public Product getProductById(Long id) { //编写降级的方法逻辑
Product product = new Product();
product.setProductName("调用失败,触发Feign的熔断降级方法,id:"+id);
return product;
}
}
- 修改FeignClient接口添加hystrix熔断
//在@FeignClient注解中添加降级方法
@FeignClient(name = "product",fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
public Product getProductById(@PathVariable Long id);
}
四 Hystrix的监控平台
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
- 在启动类上添加激活仪表盘的注解
@EnableHystrixDashboard
- 开放actuator的端口
management:
endpoints:
web:
exposure:
include: '*'
- 测试访问
# 仪表盘地址
http://localhost:8002/hystrix
# 输入监控点的数据流
http://localhost:8002/actuator/hystrix.stream
五 熔断器的配置使用
熔断器有三个状态 CLOSED 、 OPEN 、 HALF_OPEN 熔断器默认关闭状态,当触发熔断后状态变更为 OPEN ,在等待到指定的时间,Hystrix会放请求检测服务是否开启,这期间熔断器会变为 HALF_OPEN 半开启状态,熔断探测服务可用则继续变更为 CLOSED 关闭熔断器。
- 修改基于restTemplate远程调用的controller中的方法,模拟除了调用id=1之外的其他id值均请求失败,抛出异常
@GetMapping("/{id}")
@HystrixCommand
public Product getProductById(@PathVariable Long id){
if (id!=1){
throw new RuntimeException("请求异常");
}
Product product = restTemplate.getForObject("http://product/product/" + id, Product.class);
return product;
}
- 熔断器的参数配置
hystrix:
command:
default:
circuitBreaker:
requestVolumeThreshold: 5 #触发熔断的最小请求次数,默认20
sleepWindowInMilliseconds: 10000 #熔断多少秒后去尝试请求
errorThresholdPercentage: 60 #触发熔断的失败请求最小占比,默认50%
六 熔断器的隔离策略
微服务使用Hystrix熔断器实现了服务的自动降级,让微服务具备自我保护的能力,提升了系统的稳定性,也较好的解决雪崩效应。其使用方式目前支持两种策略:
- 线程池隔离策略:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
- 信号量隔离策略:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判 断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请 求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发 流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服 务)