• 业务背景介绍
    对于web应用的限流,光看标题,似乎过于抽象,难以理解,那我们还是以具体的某一个应用场景来引入这个话题吧。
    在日常生活中,我们肯定收到过不少不少这样的短信,“双11约吗?,千款….”,“您有幸获得唱读卡,赶快戳链接…”。这种类型的短信是属于推广性质的短信。为什么我要说这个呢?听我慢慢道来。
    一般而言,对于推广营销类短信,它们针对某一群体(譬如注册会员)进行定点推送,有时这个群体的成员量比较大,譬如京东的会员,可以达到千万级别。因此相应的,发送推广短信的量也会增大。然而,要完成这些短信发送,我们是需要调用服务商的接口来完成的。倘若一次发送的量在200万条,而我们的服务商接口每秒能处理的短信发送量有限,只能达到200条每秒。那么这个时候就会产生问题了,我们如何能控制好程序发送短信时的速度昵?于是限流这个功能就得加上了
  • 生产环境背景
    1、服务商接口所能提供的服务上限是400条/s
    2、业务方调用短信发送接口的速度未知,QPS可能达到800/s,1200/s,或者更高
    3、当服务商接口访问频率超过400/s时,超过的量将拒绝服务,多出的信息将会丢失
    4、线上为多节点布置,但调用的是同一个服务商接口
  • 需求分析
    1、鉴于业务方对短信发送接口的调用频率未知,而服务商的接口服务有上限,为保证服务的可用性,业务层需要对接口调用方的流量进行限制—–接口限流
  • 需求设计
    方案一、在提供给业务方的Controller层进行控制。
    1、使用guava提供工具库里的RateLimiter类(内部采用令牌捅算法实现)进行限流
<!--核心代码片段-->
private RateLimiter rateLimiter = RateLimiter.create(400);//400表示每秒允许处理的量是400if(rateLimiter.tryAcquire()) {//短信发送逻辑可以在此处}

2、使用Java自带delayqueue的延迟队列实现(编码过程相对麻烦,此处省略代码)

3、使用redis实现,存储两个key,一个用于计时,一个用于计数。请求每调用一次,计数器增加1,若在计时器时间内计数器未超过阈值,则可以处理任务

 if(!cacheDao.hasKey(API_WEB_TIME_KEY)) {            cacheDao.putToValue(API_WEB_TIME_KEY,0,(long)1, TimeUnit.SECONDS);
}       if(cacheDao.hasKey(API_WEB_TIME_KEY)&&cacheDao.incrBy(API_WEB_COUNTER_KEY,(long)1) > (long)400) {LOGGER.info("调用频率过快");
}
//短信发送逻辑

方案二、在短信发送至服务商时做限流处理
方案三、同时使用方案一和方案二

  • 可行性分析
    最快捷且有效的方式是使用RateLimiter实现,但是这很容易踩到一个坑,单节点模式下,使用RateLimiter进行限流一点问题都没有。但是…线上是分布式系统,布署了多个节点,而且多个节点最终调用的是同一个短信服务商接口。虽然我们对单个节点能做到将QPS限制在400/s,但是多节点条件下,如果每个节点均是400/s,那么到服务商那边的总请求就是节点数x400/s,于是限流效果失效。使用该方案对单节点的阈值控制是难以适应分布式环境的,至少目前我还没想到更为合适的方式。
    对于第二种,使用delayqueue方式。其实主要存在两个问题,1:短信系统本身就用了一层消息队列,有用kafka,或者rabitmq,如果再加一层延迟队列,从设计上来说是不太合适的。2:实现delayqueue的过程相对较麻烦,耗时可能比较长,而且达不到精准限流的效果
    对于第三种,使用redis进行限流,其很好地解决了分布式环境下多实例所导致的并发问题。因为使用redis设置的计时器和计数器均是全局唯一的,不管多少个节点,它们使用的都是同样的计时器和计数器,因此可以做到非常精准的流控。同时,这种方案编码并不复杂,可能需要的代码不超过10行。

  • 实施方案
    根据可行性分析可知,整个系统采取redis限流处理是成本最低且最高效的。
    具体实现

    1、在Controller层设置两个全局key,一个用于计数,另一个用于计时

private static final String API_WEB_TIME_KEY = "time_key";private static final String API_WEB_COUNTER_KEY = "counter_key";

2、对时间key的存在与否进行判断,并对计数器是否超过阈值进行判断

if(!cacheDao.hasKey(API_WEB_TIME_KEY)) {cacheDao.putToValue(API_WEB_TIME_KEY,0,(long)1, TimeUnit.SECONDS);cacheDao.putToValue(API_WEB_COUNTER_KEY,0,(long)2, TimeUnit.SECONDS);//时间到就重新初始化为}if(cacheDao.hasKey(API_WEB_TIME_KEY)&&cacheDao.incrBy(API_WEB_COUNTER_KEY,(long)1) > (long)400) {LOGGER.info("调用频率过快");}//短信发送逻辑

实施结果
可以达到非常精准的流控,截图会在后续的过程中贴出来。欢迎有疑问的小伙伴们在评论区提出问题,我看到后尽量抽时间回答的

分布式环境下限流方案的实现相关推荐

  1. JAVA中useDrlimiter方法_今天来讲讲分布式环境下,怎么达到对象共享,以及实现原子性(atomic),以Redis中的Redisson为例(实现分布式锁、分布式限流等)...

    相信各位对redis肯定是不陌生的,一个高吞吐量的内存型结构存储数据库.可用用于很多业务场景,能够有效的解决很多复杂的并发问题,分布式问题. 下面粘一下中文官网介绍: 关于解决对象共享问题,很多方式, ...

  2. 分布式高并发服务三种常用限流方案简介

    以下文章来源于技术岁月 ,作者贺鹏Kavin 在高并发大流量系统中,由于并发大造成服务资源不足,负载过高,进而引发致一系列问题,这里的流量一般都是突发性的,由于系统准备不足,很难短期扩容来应对 ,进行 ...

  3. 【分布式】分布式环境下如何保证数据库和缓存的双写一致性?看完我明白了!!

    写在前面 当今时代,互联网高速发展,已然从IT时代进入到DT时代.我们系统的架构也由原来的单体应用,转变为分布式.微服务的架构模式.从数据上来看,数据量越来越大,数据的查询性能越来越低.此时,就需要我 ...

  4. 基于Redis组件之分布式RateLimiter限流

    上文我们介绍了RateLimiter文章路径针对IP来限流的方式,上文的限流方案,只针对单应用情况,分布式集群下就不能使用上文的方式,分布式下的限流方案有很多种,这边展示的是Redis的封装redis ...

  5. 微服务架构服务限流方案详解

    话说在 Spring Cloud Gateway 问世之前,Spring Cloud 的微服务世界里,网关一定非 Netflix Zuul 莫属.但是由于 Zuul 1.x 存在的一些问题,比如阻塞式 ...

  6. 2021年大数据环境搭建(二):分布式环境搭建

    2021大数据领域优质创作博客,带你从入门到精通,该博客每天更新,逐渐完善大数据各个知识体系的文章,帮助大家更高效学习. 有对大数据感兴趣的可以关注微信公众号:三帮大数据 目录 分布式环境搭建 集群规 ...

  7. 分布式环境下,互斥性与幂等性问题,分析与解决思路

    欢迎关注方志朋的博客,回复"666"获面试宝典 随着互联网信息技术的飞速发展,数据量不断增大,业务逻辑也日趋复杂,对系统的高并发访问.海量数据处理的场景也越来越多.如何用较低成本实 ...

  8. mysql集群session_集群/分布式环境下5种session处理策略

    前言 在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理.如果不做任何处理的话,用户将出现频繁登录的现象,比如集群中存在A.B两台服务器,用户在第一次访问网站时,Ngin ...

  9. 【Zookeeper系列】ZooKeeper管理分布式环境中的数据(转)

    原文地址:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  10. 分布式服务框架 Zookeeper — 管理分布式环境中的数据

    FROM: http://www.superwu.cn/2014/11/26/1461 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Z ...

最新文章

  1. vc 代码检查工具_C++网络安全入侵检测技术模块及源程序代码
  2. 一步步学习SPD2010--第七章节--使用BCS业务连接服务
  3. LeetCode 1464. 数组中两元素的最大乘积
  4. [Git GitHub] Windows下安装git,从0开始搭建git环境(配置环境变量+设置git-ssh key...配置)(超全版)
  5. NoSQL和Redis简介及Redis在Windows下的安装和使用教程
  6. mariadb配置允许远程访问方式
  7. 幂次方计算_收藏!机考计算器用法汇总,算题速度提高几倍
  8. cmmi分为哪几个等级?
  9. TongLINK/Q7.X 8.x查看队列情况命令
  10. P2P流量的监控与管理方案
  11. 面试准备:计算机网络常见面试题
  12. linux_SIGCHLD信号-子进程回收
  13. 【应用随机过程】04. 马尔可夫链的平稳分布
  14. 自相关与互相关的理解与物理意义
  15. 我们既然选择了远方,便只顾风雨兼程)
  16. 网络高手必备十款经典软件
  17. 计算机基础的建议,计算机应用基础教学实施建议.docx
  18. 永中Office的发行问题
  19. codeforces7D Palindrome Degree(manacherdp或Hshdp)
  20. Matlab【特征提取】频带方差端点检测含Matlab源码

热门文章

  1. RMAN-06091: no channel allocated for maintenance (of an appropriate type)
  2. BottomNavigationView的基本使用
  3. [原创] 婚纱照PS处理技术精粹(视频教程1.2G免费下载,11个核心技术点)
  4. Word文档如何生成目录?
  5. AutoJs学习-获取QQ群消息
  6. 前端:标准删除确认提示
  7. hdu 5773 (The All-purpose Zero)
  8. vue 中的const {XXX } =this 的作用效果
  9. Android获取超级管理员权限
  10. Matplotlib confusion map显示不全