序号 | 名称 | 链接 |
1 | Spring Cloud 系列(二) 配置中心-Config | https://blog.csdn.net/qq_38130094/article/details/91456800 |
2 | Spring Cloud系列(三) Netflix Eureka注册中心 | https://blog.csdn.net/qq_38130094/article/details/93992709 |
3 | Spring Cloud 系列(四) Netflix ribbon负载均衡 | https://blog.csdn.net/qq_38130094/article/details/97240915 |
4 | Spring Cloud 系列(五) Netflix Hystrix | https://blog.csdn.net/qq_38130094/article/details/97626558 |
1. Hystrix简介
Hystrix是Netflix开源的一款承兑分布式系统的延迟和容错库,目的是用来隔离分布式服务故障。它提供了线程和信号量隔离,以减少不同服务之间的资源竞争带来的相互影响;提供了优雅的降级机制;提供了熔断机制,使得服务可以快速失败,而不是一直阻塞等待服务响应,并能从中快速恢复。Hystrix通过这些机制来阻止级联失败并保证系统弹性、可用。
2、Hystrix的作用
2.1解决的问题:
1: 限制调用分布式服务的资源使用,当某一个调用的服务出现问题不会影响其他服务调用, 通过线程隔离和信号量隔离实现;
2:Hystrix提供了优雅降级机制:超时降级、资源不足时(线程或者信号量)降级,降级后可 以配合降级接口返回托底数据;
3:Hystrix提供了熔断器实现,当失败率达到阈值自动触发降级(如因网络故障或超时造成的 失败率高),熔断器触发的快速失败会进行快速恢复;
4:提供了请求缓存和请求合并实现;
2.2 线程隔离
将Tomcat线程处理的任务转交给Hystrix内部的线程去执行,这样Tomcat线程就可以去 做其他事情。当Hystrix的线程将任务执行完成后,将执行结果返回给Tomcat线程。
1:功能:线程隔离
2:目的:管理线程资源,保证线程不会泛滥最终目的是为了保护服务节点 保障 可用性
3:场景:并发(并发量小一点的场景)的场景 都可以使用
4:走降级的会执行 fallback 方法:
作用:兜底数据/降级 从其他地方给你一个结果,比如redis
当无法获得可用核心线程数时,Hystrix直接在主线程中调用fallback()方法,执行降级逻辑。
2.3 信号量隔离
信号量隔离只是起到一个开关的作用,例如:服务X的信号量大小为10,那么同时只允许10个tomcat线程来访问服务X,其他的请求服务X,其他的请求 将被拒绝,从而达到限流保护的作用
//1 :HystrixCommand 命令所属的组的名称:默认注解方法类的名称
String groupKey() default "";//2 :HystrixCommand 命令的key值,默认值为注解方法的名称
String commandKey() default "";//3 :线程池名称,默认定义为groupKey
String threadPoolKey() default "";
//4 :fallbackMethod 定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中
String fallbackMethod() default "";
//5 :配置hystrix命令的参数
HystrixProperty[] commandProperties() default {};
//6 :commandProperties配置hystrix依赖的线程池的参数
HystrixProperty[] threadPoolProperties() default {};//5:如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。我们也可以通过此方法定义哪些需要忽略的异常
Class<? extends Throwable>[] ignoreExceptions() default {};//6:定义执行hystrix observable的命令的模式,类型详细见ObservableExecutionMode
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;//7:如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常
HystrixException[] raiseHystrixExceptions() default {};//8:定义回调方法:但是defaultFallback不能传入参数,返回参数和hystrix的命令兼容
String defaultFallback() default "";
//线程隔离:使用该方式,HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。@GetMapping("/testThread")@HystrixCommand(groupKey = "ThreadPoolGroupKey",//HystrixCommand 命令所属的组的名称:默认注解方法类的名称commandKey = "ThreadPoolCommandKey",//命令的key值,默认值为注解方法的名称threadPoolKey = "ThreadPoolKey",//线程池名称,默认定义为groupKeyfallbackMethod = "fallbackMethod",//定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中// 配置hystrix命令的参数commandProperties = {//降级处理超时时间@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1000"),//该属性用来配置HystrixCommand.run()的执行是否启用超时时间。默认为true@HystrixProperty(name="execution.timeout.enabled", value="true"),//执行的隔离策略。默认为THREAD@HystrixProperty(name="execution.isolation.strategy", value="THREAD")}, threadPoolProperties = {//核心线程数@HystrixProperty(name="coreSize",value="15")})public String testThread(){try {int m = new Random().nextInt(1200);System.out.println("Thread sleep "+m+" ms");//与Thread.sleep();是一样的只是对时间进行了封装(枚举)增加可读性TimeUnit.MILLISECONDS.sleep(m);} catch (InterruptedException e) {e.printStackTrace();}return "Thread Pool";}/*** (信号量隔离):使用该方式,HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受到信号量个数的限制。 * @return*/@GetMapping("/testSemaphore")@HystrixCommand(groupKey = "SemaphoreGroupKey",commandKey = "SemaphoreCommandKey",threadPoolKey = "SemaphoreThreadPoolKey",fallbackMethod = "fallbackMethod",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1000"),@HystrixProperty(name="execution.timeout.enabled", value="true"),@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"),@HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="3"),@HystrixProperty(name="fallback.isolation.semaphore.maxConcurrentRequests", value="1")})public String testSemaphore(){try {int m = new Random().nextInt(1200);System.out.println("Thread sleep "+m+" ms");TimeUnit.MILLISECONDS.sleep(m);} catch (InterruptedException e) {e.printStackTrace();}return "Semaphore";}
3. 两种模式对比
1:线程池隔离对每个服务,使用单独的线程池
2:信号量隔离使用信号量计数器
3:线程池隔离模式消耗资源大,大量的线程上下文切换
4:信号量隔离模式资源消耗小,只是一个计数器。
线程隔离 | 信号量隔离 | |
线程 | 与调用线程非相同线程 | 与调用线程相同(容器线程) |
开销 | 排队,调度,上下文开销 | 无线程切换,开销低 |
异步 | 支持 | 不支持 |
并发支持 | 支持(最大线程池大小) | 支持(最大信号量上限) |
四,Hystrix服务降级
当请求出现了异常,超时或者服务不可用等情况下,Hystrix可以自定义降级策略,防止直接返回空或者抛出异常。
当触发服务降级后会执行fallbackMethod();方法;
注:当抛出HystrixBadRequestException异常不会触发降级。
5.服务熔断
熔断也叫过载保护,一般指软件系统中,由于某些原因,服务出现了过载现象,为了防止造成整个系统故障,从而采用一种保护措施,如果某个服务调用慢或者有大量超时,Hystrix熔断该服务的调用,对于后续调用请求不在继续调用目标服务,直接返回,快速释放资源,如果目标服务情况好转则恢复调用。
核心:
1:在滚动时间窗口内,如果没有接收到指定最少请求个数,即使所有请求都失败,也不会打断路由
2:要满足时间\请求数\失败比例三个条件,触发熔断
3:当熔断后,fallback流程由main线程执行,一定时间后重新恢复,尝试执行主业务流程。
@GetMapping("/testCircuitBreaker")@HystrixCommand(groupKey = "CircuitBreakerGroupKey",commandKey = "CircuitBreakerCommandKey",threadPoolKey = "CircuitBreakerThreadPoolKey",fallbackMethod = "fallbackMethod",threadPoolProperties = {@HystrixProperty(name="coreSize",value="200")},commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1000"),@HystrixProperty(name="execution.timeout.enabled", value="true"),@HystrixProperty(name="circuitBreaker.enabled",value="true"),@HystrixProperty(name="metrics.rollingStats.timeInMilliseconds",value="10000"),@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="8"),@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="50"),@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="5000")})public String testCircuitBreaker(){try {int value = new Random().nextInt(10);System.out.println("Random value "+value);if(value % 3 !=0){while(true){}}else{System.out.println("secuss for "+value);}} catch (Exception e) {e.printStackTrace();}return "CircuitBreaker";}
6.请求缓存
Hystrix可将请求进行缓存,当后续有相同的请求时,直接返回缓存中的响应,从而避免直接对服务进行调用,增加服务的压力
7.请求合并
Hystrix可以在毫秒级别的请求做合并,但是感觉官方并不推荐使用(在官方的Hystrix的流程图中未给出请求合并)
hystrix工作流程图
参考:https://github.com/Netflix/Hystrix/wiki