# 《Seckill秒杀系统》第83章:基于QPS实现单机API限流

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:理解API限流的原理,从源码级别重点掌握本地API限流的核心技术与落地方案,并能够将其灵活应用到自身实际项目中。

大家好,我是冰河~~

在秒杀系统中,使用Sentinel实现分布式限流是不可或缺的。但是,在真正的秒杀场景下,在微服务中进行本地限流也是需要的,本地限流可以对分布式限流进行有效的补充。哪怕分布式限流出现故障,我们还有本地限流进行兜底。

# 一、前言

Sentinel是分布式限流神器,经受住了阿里巴巴双11大促高并发流量的考验。在秒杀系统中,集成了Sentinel分布式限流,但是我们仔细想想,秒杀系统集成分布式限流后,这就足够了吗?很显然是不行的,如果在极端情况下,分布式限流出现故障呢?所有流量都打入秒杀系统?在前面的文章中,我们也已经提到过,任何系统总有一个承载流量的上限,一旦超过这个上限,系统就会出现问题。

所以,除了使用分布式限流外,我们也需要增加本地API限流,本地API限流不仅仅是对分布式限流的有效补充,当分布式限流出现故障时,本地API限流更是分布式限流的有效兜底措施。

# 二、本章诉求

基于自定义注解实现本地API限流,当分布式限流出现故障时,本地限流作为补充和兜底措施。从源码级别重点掌握基于QPS实现本地API限流的落地方案,并能够将其灵活应用到自身实际项目中。

# 三、本地API限流原理

在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页),因此需有一种手段来限制这些场景的并发/请求量,即限流。

具体限流的原理可以参见《第79章:限流削峰 (opens new window)》一章的内容,这里不再赘述。

# 四、本地API限流实战

本节,就带着大家基于自定义注解开发本地API限流的功能,并整合到用户微服务测试实现效果。

# 4.1 新增自定义注解

新增@SeckillRateLimiter注解类,源码详见:seckill-ratelimiter工程下的io.binghe.seckill.ratelimiter.annotation.SeckillRateLimiter。

@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SeckillRateLimiter {
    /**
     * 限流器名称,如果不设置,默认是类名加方法名。如果多个接口设置了同一个名称,则使用同一个限流器
     */
    String name() default "";

    /**
     * 一秒内允许通过的请求数QPS
     */
    int permitsPerSecond() default 0;

    /**
     * 获取令牌超时时间
     */
    long timeout() default 0;

    /**
     * 获取令牌超时时间单位
     */
    TimeUnit timeUnit() default TimeUnit.SECONDS;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 4.2 新增BHRateLimiter类

BHRateLimiter类主要是基于Google开源的RateLimiter类封装的限流器,也是实现本地API限流的核心类。

源码详见:seckill-ratelimiter工程下的io.binghe.seckill.ratelimiter.bean.BHRateLimiter。

# 查看完整文章

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码