Java高并发系统的限流策略
限流算法
令牌桶(Token Bucket)、漏桶(leaky bucket)和计数器算法是最常用的三种限流的算法。
计数器限流算法也是比较常用的,主要用来限制总并发数,比如数据库连接池大小、线程池大小、程序访问并发数等都是使用计数器算法。也是最简单粗暴的算法。
使用计数器限流示例1:
public class CountRateLimiterDemo { private static AtomicInteger count = new AtomicInteger(0); public static void exec() { if (count.get() >= 5) { System.out.println("请求用户过多,请稍后在试!"+System.currentTimeMillis()/1000); } else { count.incrementAndGet(); try { //处理核心逻辑 TimeUnit.SECONDS.sleep(1); System.out.println("--"+System.currentTimeMillis()/1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { count.decrementAndGet(); } } }
}
使用AomicInteger来进行统计当前正在并发执行的次数,如果超过域值就简单粗暴的直接响应给用户,说明系统繁忙,请稍后再试或其它跟业务相关的信息。
弊端:使用 AomicInteger 简单粗暴超过域值就拒绝请求,可能只是瞬时的请求量高,也会拒绝请求。
使用计数器限流示例2
public class CountRateLimiterDemo { private static Semaphore semphore = new Semaphore(50); public static void exec() { if(semphore.getQueueLength()>100){ System.out.println("当前等待排队的任务数大于100,请稍候再试..."); } try { semphore.acquire(); // 处理核心逻辑 TimeUnit.SECONDS.sleep(1); System.out.println("--" + System.currentTimeMillis() / 1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semphore.release(); } }
}
使用Semaphore信号量来控制并发执行的次数,如果超过域值信号量,则进入阻塞队列中排队等待获取信号量进行执行。如果阻塞队列中排队的请求过多超出系统处理能力,则可以在拒绝请求。
相对Atomic优点:如果是瞬时的高并发,可以使请求在阻塞队列中排队,而不是马上拒绝请求,从而达到一个流量削峰的目的。
使用guava的RateLimiter限流示例3
Guava中开源工具类RateLimiter是基于令牌桶算法的实现类,可以简单的实现限流的工作,并根据系统实际情况调整生成token速率。RateLimiter 对简单的令牌桶算法做了一些工程上的优化,具体的实现是 SmoothBursty。需要注意的是,RateLimiter 的另一个实现 SmoothWarmingUp,就不是令牌桶了,而是漏桶算法。也许是出于简单起见,RateLimiter 中的时间窗口能且仅能为 1s,如果想搞其他时间单位的限流,只能另外造轮子。
RateLimiter 有一个有趣的特性是「前人挖坑后人跳」,也就是说 RateLimiter 允许某次请求拿走超出剩余令牌数的令牌,但是下一次请求将为此付出代价,一直等到令牌亏空补上,并且桶中有足够本次请求使用的令牌为止。这里面就涉及到一个权衡,是让前一次请求干等到令牌够用才走掉呢,还是让它先走掉后面的请求等一等呢?Guava 的设计者选择的是后者,先把眼前的活干了,后面的事后面再说。
RateLimiter rateLimiter = RateLimiter.create(2);
System.out.println(rateLimiter.acquire(5));
System.out.println(rateLimiter.acquire(2));
System.out.println(rateLimiter.acquire(1));
输出
0.0
2.496889
0.992149
可以看出,令牌桶每秒只能产生2个令牌,我们可以第一次取出5个,但是第二个再去取令牌的时候,需要等2.5s,也就是第一次令牌取完后,需要等2.5s才能取到令牌。同样的,第三次取1个令牌的时候,也需要等待第二次的1s的时间。也就是,取的速率可以超过令牌产生的速率,但是下一次再次去取的时候,需要阻塞等待。
当然也可以使用tryAcquire来非阻塞的获取,可以实时返回结果。另外tryAcquire也可以传入参数,也就是等待的时间,超时直接返回false。这点等同于常见的lock,tryLock。
Java高并发系统的限流策略相关推荐
- 谈谈高并发系统的限流
开涛大神在博客中说过:在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.本文结合作者的一些经验介绍限流的相关概念.算法和常规的实现方式. 缓存 缓存比较好理解,在大型高并发系统中,如果没有缓 ...
- 慌了,居然被问到怎么做高并发系统的限流
点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 来源:uee.me/cDuRD 在开发高并发系统时有三把利 ...
- 面试官 | 讲一下如何给高并发系统做限流?
作者 | nick hao 来源 | uee.me/cDuRD 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.本文结合作者的一些经验介绍限流的相关概念.算法和常规的实现方式. 缓存 缓存 ...
- 高并发系统之限流特技
转载至:http://blog.csdn.net/g_hongjin/article/details/51649246 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.缓存的目的是提升系统 ...
- 高并发系统的限流算法与实现
开发高并发系统时有三把利器用来保护系统:缓存.降级和限流. 缓存:缓存的目的是提升系统访问速度和增大系统处理容量. 降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的 ...
- 聊聊高并发系统之限流特技-1
在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流. 缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹:而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉 ...
- 高并发中的 限流、熔断、降级、预热、背压你都知道是什么意思吗?
首先,我们需要明确一下这几个名词出现的场景:分布式高并发环境.如果你的产品卖相不好,没人鸟它,那它就用不着这几个属性.不需要任何加成,低并发系统就能工作的很好. 分布式系统是一个整体,调用关系错综复杂 ...
- 高可用系统设计 | 分布式限流策略:计数器算法、漏桶算法、令牌桶算法
文章目录 限流 什么是限流? 分布式限流 限流算法 计数器算法 固定窗口计数器 滑动窗口计数器 漏桶算法 令牌桶算法 限流 什么是限流? 限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已 ...
- java 异步_聊聊java高并发系统之异步非阻塞
作者:孙伟,目前负责京东商品详情页统一服务系统,写过java,写过ngx_lua,还写过storm等,喜欢学习研究新事物. 在做电商系统时,流量入口如首页.活动页.商品详情页等系统承载了网站的大部分流 ...
最新文章
- 安卓应用如何引用动态库
- 机器学习常见知识点自查50问与答
- 执行SQL-MapperProxy.invoke()
- c语言加花指令,花指令的应用
- python实现链表的删除_干货||链表的技巧和算法总结
- 数据科学家为什要用Git?怎么用? 1
- 项目学子商城(加密,异常,拦截器SpringBoot没有xml配置文件,附常见配置错误)
- 网站采集软件,全自动网站文章采集器,一键网页数据抓取
- 【从蛋壳到满天飞】JS 数据结构解析和算法实现-链表
- R语言学习笔记(四)--数据结构
- html5横竖条纹背景,CSS制作Web页面条纹背景样式的介绍
- 模板引擎Beet的6大创新点
- 腾讯云windows server搭建valheim(英灵神殿)服务器
- 管理者的角色修炼-第一课总结
- android 模拟返回键
- RTSP取流之海康威视
- 常用数据结构和算法操作效率的对比总结
- Linux修改屏幕分辨率(命令行)
- 世界工厂供应商采集助手【已失效】
- IOS开发者账号购买、续费支付方法