Hystrix实现了 超时机制和断路器模式。
Hystrix是Netflix开源的一个类库,用于隔离远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。主要有以下几点功能:
- 为系统提供保护机制。在依赖的服务出现高延迟或失败时,为系统提供保护和控制。
- 防止雪崩。
- 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中运行。
- 跳闸机制:当某服务失败率达到一定的阈值时,Hystrix可以自动跳闸,停止请求该服务一段时间。
- 资源隔离:Hystrix为每个请求都的依赖都维护了一个小型线程池,如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。防止级联失败。
- 快速失败:Fail Fast。同时能快速恢复。侧重点是:(不去真正的请求服务,发生异常再返回),而是直接失败。
- 监控:Hystrix可以实时监控运行指标和配置的变化,提供近实时的监控、报警、运维控制。
- 回退机制:fallback,当请求失败、超时、被拒绝,或当断路器被打开时,执行回退逻辑。回退逻辑我们自定义,提供优雅的服务降级。
- 自我修复:断路器打开一段时间后,会自动进入“半开”状态,可以进行打开,关闭,半开状态的转换。
隔离
将请求封装在HystrixCommand中,然后这些请求在一个独立的线程中执行,每个依赖服务维护一个小的线程池(或信号量),在调用失败或超时的情况下可以断开依赖调用或者返回指定逻辑
熔断
当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)
降级
服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值
hystrix容错流程
1.每个请求都会封装到 HystrixCommand 中
2.请求会以同步或异步的方式进行调用(execure(),queue())
3.判断熔断器是否打开,如果打开,它会直接跳转到 8 ,进行降级
4.判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8
5.如果前面没有错误,就调用 run 方法,运行依赖逻辑
5.运行方法可能会超时,超时后从 5a 到 8,进行降级
6.运行过程中如果发生异常,会从 6b 到 8,进行降级
6.运行正常会进入 6a,正常返回回去,同时把错误或正常调用结果告诉 7 (Calculate Circuit Health)
7.Calculate Circuit Health它是 Hystrix 的大脑,是否进行熔断是它通过错误和成功调用次数计算出来的
8.降级方法(8a没有实现降级、8b实现降级且成功运行、8c实现降级方法,但是出现异常)
8a.没有实现降级方法,直接返回异常信息回去
8b.实现降级方法,且降级方法运行成功,则返回降级后的默认信息回去
8c.实现降级方法,但是降级也可能出现异常,则返回异常信息回去
hystrix独立使用
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
public class HystrixTest extends HystrixCommand {
protected HystrixTest(HystrixCommandGroupKey group) {
super(group);
}
public static void main(String[] args) {
/**
* execute():以同步阻塞方式执行run()。以demo为例,调用execute()后,
* hystrix先创建一个新线程运行run(),
* 接着调用程序要在execute()调用处一直阻塞着,直到run()运行完成
*/
// System.out.println("result:" + hystrixTest.execute());
/**
* queue():以异步非阻塞方式执行run()。以demo为例,
* 一调用queue()就直接返回一个Future对象,
* 同时hystrix创建一个新线程运行run(),
* 调用程序通过Future.get()拿到run()的返回结果,
* 而Future.get()是阻塞执行的
*/
Future<String> futureResult = new HystrixTest(HystrixCommandGroupKey.Factory.asKey("ext")).queue();
String result = "";
try {
result = futureResult.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("程序结果:"+result);
}
@Override
protected Object run() throws Exception {
// TODO Auto-generated method stub
System.out.println("执行正常逻辑");
int i = 1/0;
return "ok";
}
@Override
protected Object getFallback() {
return "getFallbackgetFallback";
}
}
整合Resttemplate
Service
@HystrixCommand(fallbackMethod = "back")
public String alive() {
// 自动处理URL
RestTemplate restTemplate = new RestTemplate();
String url ="http://user-provider/hello";
String object = restTemplate.getForObject(url, String.class);
return object;
}
public String back() {
return "请求失败处理";
}
启动类
需要加上配置,feign不需要启动类加上这个,要在配置文件打开
@EnableCircuitBreaker
整合Feign
接口
@FeignClient(name = "user-provider",fallback = HelloBack.class)
public interface ConsumerApi {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello();
}
实现
import org.springframework.stereotype.Component;
@Component
public class HelloBack implements ConsumerApi{
@Override
public String alive() {
return "处理如果失败会到这里来处理逻辑";
}
}
配置
feign.hystrix.enabled=true
开启dashboard
启动类
@EnableHystrixDashboard
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
健康上报
http://localhost:8080/actuator/hystrix.stream
图形化
http://localhost:8080/hystrix
信号量隔离与线程隔离
默认情况下hystrix使用线程池控制请求隔离
线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。
信号量隔离主要维护的是Tomcat的线程,不需要内部线程池,更加轻量级。
配置
hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
thread 通过线程数量来限制并发请求数,可以提供额外的保护,但有一定的延迟。一般用于网络调用
semaphore 通过semaphore count来限制并发请求数,适用于无网络的高并发请求
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。
semaphore应该占整个容器(tomcat)的线程池的一小部分。
Feign下配置
hystrix.command.default.execution.isolation.strategy=SEMAPHORE