Dubbo中流量控制实现

流量控制

为了系统的健壮性和稳定性考虑,通常要对访问进行有效的控制,防止流量突然暴增,引发一系列服务雪崩效应。

1.单机限流

大概逻辑就是把每个请求当作一个小朋友,把最细粒度Dubbo服务中的方法当作游乐场,每个方法设计出一个标准容量参数,然后在方法开始执行业务逻辑时进行计数加 1,最后在方法结束执行业务时进行计数减 1,而这个计数加 1、计数减 1 就是我们需要的实时容量参数。

于是权限系统的流程图变成这样:

image

查询请求进入权限系统后,正常情况是先经过计数模块,计数模块进行加1操作,再去处理业务逻辑,待业务逻辑处理后返回,再进行计数减1操作。如果请求进来时,计数模块发现实时容量已满,就拒绝或等待。

计数模块核心逻辑:

使用拦截器,来进行统一计数处理。

考虑多线程情况,我们使用ConcurrentMap + AtomicInteger 来进行加减操在,以服务名 + 方法名作为key,value是当前接口使用次数,ConcurrentMap保证同一个key在并发操作时线程安全,AtomicInteger保证原子性的加减计数。

对服务提供方的改造主要有以下几点:

  1. 定义一个自定义计数器,设置为主要在提供方生效。
  2. 定义qps.enable、qps.value 两个方法级别的参数,qps.enable 参数主要表示是否开启流量控制,qps.value 参数主要表示流量的标准容量上限值
  3. 在invoke方法中先尝试获取计数资源,如果不需要限流或者已获取计数资源,则放行,否则会抛出无法获取计数资源的运行时异常。
  4. 在invoke的finally代码块中处理释放计数资源的逻辑。
  5. 在提供方的@DubboService 注解中,为方法增加了 qps.enable=true、qps.value=3 两个配置,来应用我们刚刚写的限流过滤器。

2.分布式限流

分布式是集群部署,单机模式那样限流也不是不行,只是不是最优解,我们需要考虑有少部分机器宕机的情况下总的QPS不变。

分布式我们就不能在每台机器的JVM内存中控制流量,需要把计数信息存放在第三方。这个第三方要可以缓存,可以进行计算,操作的效率也要相对较高,这里就推荐Redis。

引入Redis来保存接口访问计数之后,对之前的限流逻辑进行改造:

  1. 新增qps.type方法级别参数,主要表示处理限流的工具,有jlimit、rlimit两种,jlimit表示采用JVM限流,rlimit表示采用Redis限流,不配置的情况默认为JVM限流。
  2. 根据qps.type不同的值需要用不同的工具进行限流处理,这里采用了Map结果引入策略模式来做分发,并把策略模式应用到invoke方法的主体逻辑。
  3. 新增了一套关于Redis的计数累加、计数核减的逻辑实现。
  4. 在提供方的 @DubboService 注解中,继续为方法增加了 qps.type=redis 的配置,表示需要使用分布式限流。

以上只是实现思路,代码实现还得实操,动手实现一下才能更好的掌握。

限流在我们业务场景中的应用:

  1. 合法性限流,比如验证码攻击、恶意爬虫、恶意请求参数、利用限流有效拦截这些恶意请求。
  2. 业务限流,合理地评估功能的并发支撑能力。
  3. 网关限流,防止爆发流量对网关的冲击
  4. 连接数限流,比如利用线程池的数量来控制流量

学习来源:极客时间 《Dubbo源码剖析与实战》学习笔记 Day1

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故里学Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值