Hystrix主要能为我们解决哪些问题
- 服务降级:当一个服务出现宕机、超时、资源不足或者出现异常时,可以执行一个降级的方法,调用降级业务逻辑,返回一个托底的数据/响应。
- 线程隔离:提供了一个Hystrix的线程池,以及信号量机制,帮助我们管理容器的线程池,或者实现与容器的线程池隔离。
- 熔断:当一个请求的失败率,达到一定阈值的时候,启动熔断机制。
- 请求缓存:缓存当前请求的信息,下次调用直接返回。
- 在customer里面导入pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在启动类上加入这个注解 @EnableCircuitBreaker
在contrller中针对一个类进行降级
@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack")
public Customer findById(@PathVariable Integer id){
int i = 1/0;
return searchClient.findById(id);
}
// findById的降级方法 方法的描述要和接口一致
public Customer findByIdFallBack(Integer id){
return new Customer(-1,"",0);
}
/customer/{id}是我方法请求的路径
findByIdFallBack 要和西安的降级方法名字
上面的方法和降级的方法是重写关系 如果成功返回return searchClient.findById(id);
失败则调用降级的方法
在接口上增加@HystrixCommand(fallbackMethod = “findByIdFallBack”)注解
线程隔离
1.线程隔离策略
- Hystrix的线程池(默认):接收用户请求采用容器(tomcat)的线程池,执行业务代码时,调用其他服务时候采用Hystix的线程池。
- 信号量:使用还是容器的线程池,他是使用信号量机制,帮我们管理容器的线程池。
- 接口添加了@HystrixCommand注解,默认就是用了线程池的线程隔离策略。
2.配置信息
- 线程隔离策略:hystrix.command.default.execution.isolation.strategy THREAD、信号量SEMAPHORE
- 指定超时时间:配置了超时时间,调用其他服务或者执行业务代码总耗时超过该数值,则调用服务降级方法。
- 默认配置:1000ms,该配置只针对线程池策略可用。
- hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 1000
- 是否启用超时时间:hystrix.command.default.execution.timeout.enabled true
- 超时之后是否中断:hystrix.command.default.execution.isolation.thread.interruptOnTimeout true
- 取消之后是否中断:hystrix.command.default.execution.isolation.thread.interruptOnCancel false(具体可以看GitHub官方文档)
代码实现部分
@GetMapping("/inset")
@HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy",value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public int searcheById(@RequestBody Goods goods) throws InterruptedException {
System.out.println("当前线程:"+Thread.currentThread().getName());
Thread.sleep(5000);
Goods goods1 = new Goods("榴莲往返",30,"斤","500",new Date(),new Date(),1);
return serchClient2.insent(goods1);
}
public int findByIdFallBack1(Goods goods){
return 0;
}
如果成功 创建对象 失败返回0 休眠了5秒 他默认3面肯定超时
断路器
断路器的工作原理
在调用指定服务时,如果说这个服务的失败率在指定的时间范围内(时间条件10秒)达到你输入的一个阈值,将断路器从closed状态,转变为open状态,指定服务时无法被访问的,如果你访问就直接走fallback方法,在一定的时间内,open状态会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务再次转变为open状态,会再次循环到half open,直到断路器回到一个closed状态。
2.配置断路器的监控界面
导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
在启动类中添加注解
@@EnableHystrixDashboard//启用Hystrix图形化监控界面 豪猪页面
3.配置一个Servlet路径,指定上Hystrix的Servlet
@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}
//------------------------------------------------------------
在启动类上,添加扫描Servlet的注解
@ServletComponentScan(“com.qf.servlet”)
这个包是你定义@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}的包
访问:http://localhost:8080/hystrix.stream 进入豪猪页面
当出错会从cloued变为open你访问降级fallback方法时会从open变为half open状态在判断服务请求是否有错 有错继续open 位错变为cloued状态
断路器的配置
- 是否启用断路器(开关):hystrix.command.default.circuitBreaker.enabled true
- -失败阈值:hystrix.command.default.circuitBreaker.requestVolumeThreshold 20 意思就是每10秒钟之内失败的请求数达到20个,那么断路器就会打开(open状态)
- 断路器open之后,所少毫秒达到半开状态,也就是多少毫秒之内是拒绝请求的:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 5000 默认是5秒
- 请求总数达到多少时,断路器断开:hystrix.command.default.circuitBreaker.errorThresholdPercentage 50%
- 强制让服务拒绝请求:hystrix.command.default.circuitBreaker.forceOpen false
- 强制让服务接收请求:hystrix.command.default.circuitBreaker.forceClosed false
注意:forceOpen 和 forceClosed 互斥,同时只能配置一个为true
代码:
@GetMapping("/allbyid/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//断路器打开状态
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "3"),
//1s请求3次便从cloued状态转为open状态
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "70"),
//失败率达到70%
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")//断路器open状态后 5秒拒绝请求
})
public String searcheById(@PathVariable Integer id) throws InterruptedException {
System.out.println("当前线程:"+Thread.currentThread().getName());
if(id==0){
int i=0/0;
}
return serchClient2.querybyid(id).toString();
}
public String findByIdFallBack(Integer id){
return "商品已经下架";
}
当我访问/allbyid/{id}时 成功正常显示数据 失败 return "商品已经下架"