如何实现API接口限流

这篇文章主要介绍如何实现API接口限流,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

创新互联公司-专业网站定制、快速模板网站建设、高性价比宾川网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式宾川网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖宾川地区。费用合理售后完善,10年实体公司更值得信赖。

同样,在互联网行业中,也存在这样得场景,我们把它称为——限流,为什么要限流呢,原因如下:

在系统上线初期,用户量和访问量不大得时候,一般部署几台应用服务器,数据库做一个读写分离就基本上抗得住,但随着时间的推移,业务的发展,用户量和日活得增加,系统所承受的压力越来越大,我么都知道,应用服务器扩容很方便,但数据库扩容就有些麻烦,如果请求数据库的量太大的话,或者遇到恶意攻击,数据库极有可能宕机,最后导致整个网站不可用。

为了避免这样的事情发生,我们通常要限制住用户的请求次数。对于合法的用户,我们要限制单位时间内用户调用接口的次数,对于恶意攻击者,直接将他放入黑名单中。

我们通常用redis中的zset数据结构来做限流。由于zset底层是用跳跃表存储数据的,按score字段从小到大排序,我们可以把时间戳存入score字段。随着时间的流逝,把每一次请求的时间戳存入score中,而member呢?随便存储什么无所谓啦,但不要存储太大的数据。如下图:

如何实现API接口限流

假如我们要求接口的调用一分钟不能超过100次,那么图中橙色矩形区域是一个时间段范围内的时间窗口,矩形的有边框是当前时间,它随着时间的流逝一点一点向右移动,矩形左边框是1min前,矩形的宽度就是1min。我们通过Redis的zcount命令很容易计算出这个时间范围内的数据量,如果数据量超出100,说明用户请求的太快了,应该进行限流的操作。下面来看一段简单的代码:

/**     * 基于zset限流     * @param key       redis key     * @param maxCount  指定时间内最大通过个数     * @param timeRange 时间窗范围,单位:秒     * @return          是否可以继续请求     */    public static  boolean rateLimiterByZset(String key,int maxCount,int timeRange){        try (Jedis jedis = jedisPool.getResource()) {            long currentTime = new Date().getTime();        //当前时间戳            long secondTime = currentTime-timeRange*1000;      //second秒前的时间戳            long memberCount = jedis.zcount(key,secondTime,currentTime);            if(memberCount >= maxCount){                return false;            }
           jedis.zadd(key,currentTime,currentTime+"");            //删除时间框外的数据,因为它们已经没有用了            jedis.zremrangeByScore(key,0,secondTime);        }        return true;    }

哈哈,就这么简单。有一点要注意的是,请大家及时删除时间框(也就是上图中左边框外)范围外的数据,因为它们已经没有用了,留着非常消耗内存资源。

大家会不会有这样的疑问:对zset操作这么频繁,会不会有性能上的问题呀?其实大家不必太担心,毕竟Redis的数据结构都是经过精心设计的,性性能很高,大家可以参考小编的这篇文章,来学习Redis的数据结构。

从数据存储角度分析Redis性能为何如此高

刘莅,公众号:向代码致敬从数据存储角度分析Redis性能为何如此高  

测试程序和输出效果如下:

@Test    public void test1() throws Exception{        int i = 1;        while(true){            Thread.sleep(5);            boolean flag = RedisRateLimiter.rateLimiterByZset("keysss",10,1);            if(flag){                System.out.println("第"+i+"个请求成功");            }else{                System.out.println("第"+i+"个被限流");            }            i++;        }    }
第1个请求成功第2个请求成功第3个请求成功第4个请求成功第5个请求成功第6个请求成功第7个请求成功第8个请求成功第9个请求成功第10个请求成功第11个被限流第12个被限流...第42个被限流第43个被限流第44个请求成功第45个请求成功第46个请求成功第47个请求成功第48个请求成功第49个请求成功第50个请求成功第51个请求成功第52个请求成功第53个请求成功第54个被限流第55个被限流...

以上是“如何实现API接口限流”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!


网站题目:如何实现API接口限流
标题路径:http://pwwzsj.com/article/jgidgc.html