目录
4.3.1、Hystrix 执行调用链的流程图(网上的图片)
4.3.2、spring boot 使用 Hystrix 的简单实用
4、熔断
4.1、熔断的基本认识
4.1.1、熔断的场景分析
1、在大型分布式架构中,一个用户请求,可能是如下图所示
2、如果这个时候一个服务出现异常:
- 服务提供者不可用
- 重试导致的流量过大
- 服务调用者使得同步调用,产生大量的等待现场占用资源,一旦现场资源被耗尽,调用者提供的服务也会变成不可用状态导致请求堆积,从而出现整个服务不可用的问题。
3、复杂的分布式架构的应用程序有很多依赖,都会不可避免的出现服务故障等问题。高并发的依赖失败时,如果没有采取措施,当前应用服务就有被拖垮的风险。
4.1.2、解决方案就是引入熔断机制
当下游服务因为访问压力过大或者其他原因导致影响变慢的时候,上游服务为了保护自己以及系统整体的可用性,可以暂时切断对下游服务的调用。
熔断的理解来源于生活:比如 电路“跳闸”,电压超负荷时会自动跳闸,防止电路烧毁和触电。比如股市熔断等。
4.1.3、断路器的熔断
- 失败比例(circuitBreaker.errorThresholdPercentage)
失败率达到多少百分比后触发熔断,默认:50%
- 熔断响应时间(circuitBreaker.sleepWindowInMilliseconds)
访问超时,会触发半打开状态,熔断大多数,放少量进行尝试,默认:5s
- 熔断异常数(circuitBreaker.requestVolumeThreshold)
访问异常数达到一定数量的时候触发异常,默认:20
- 直接触发熔断(circuitBreaker.forceOpen)(circuitBreaker.forceClosed)
一些秒杀场景,或者知道服务不可用的时候直接选择熔断,不让访问服务,默认 false
4.1.4、熔断的自定义实现
1、分析原理图
2、通过AOP +注解实现简单的熔断
private final String POINT_CUT_2 = "execution(* com.ben.springcloud.loadbalanceserver.controller.ServerController.advancedSay2(..) && @annotation(circuitBreaker)";
@Around(POINT_CUT_2)
public Object advancedSay2InTimeout(ProceedingJoinPoint point, CircuitBreaker circuitBreaker) throws Throwable {
long timeout = circuitBreaker.timeout();
Future<Object> future = executorService.submit(() -> {
Object returnValue = null;
try {
returnValue = point.proceed(point.getArgs());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return returnValue;
});
Object returnValue = null;
try{
returnValue = future.get(timeout, TimeUnit.MICROSECONDS);
}catch (TimeoutException e){
future.cancel(true);
returnValue = errorContent("");
}
return returnValue;
}
//通过反射获取timeout
long timeout = -1;
if(point instanceof MethodInvocationProceedingJoinPoint){
MethodInvocationProceedingJoinPoint methodPoint = (MethodInvocationProceedingJoinPoint)point;
MethodSignature signature = (MethodSignature)methodPoint.getSignatrue();
Method method = signatrue.getMethod();
CircuitBreader circuitBreader = mothod.getAnnotation(CircuitBreader.class);
timeout = circuitBreader.timeout();
}
4.2、限流的基本认识
4.2.1、场景分析
十一黄金周,旅游景点都是人满为患,所以景点为了避免出现事故,会采取限流措施。
在软件场景里,一个秒杀场景,同一时间点,大家都访问抢购请求,并发峰值达到高点,服务器是会出现事故。所以设置一个最大的流量限制,如果超过这个流量,我们就拒绝提供服务,从而使得我们的服务不会挂掉。
当然,限流虽然可以保护系统不会挂掉,但对于限流的用户来说,他们则会访问不了服务(也就是服务降低)所以限流是一个有损的解决方案,但是相比于全部服务都挂掉,已经是一个最好的解决方案了。
4.2.2、限流的常用算法
1、滑动窗口
发送和接受都维护一个数据帧的序列,这个序列就是窗口。发送方的窗口大小由接收方确定,目的在于控制发送速度,以免接收方的缓存不够大,而导致溢出,同