雪崩-隔离-熔断-降级-限流-sentinel,hystrix

概念介绍:雪崩,隔离,熔断,降级,限流
什么是服务雪崩?
比如订单业务有接口请求支付业务,但是这个时候支付业务有一个接口报错了,或者链接不上,每一个请求来一个阻塞一个,经过一段时间达到了服务器tomcat的最大工作线程数,后面订单业务在请求支付业务就发现一直等待,感觉支付整个模块挂掉了,这个时候,订单业务不断请求到支付的线程也达到了订单服务的最大上限,订单业务也给阻塞了,这个时候如果有其他服务调用订单业务,会发现调不通,达到最大线程之后也给阻塞了,以此类推,由于底层的一个问题,到最后导致所有与之相关的服务都阻塞了,就是服务雪崩.

这里讲下tomcat作为一个服务器,工作线程在100-500之间,4核的机器,大概支持200-300个线程,每一个请求进来都会使用一个线程来处理请求

隔离就是为了解决雪崩的一种方法:比如订单业务调用支付业务的,我们就专门设置出20个线程用来请求支付业务,这样哪怕支付业务出问题,也就阻塞了订单业务20个线程,不影响订单业务其他的业务.

熔断是什么意思呢?
比如订单业务请求支付业务已经有20个线程都阻塞了,那么对于后面进来的请求,订单业务直接返回这里有异常.
开启熔断开关之后一段时间内,会直接返回异常
1.熔断关闭状态(Closed)
服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制。

2.熔断开启状态(Open)
在固定时间窗口内(Hystrix默认是10秒),接口调用出错比率达到一个阈值(Hystrix默认为50%),会进入熔断开启状态。进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法。

3.半熔断状态(Half-Open)
在进入熔断开启状态一段时间之后(Hystrix默认是5秒),熔断器会进入半熔断状态。所谓半熔断就是尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断关闭状态。


降级是什么意思呢?
在服务器压力剧增的情况或者下游服务异常,根据当前的业务情况和流量对一些服务和页面做有策略的降级,以此释放服务器的资源,保证核心业务的正常.
一般有几种降级方式:
服务接口拒绝服务:直接返回预设的页面,比如在DNS或者nginx上的
页面拒绝服务:提示服务繁忙,跳转到nginx的静态页面
延迟持久化:服务能正常访问,订单业务直接返回提交成功或者变更成功,提示稍晚会看到结果,订单业务把请求到支付业务的消息记录到本地磁盘,等熔断开关关闭了,阻塞的线程也开始工作了,再把本地的记录交给支付业务进行处理
随机拒绝服务:服务器随机拒绝服务,让客户重试.

限流是什么意思呢?
就是比如订单服务支持每秒处理200个请求,但是支付每秒只能处理100个请求,那么超过的请求,就不做处理,每次值放100个请求过去,其他的进入等待队列中.目前常见的限流算法有:令牌桶,漏桶,计数器

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 当桶满时,新添加的令牌被丢弃或拒绝。

漏桶,就是我不管你一次进来多少请求,我以稳定的速率处理请求,如果超出了最大的容量,请求会被丢弃

计数器算法:
两种方式
1.使用AomicInteger来进行统计当前正在并发执行的次数,如果超过域值就简单粗暴的直接响应给用户,说明系统繁忙,请稍后再试或其它跟业务相关的信息。
private static AtomicInteger count = new AtomicInteger(0);

public static void test() {
if (count.get() >= 5) {
System.out.println("请求过多,请稍后在试!"+System.currentTimeMillis()/1000);
} else {
count.incrementAndGet();
try {
//处理核心逻辑
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
count.decrementAndGet();
}
}
}
2.使用Semaphore信号量来控制并发执行的次数,如果超过域值信号量,则进入阻塞队列中排队等待获取信号量进行执行。如果阻塞队列中排队的请求过多超出系统处理能力,则可以在拒绝请求。
private static Semaphore semphore = new Semaphore(10);

public static void test() {
if(semphore.getQueueLength()>100){
System.out.println("当前等待排队的请求数大于100,请稍候再试...");
}
try {
semphore.acquire();
// 处理核心逻辑
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semphore.release();
}
}

 

目前市面上常用的有spring cloud netflix 整合的hystrix和spring cloud alibaba 整合的sentinel
hystrix在熔断降级设计上,通过线程池隔离的方式,来对依赖(对应sentinel中的资源)进行了隔离,这样做的好处是资源与资源之间进行了彻底的隔离,缺点是出了增加线程切换的成本,还需预先给各个资源做线程池大小的分配
sentinel对这个问题采取两种手段
第一种通过并发数进行限制:对请求一个资源的并发线程数进行设置,如果响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积.当达到一定数量之后,对该资源的新请求就会被拒绝,堆积的线程完成任务之后才开始继续接受请求.
第二种通过资源的响应时间进行降级:当依赖的资源出现响应时间过长之后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才恢复.

Sentinel 的主要工作机制如下:
对主流框架提供适配或者显示的API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel提供开放的接口,方便您定义及改变规则。
Sentinel提供实时的监控系统,方便您快速了解目前系统的状态。

posted @ 2021-01-14 18:13  CodingChangeTheWorld  阅读(472)  评论(0编辑  收藏  举报