设计一个基于用户的API限流策略 Rate Limit

应用场景

API接口的流量控制策略:缓存、降级、限流。限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。限流策略虽然降低了服务接口的访问频率和并发量,却换取服务接口和业务应用系统的高可用。

常用的限流策略:

  • Nginx 限流

    按照一定的规则如帐号、IP、系统间调用逻辑等在 Nginx 层面做限流

  • 业务系统限流

    • 客户端限流

    • 服务端限流

  • 数据库限流

常用限流算法

  • 计数器

    计数器是最简单粗暴的算法,通过直接统计每个时间的请求数目来判断是否需要拒绝。

    比如某个服务最多只能每秒钟处理 100 个请求。我们可以设置一个 1 秒钟的滑动窗口,窗口中有 10 个格子,每个格子 100 毫秒,每 100 毫秒移动一次,每次移动都需要记录当前服务请求的次数。内存中需要保存 10 次的次数。可以用数据结构 LinkedList 来实现。格子每次移动的时候判断一次,当前访问次数和 LinkedList 中最后一个相差是否超过 100 ,如果超过就需要限流了。

    很明显,当滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。

    计数器的实现简单,但是是平均分配1秒钟的请求,然而实际情况中的请求往往是动态的,流量不平滑的。

  • 漏桶

    漏桶( Leaky Bucket )算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。

    可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水( burst ),另一个是水桶漏洞的大小( rate )。

    因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发( burst )到端口速率.因此,漏桶算法对于存在突发特性的流量来说缺乏效率.

  • 令牌桶

    令牌桶算法( Token Bucket )和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定 1/QPS 时间间隔(如果 QPS=100 ,则间隔是 10ms )往桶里加入 Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个 Token ,如果没有 Token 可拿了就阻塞或者拒绝服务.

    令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 一般会定时(比如100毫秒)往桶中增加一定数量的令牌, 有些变种算法则实时的计算应该增加的令牌的数量.

基于Redis的令牌桶算法限流策略实现

  • 策略

    因为出现了某些客户突然加大流量的情况,为了避免抢占其他用户的资源,所以设计了基于用户(限制单个用户的最大请求数)的令牌桶策略。

  • JAVA 实现

    /*** 获取令牌** @param key            令牌类别标识(每个用户不同)* @param permits        请求的令牌数量* @param currMillSecond 当前毫秒数* @return 是否能请求到令牌*/
    public boolean acquire(String key, Integer permits, long currMillSecond) {try (Jedis jedis = JedisPoolUtil.getJedisPool().getResource()) {//针对新用户创建令牌桶if (!jedis.exists(key)) {jedis.hset(key, "last_mill_second", String.valueOf(currMillSecond));jedis.hset(key, "curr_permits", "0");jedis.hset(key, "max_permits", "500");jedis.hset(key, "rate", "400");return true;}//获取令牌桶信息,上一个令牌时间,当前可用令牌数,最大令牌数,令牌消耗速率List<String> limitInfo = jedis.hmget(key, "last_mill_second", "curr_permits", "max_permits", "rate");long lastMillSecond = Long.parseLong(limitInfo.get(0));Integer currPermits = Integer.valueOf(limitInfo.get(1));Integer maxPermits = Integer.valueOf(limitInfo.get(2));Double rate = Double.valueOf(limitInfo.get(3));//向桶里面添加令牌Double reversePermitsDouble = ((currMillSecond - lastMillSecond) / 1000) * rate;Integer reversePermits = reversePermitsDouble.intValue();Integer expectCurrPermits = reversePermits + currPermits;Integer localCurrPermits = Math.min(expectCurrPermits, maxPermits);//添加令牌之后更新时间if (reversePermits > 0) {jedis.hset(key, "last_mill_second", String.valueOf(currMillSecond));}//判断桶里面剩余的令牌数目if (localCurrPermits - permits >= 0) {jedis.hset(key, "curr_permits", String.valueOf(localCurrPermits - permits));return true;} else {jedis.hset(key, "curr_permits", String.valueOf(localCurrPermits));return false;}} catch (Exception e) {return false;}
    }
    

    使用方式:

    if (!rateLimiterService.acquire("limiter:" + uid, 1, System.currentTimeMillis())) {throw new BusinessException(ExceptionType.TOO_BUSY);
    }
    

设计一个基于用户的API限流策略 Rate Limit相关推荐

  1. 一个基于用户的API限流策略 Rate Limit

    1. 限流场景 在开发高并发系统时,有很多种方法可用来保护系统:缓存.降级.限流等. 缓存:提升系统访问速度,增大系统处理能力 降级:服务出现问题或影响核心流程的性能时,需要暂时屏蔽,待高峰过去或问题 ...

  2. 基于用户的API限流策略

    应用场景 API接口的流量控制策略:缓存.降级.限流.限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的.限流策略虽然降低了服务接口的访问频率和并发量,却换取服务接口和业 ...

  3. 算法高级(7)-限流(Rate limit)算法详解

    一.前言 保障服务稳定的三大利器:熔断降级.服务限流和故障模拟.今天和大家谈谈限流算法的几种实现方式,本文所说的限流并非是Nginx层面的限流,而是业务代码中的逻辑限流. 那么为什么需要限流呢? 按照 ...

  4. Java互联网架构-如何设计服务接口API限流功能

    API 概念的出现,远远早于个人计算机的诞生,更不用说网络的诞生了.在公用数据处理的早期,为了一个应用能够与其它系统交互,开发者便已开始设计可公开访问并描述清晰的"接入点".早在那 ...

  5. 秒杀限制人群,如何设计秒杀服务的限流策略?

    对于秒杀业务,大家应该比较熟悉了.比如,"某商品原价 1299 元, 双十一整点秒杀价仅 500 元,限量 100 件,先到先得" 等等.通过这段文案我们能够发现,参与秒杀活动商品 ...

  6. 如何设计秒杀服务器的限流策略

    如果平时系统的访问量只有一万,而最大承受限制为五万,在秒杀时刻的瞬间,访问量突然增加到100W,此事系统一定会因访问量过大而宕机,此时就应该设计一个限流策略,使服务器能接收和处理的请求减少. 秒杀限流 ...

  7. 服务接口API限流 Rate Limit

    转载:https://www.cnblogs.com/exceptioneye/p/4783904.html https://blog.csdn.net/zrg523/article/details/ ...

  8. 【限流02】限流算法实战篇 - 手撸一个单机版Http接口通用限流框架

    本文将从需求的背景.需求分析.框架设计.框架实现几个层面一步一步去实现一个单机版的Http接口通用限流框架. 一.限流框架分析 1.需求背景 微服务系统中,我们开发的接口可能会提供给很多不同的系统去调 ...

  9. 基于Redis的分布式限流详解

    前言 Redis除了能用作缓存外,还有很多其他用途,比如分布式锁,分布式限流,分布式唯一主键等,本文将和大家分享下基于Redis分布式限流的各种实现方案. 一.为什么需要限流 用最简单的话来说:外部请 ...

最新文章

  1. idea直连linux部署项目,idea项目打包和在linux的部署
  2. DRP问题集结(一)-Tomcat无法启动,报错java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory...
  3. ubuntu权限管理
  4. 2021-01-07 matlab数值分析 常微分方程初边值问题数值解 标准龙格库塔四阶四段公式 欧拉法
  5. 科研神器推荐之那些年你用过的工具
  6. SH1B LMR62014XMFE/NOPB
  7. svn 版本控制操作命令
  8. mysql 比较一个字符串_比较MySQL中的两个字符串?
  9. BUUCTF Web [GXYCTF2019]Ping Ping Ping
  10. LeetCode93. 复原IP地址
  11. scrollview 中用listview的方法
  12. 记录一个Lock和sychronized应用及双检锁
  13. 《HTTP权威指南》读书笔记(1)-HTTP简介与消息结构
  14. Github客户端下载以及使用方法
  15. 基于Android的英文电子词典
  16. 花两个月吃透京东T8推荐的178页京东基础架构建设之路,入职定T5
  17. 中级软件设计师笔记全套 看完你就过啦
  18. AARRR模型——激活:获客红海背后的蓝海(上)
  19. [原创]QQ农场外挂辅助程序-小萝莉偷菜机器人,提供下载。
  20. 更愿意思念更早的“金陵”

热门文章

  1. Excel VBA-正则表达式汇总
  2. 使用SQL语句向表中插入多行数据
  3. js清除cookie有时无法清除
  4. 【连接池】Tomcat 连接池中 maxActive,maxWait,maxAge,testOnBorrow,testWhileIdle等选项的作用
  5. 安卓蓝牙开发的几个版本区别
  6. 关于单级PID及串级PID
  7. 台达PLC与单片机的通讯
  8. codeforces 14E. Camels(多维dp)
  9. nodejs+vue高校教室管理系统
  10. 反向代理haproxy用法详解