Sentinel Dubbo 适配器看限流与熔断(实战思考篇)

我们先来看看官方提供的 Dubbo 适配器的核心实现:

SentinelDubboConsumerFilter#invoke

在这里插入图片描述

消费端这边使用到了两个资源名称,一个是接口级别,例如 com.demo.service.UserService,另外一是方法级别,例如 com.demo.servcie.UserServce#findUser(Ljava.lang.String)。

定义了两个资源后,Sentinel 会使用滑动窗口机制,为上述两个资源收集实时的调用信息,为后续的限流、熔断提供数据依据。

限流规则是依附于具体某一个项目的,例如如下图所示:

在这里插入图片描述限流、熔断都是根据资源级别,如果需要对消费端的调用进行限流的话,就需要为这两个资源配置对应的限流规则,如果不配置则默认通过,表示不限流。

1.1 服务调用端(消费方)是否需要配置限流规则

在 dubbo 的服务调用场景中,在消费端设置限流的规则的话,这个调用链是针对整个集群所有服务提供者的,例如当前集群中包含3个服务提供者,每个服务提供者用于1000tps的服务能力,那消费端的限流,应该配置的限流TPS应该为3000tps,如果设置为1000tps,则无法完整的利用服务端的能力,基于这样的情况,通常消费端无需配置限流规则。

那是不是说消费端就没必要配置限流规则呢?其实也不是,有如下这个场景,例如调用第三方外部的计费类服务接口,对方通常为特定的账户等级设置对应的TPS上限,如果超过该调用频率就会抛出错误,这种情况还是需要设置限流规则,确保消费端以不超过要求进行调用,避免业务异常。

1.2 服务调用端(消费方)是否需要配置熔断

引入熔断的目的是避免服务端单节点响应慢而导致这个服务不稳定,例如示例中有3个服务提供者,如果192.168.1.3的服务提供者由于触发了BUG导致响应时间大大增加,导致发往该服务提供者的请求大概率超时,在这样的情况下希望在接下来某段时间内消费方发往这这个服务提供者的请求快速熔断降级,返回错误,由客户端重试其他服务提供者。其实现效果如下:

在这里插入图片描述

当前的 Sentinel 默认是否能满足上述的需求呢?

我们以 Sentinel 基于异常比例熔断策略来进行阐述,如果资源的调用异常比例超过一定值是会触发降级熔断,抛出 DegradeException 异常。

由于总共只有三个服务提供者,其中发往192.168.1.3的请求大概率会由于超时失败,则异常比例会超过设置的熔断降级规则,会触发降级,造成的效果是整个服务调用都会发送熔断降级,即调用192.168.1.4,5两个请求都不会被熔断,造成整个服务调用不可用,与期望不一致。即还是会出现一个节点的不稳定而导致整个服务不稳定的情况。

其造成的根本原因是因为其资源的定义并没有包含服务提供者的信息,改进的初步方案:

  1. 在过滤器中再定义一个资源,加上服务提供的IP与端口号,例如 SphU.entry(“com.d.s.UserService@ip:port”),对单个服务提供者进行单独收集调用信息,并且需要提供一可配置的项,用来标记该类型的资源在做熔断判断可使用某一个资源的配置,例如配置为 com.d.s.UserService,表示用这个配置规则来判断熔断。

  2. 在熔断规则判断的时候,该资源使用被引用资源的熔断规则进行判断。

最后来解答一下,熔断规则通常只需要配置在调用方即可。

2、从服务来看限流与熔断


由于服务端看限流与熔断就比较简单,因为服务端与客户端存在一个非常大的区别是客户端存在负载均衡机制,一个消费端对于同一资源来说,会调用多个服务提供者,而服务提供者对于一个资源来就是其自身,故限流规则,熔断规则都是针对个体,其复杂度降低。

为了知识体系的完备性,我们来看一下 Sentinel Dubbo 在服务端的适配器的实现。

SentinelDubboProviderFilter#invoke

在这里插入图片描述

这里有二个关键点:

  1. 使用了 ContextUtil 的 entry 方法,定义本次调用的上下文环境名称为:resourceName,默认为接口名与方法名、参数列表,例如 com.d.s.UserServce#findUser(Ljava.lang.String),源头为消费端的应用名称。

  2. 定义两个资源,这里与消费端相同,就不做重复解读。

关于这个 ContextUtil 的 entry 方法非常关键,因为 Sentinel 中数据节点的统计是以 ContextName 为维度的。

例如想对一个应用所有的操作 redis 操作统一设置为一个资源名,redisOpsResource,即想控制该应用整体的 redis 操作 tps,其场景如下:

在这里插入图片描述

例如初衷设计为 opsReisTotal 的整个 tps 为 500,例如从UserService#findser链路的访问 redis tps 为 400,而从 Order#createOrder 链路访问 redis tps 为 400,此时 redis 的整体 tps 已经达到了 800 tps,但你会发现并不会触发限流,因为对资源 RredisOpResource 的调用信息统计是以 context name 为维度的,不同的 context name 互不影响,从而无法做到全局控制。

3、总结


本文结合 Sentinel 官方对于 Dubbo 提供的适配器并加以理解,提出了如下观点,欢迎大家留言探讨,相互交流,共同进步。

惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

image.png

image.png

备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

[外链图片转存中…(img-0fbxnEUv-1714445217875)]

[外链图片转存中…(img-RY6f8mW7-1714445217875)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值