一. Hystrix介绍
-
官方文档
-
什么是Hystrix?
-
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
-
-
Hystrix特性
-
请求熔断:
-
快照时间窗:统计的时间范围就是快照时间窗,默认为最近的10秒
-
请求总数下限:在快照时间窗内,必须满足请求总数下限才有资格根据熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用此时不足20次,即时所有的请求都超时或其他原因失败,断路器都不会打开。
-
错误百分比下限:失败超一定比例(默认50%),断路器切换到OPEN。保持一段时间(默认5秒)之后,切换到HALF-OPEN
-
-
服务降级:当请求后台相应失败,通过实现的fallback方法,给调用者返回缓存中的值或者默认值
-
依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离。通过分配线程,保证服务不会被卡住,在使用了@HystrixCommand来将某个函数包装成了Hystrix命令,这里除了定义服务降级之外,Hystrix框架就会自动的为这个函数实现调用的隔离。
-
请求缓存:请求过一次,放入缓存,同样的请求从缓存中给他返回
-
请求合并:( HystrixCollapser)我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。
-
二. 使用Hystrix
-
在pom.xml中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
-
启动类添加注解
-
添加@EnableCircuitBreaker或@EnableHystrix,来开启Hystrix使用
-
注:当注解越来越多的时候还可以通过使用Spring Cloud应用中的@SpringCloudApplication注解来修饰应用主类
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {}
-
在Controller中添加一个“fallback”的方法,并在需要做降级的方法上添加注解@HystrixCommand
@RestController
@RequestMapping("api/v1/order")
public class OrderController {
@Autowired
private ProductOrderService productOrderService;
@RequestMapping("save")
@HystrixCommand(fallbackMethod = "saveOrderFail")
public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){
Map<String, Object> data = new HashMap<>();
data.put("code", 0);
data.put("data", productOrderService.save(userId, productId));
return data;
}
//注意,方法签名一定要要和api方法一致
private Object saveOrderFail(int userId, int productId){
Map<String, Object> msg = new HashMap<>();
msg.put("code", -1);
msg.put("msg", "抢购人数太多,您被挤出来了,稍等重试");
return msg;
}
}
三. 在Fegin上使用Hystrix
-
在application.yml中开启feign支持hystrix(新版本必须加)
feign:
hystrix:
enabled: true
-
创建XxxClientFallBack实现XxxClient接口(FeginClient),复写需要做降级处理的方法
@Component
public class ProductClientFallback implements ProductClient {
@Override
public String findById(int id) {
System.out.println("feign 调用product-service findbyid 异常");
return null;
}
}
-
将XxxClient(FeginClient)接口类的注解修改
-
@FeignClient(name="xxx", fallback=xxx.class ), class需要实现当前FeignClient的类
-
@FeignClient(name = "product-service", fallback = ProductClientFallback.class)
//@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/api/v1/product/find")
String findById(@RequestParam(value = "id") int id);
}