一、概念
1、雪崩效应
服务链中的某一个服务不可用,导致一些列的服务不可用,最终导致服务逻辑崩溃。
造成原因:服务提供者不可用、重试加大流量、服务调用者不可用。
2、解决雪崩效应
降级:超时降级、资源不足时降级,降级后可配合降级接口放回兜底数据。实现一个fallback方法,当服务提供者出现异常可以使用此方法返回fallback方法返回的值。
熔断:当失败率达到阈值自动触发降级,熔断就是具有特定条件的降级,当出现熔断时在设定时间内容就不再请求。
请求缓存:服务A调用服务B,如果在A中添加请求缓存,第一次请求后把数据做缓存,此后调用B就直接从缓存中获取。
请求合并:当服务A调用服务B时,设定在5毫秒内所有请求合并到一起,对于服务B的负载就会大大减少,解决了对于服务B负载激增的问题。
隔离:隔离分为线程池隔离和信号量隔离。通过判断线程池或信号量是否已满,超出容量的请求直接降级,从而达到限流的作用。
二、降级
1、概念
降级是指当请求超时、资源不足的情况发生时进行服务降级处理,不调用真实服务逻辑,而是使用快速失败方式直接返回一个兜底数据,保证数据链的完整。
2、步骤
导入依赖
<!-- hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类打注解@EnableCircuitBreaker
@SpringBootApplication
@EnableEurekaClient
//开启Fegin
@EnableFeignClients
//开启hystrix
@EnableCircuitBreaker
public class OrderServerApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication.class,args);
}
}
在需要降级的方法上注解@HystrixCommand(fallbackMethod = "降级方法名")、并编写对于降级方法。
@HystrixCommand(fallbackMethod = "method")
@GetMapping("/getOrder")
public String getOrder(){
String name = userFegin.getUserName();
if(null == name && "".equals(name)){
return "没有获取到用户名";
}
return name+" 订单";
}
//降级方法返回值和参数要与原方法一致
public String method(){
return "降级";
}
三、熔断
1、概念
当一定时间内,异常请求比例达到阈值,启动熔断,启动后会停止调用具体服务逻辑,通过fallback快速放回兜底数据,保证服务链完整。
熔断有自动回复机制,如:当熔断器启动后,每隔5秒尝试将新的请求发送给Application service,如果服务可正常执行并返回结果,则关闭容断器,服务恢复。
降级是出错了返回兜底数据,而熔断是出错后开启熔断将会在一定时间内不在访问服务。
2、实例
在降级的基础上添加属性配置。在@HystrixCommand(fallbackMethod = "降级方法名")这个注解添加条件。
@HystrixCommand(fallbackMethod = "method",commandProperties = {
//20秒内
@HystrixProperty(name= HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS,value = "20"),
//请求6个
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "6"),
//有30%出错
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "30")
})
@GetMapping("/getOrder")
public String getOrder(){
//模拟降级
// throw new RuntimeException();
String name = userFegin.getUserName();
if(null == name && "".equals(name)){
return "没有获取到用户名";
}
return name+" 订单";
}
四、请求合并
1、使用场合
服务远程调用在高并发的情况下,通信次数的增加会导致总的通信时间增加,而线程池的资源也是有限的,高并发的环境下会导致大量的线程处于等待状态,进而导致响应延迟。
2、缺点
设置请求合并后,本来一个请求1ms就能完成,但是现在必须等10ms,时间到后会将10ms内所有请求一次发送。
3、注解介绍
请求合并的注解@HystrixCollapser()
五、线程池隔离
1、目的
某个线程池都被占用也不影响其他线程。
2、优缺点
优点:任何一个服务都会被隔离在自己的线程池内,即使自己的线程池满了。
当依赖的服务重新启动时,可以通过清理线程池,瞬间恢复服务的调用。
每个都是独立的线程,一定程度解决高并发问题。
线程池中的线程个数有限制,解决限流问题。
缺点:增加CPU开销。
每个操作都是独立的线程,就有排队、调度和上下文切换等问题。
3、配置方式
通过方法注解@HystrixCommand()
六、信号量隔离
1、信号量概念
java.util.concurrent.Semaphore用来控制可同时并发的线程数。通过构造方法指定内部虚拟许可的数量。每次线程执行操作时先通过acquire方法获得许可,直到其它线程释放许可。
如果采用信号量隔离技术,每接收一个请求,都是服务自身线程去直接调用依赖服务,信号量就相当于一道关卡,每个线程通过关卡后,信号量减一,当为0时不允许线程通过,直接调用fallback逻辑。
2、实现方式
通过方法注解@HystrixCommand()