前言
前天,我们分享了guava
工具包中的一个限速组件——RateLimiter
,由于当时说后续要继续分享微服务限速的内容,所以我又专门梳理微服务限速相关的解决方案,今天抽时间来做一个梳理。
限流算法
关于限速这块的解决方案,从部署方面来说,主要分为两大块:
一块是单体应用限速,我们之前说的RateLimiter
、Semaphore
都属于此类;
另一块是针对分布式服务的限流(集群部署),这一块的解决方案也可应用于单体服务,其中绝大多数都是基于Redis
这样的缓存实现的,另外还有基于Nginx
实现的。
限流算法大致分为三类:计数器、漏桶和令牌桶。
计数器算法
计数器属于比较常用的限流算法,计数器算法的原理是通过限制在一段时间内接口被调用的次数,来控制接口流量。比如钉钉消息接口的限流,一个第三方企业一分钟只能发送3000
条消息(具体数量我记不清楚),超过3000
条的部分只能等一分钟之后发送,这样的场景就可以通过计数器算法来实现。
实现原理
实现方式也很简单,可以通过缓存来实现,我的思路是:在接口内部最开始的地方,设置调用方的计数器(key
为调用方唯一的身份信息),第一次调用时将其值设置为1
并放进缓存中,同时缓存设置过期时间,有效期内每次调用计数器+1
,时间过期,缓存会自动删除。可以把相关逻辑封装成自定义注解,搞成通用组件,这样只需要在需要限速的接口上加上对应的的注解即可,明天我们可以来实现下。
优缺点
这种算法优点是算法简单,易于实现,但是缺点也很明显:因为是时间段控制,所以流量本身并不是平衡的,很有可能一个时间段流量特别搞,而其他时间点又没有请求,这样还是会存在宕机的可能性。比如你限制接口一分钟只能调用1000
次,那很有可能在第一秒的时候直接被调用1000
次,而之后没有请求,这样你的服务很有可能在第一秒的时候就挂掉。
漏桶算法
关于漏桶算法,我们先看一张图:
上面这张图就可以很形象地说明漏桶算法的原理:首先我们需要定义一个容量固定的漏桶,因为外部请求数量是不确定的,所以我们要通过漏桶的容量来控制请求数量。同时要确定漏桶释放请求的速率(出口),我们通过出口的速率,控制接口服务被调用的频速。当漏桶中的请求数达到上限时,所有申请加入漏桶的请求都会被丢弃掉。
这样的应用场景在日常生活中也有很多,比如节假日地铁限流、景点限流等,都是这样的操作。
和前面的计数器限速,这里的限速模式就更合理,同时也更复杂,关于它的具体实现,我们最近也会有相关实例分享。
令牌桶算法
我们先看下令牌算法的原理图:
在令牌桶算法中,令牌生产算法以恒定速率不断生成新的令牌放进令牌桶中,当数量达到令牌桶的上线时,生成的新令牌会被丢弃掉。对客户端请求来说,每次请求处理前,先要从令牌桶中获取令牌,如果获取到令牌,则进出接口服务处理相关请求,否则请求被拒绝。
令牌桶和漏桶算法有点像,但是他们的实现原理是有区别的,首先在漏桶算法中是由漏桶来控制请求速率的,而在令牌桶的算法中,是由令牌生成算法控制请求速率的,令牌桶只是充当了容器。
令牌桶在日常生活中也有很多的应用,比如陕西历史博物馆每日定量发票参观。另外,在实际限流应用开发中,令牌桶也有着很典型的应用场景,比如guava
的RateLimter
就采用了令牌桶算法。
知识扩展
这里我们再分享一些常见的限流组件,后续我们会进一步剖析这些框架,今天知识简单的罗列,也算是梳理后期内容的更新方向:
Sentinel
:面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。concurrency-limits
:奈飞公司出品的限流解决方案,我也是今天才检索到,它是一款自适应限流神器,后面抽时间学下Hystrix
:这也是奈飞公司出品的一款断路器工具,之前我们有分享过Hystrix
在服务熔断方面的应用,昨天我又专门重新发了下,感兴趣的小伙伴可以去看下,后面还要再学习下这款组件在资源隔离、服务降级等方面的应用。
结语
好了,关于限流解决方案这块我们暂时先说这么多,算法这块网上资源也比较丰富,有兴趣的小伙伴可以检索更详细的内容,后续我们会逐步来分享更详细的demo
实践过程,希望能通过整个过程,对服务限流这块有更深入的认知和理解。