对限频限流的思考

ntro1 :限流的常见实现方式及常见开源限流组件有注意点

intro2 : 你真的理解了漏桶和令牌桶限流算法吗,划分/区分二者科学吗

intro2 : 你知道限流保障服务可用时也可能导致其他服务不可用吗

早先看到朋友圈分享限频限流的文章,从中有些收获,不过笔者不打算赘述,想进一步探讨下限频限流,以及限频限流使用时可能遇到的问题,同时也是对前一篇博文的回应,或许看完本文你会对Guava令牌桶算法有不一样的理解。

什么是服务限流限频?

先看 流量整形 (traffic shaping)这个概念,wikipedia解释是一种控制网络数据包传输的技术,通过控制数据速率使数据较为均匀发送。流量整形可以一定程度减少网络拥塞,并减弱突发流量带来的影响。

对于像一个操作数据库的接口、甚至google查询、微信加好友等各种系统服务来说,也需要对请求进行频率控制,这类限频的思想就来自于流量整形,漏桶和令牌桶限流算法即是源自于流量整形衍生。

对服务的频控,具体到不同的实现大同小异,如

Guava doc对限频(RateLimiter)的理解是 在一个指定的速率上分发许可(permit),当每次来请求的时候,线程会阻塞,直到获取到可用的permit,使用完这些permit之后不需要进行释放的操作

本文暂且认为限频/限流/频控/流量整形是同一个概念

限频显然关键的一点是频率,包括频率大小以及频率计算方式,但还有一点是针对谁限频,即限频的key,常见的如path(url)、ip、api、method、uid等各种维度,似乎没有文章讨论过这一点,但是重要的,下文会讨论。

其实考虑到流量整形,限频还有一点要考虑,就是对 均匀 的定义,现实请求是离散又连续均匀的,比如某类请求从每分钟维度统计是均匀的,但可能具体到每秒每0.1秒可能就不是,下文也会提及这点。

但不管如何划分,限频的本质是对一类周期性共享资源的使用。

限频的 Key 设计

不论何限频组件/算法,都要面临对限流限频资源即key的选择,key虽简单,但重要。

像静态的基于API/PATH/METHOD,或者动态uid/ip/cookie等,他们有什么不同呢?

笔者认为限频也可以按功能分为服务限频和业务限频,即针对Key的不同分为:

  • 服务限频
    像同一个接口/path等通常操作同一类资源,显然需要有频率来控制对后端资源的访问。
    这也即现代大多数网关Gateway/Service Mesh等容器/技术会提供的,可以透明实现的而无需业务方实现。

  • 业务限频
    用来防止某些人恶意刷接口的,如最简单的根据用户请求某类接口来限制频次(当然简单的可归类于服务,但如复杂需侵入业务的需求则否)。

服务限频通常根据 接口名/url(request path)这类常量限制,业务限频则是动态的uid、ip、cookie值、甚至地区等,服务限频只能起到保证整体的后端服务可用,不能防止恶意用户刷频,比如某接口限频100次/分钟,用户A访问刷频了99次,那么其他所有用户该分钟內只能访问1次了,基于uid的业务限频可以避免该类问题,但业务限频不能进行服务限频保证后端服务。

此外,上述限频可以认为默认皆同步实现,假设有的需要业务之间调用并计算才能得到次数,比如用户当天下单优惠次数,比如用户某类接口成功次数,用户每分钟调用接口A和B加起来不能超过多少次,这些需要渗入业务结果,或者通过大数据业务计算出超频的用户,推送给接口限频,对这类限频需求,笔者定义为异步业务限频,当然这存在之后滞后的问题。

像Nginx/lstio/linkerd/springcloud都提供了服务限频,而springcloud默认通过配置也即可支持基于uid等业务限频,有些大公司实现的网关也是支持服务和业务(如用户唯一标识)的,如Dubbo的限频Tpslimiter就是仅对service key即接口类限频,而SpringCloud Alibaba 通过Sentinel则支持更丰富的服务/业务限频策略。

服务或业务限频,同步或异步计算各有优劣和不足,但直接公开的服务,如果没有业务限频而只有服务限频存在刷频风险。对于实现限频的方式来说,基于接口/path的服务限频,存在热点问题,基于uid级别限频则可能耗费存储,而且是限频的接口数X每秒(分钟)內活跃用户数的量级。

限频实现的几种技术

上述限频按功能分类,这里聊聊按实现算法分类。

这里几个较可信网站的文章, 分布式服务限流实战 , 微服务接口限流的设计与思考 ,把限频实现做了分类,分为:

信号量、计数器、固定窗口、滑动窗口、漏桶算法(Leaky Bucket)、令牌桶算法(Token Bucket)、分布式限流。

以下内容假设读者对此稍微了解。

实际上,更早一篇来自网关Kong的文章 How to Design a Scalable Rate Limiting Algorithm ,也有此分类,Kong本身使用的是 计数法 。

信号量主要用来控制并发数,本文不做讨论。

原文对滑动窗口描述简略,这里补充下:假设限频每分钟100次,一般滑动窗口是将1分钟分割多个单位时间,比如分割为10个窗口,即每6秒滑动一个窗口,统计时间范围也相应后移动。次数不需要每窗口均匀的,也可以多个滑动窗口,比如同时加一个每12秒也可,这样实现每6秒不超过x次每12秒不超过y次。

固定窗口/滑动窗口是一类好理解,但计数器和窗口也是一类,都是累计次数的做法(而令牌桶/漏桶归为桶限流),滑动窗口是更细粒度的计数器/固定窗口,如上分析也是可以支持突发流量,Hystrix停更后建议的替代者resilience4j 默认 AtomicRateLimiter 即是该做法:

Our RateLimiter is not an implementation of a leaky bucket algorithm which leaks out at a constant rate. It uses a fixed window algorithm which can have burst effects at time window boundaries.

见 issue-336 。

代码略繁,AtomicRateLimiter类变量nanoTimeStart为初始化时间,在计算当前时间窗口时以此为起点(nanoTime() – nanoTimeStart&#x

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值