java实现超时熔断 java 熔断_服务集群

什么是熔断,什么是降级,熔断与降级是同一个意思吗?

笔者去年写的一篇《我所经历的一次Dubbo服务雪崩,这是一个漫长的故事》讲诉的是笔者排查与解决线上服务雪崩的故事,可以用一张图片描述整个事件。


java实现超时熔断 java 熔断_java实现超时熔断_02

如上图所示,服务A接收客户端请求,服务B提供给内部服务调用,每个服务部署的节点数至少两个。

在事发之前的近一周,服务

B

都一直运行正常,而事发的那晚请求量突增一倍,显然,此次事故与请求突增脱不了干系。因突增请求导致服务

B

高负荷运转,超出临界点的请求最后超出设定的接口超时时间,再由于服务

B

的一个隐藏性能问题导致内存消耗殆尽,进程开始频繁

GC

,但服务

A

还是不断地往服务

B

发送请求,导致服务

B

奔溃,服务

B

的奔溃又直接导致服务

A

崩溃,这种产生连带效应的服务奔溃称为服务雪崩。

分析完事故后,我们再来说说熔断降级。熔断与降级不是一个概念,但熔断却伴随着降级,熔断在满足某种降级策略时触发,所以熔断是降级方式的一种,熔断是自动降级的一种实现。

做电商项目的朋友可能接触最多的就是服务降级,一般我们在搞大促之前,都会通过开关方式将一些无关紧要的业务接口变成“不可用”。例如,通过配置中心或者通过Redis控制服务降级开关,当开关打开时,需要降级的接口直接响应一个表达当前服务降级的状态码给调用端。

控制服务降级开关的方式可以是人工,也可以是定时任务在某个时段开启、某个时段关闭,这种降级方式称为开关降级。开关降级与熔断降级都属于服务降级,服务降级的目的都是确保服务以稳定状态运行,防止服务奔溃的出现。

熔断指的是,当服务A的下游服务B突然变得不可用或者不稳定时,服务A可以自动切断与服务B的交互从而保证自己可用,就像保险丝一样,当电流异常升高到一定高度的时候,保险丝切断电流,这就是熔断。

熔断需要条件触发,而这个触发条件就是我们设置的一种服务降级策略,例如,在每秒请求异常数超过多少时触发熔断、在每秒请求异常错误率超过多少时触发熔断、在每秒请求平均耗时超过多少时触发熔断。

熔断是切断请求,快速失败,在触发熔断时让服务A不再访问服务B,但这不是永久的。以某个资源(接口)采取平均每秒请求异常数超出5个时熔断的策略为例,假设当前时间窗口(时间单位)已经发生5个异常,那么当前时间窗口内的后续请求都会被熔断,但下一个时间窗口又会重新计算异常总数。

服务降级除以上说到的开关降级和熔断降级外,还有一种常用的服务降级方式:限流降级。

限流是限制单位时间内处理的请求数,拦截请求做降级处理。

例如,通过压测得到单个服务节点单位时间内所能处理的最大请求数,使用该数值做为降级条件,当并发处理的请求数超过这个数值时,超出的部分

请求降级处理。

常见限流规则如按

QPS

限流、按最大并行使用线程数限流。

限流还可限制单位时间内发往一个服务集群的请求总数不能超过多少,即对一个服务集群限流,不过集群限流方式实现上比单机难度稍大,需要统计单位时间内集群处理的请求数据信息。通常集群限流用于网关层,由网关限制请求某个服务集群的请求数。

限流可以在服务消费端(

Client
或者
Consumer
)限流,也可在服务提供端(
Service
或者
Provider
)

限流,典型的在消费端限流如API网关。

熔断在服务消费端实现,当请求异常(异常数过大、异常率过高、耗时过多)达到降级条件时,自动切断当前时间窗口的后续请求,直接快速失败,不去访问服务提供者。

以上是个人理解,仅供参考!如有错误,欢迎留言纠正。