java各层级限流对比,面试官说:来谈谈限流-从概念到实现,一问你就懵逼了?...

后端服务的接口都是有访问上限的,如果外部qps或并发量超过了访问上限会导致应用瘫痪。所以一般都会对接口调用加上限流保护,防止超出预期的请求导致系统故障。

从限流类型来说一般来说分为两种:并发数限流和qps限流,并发数限流就是限制同一时刻的最大并发请求数量,qps限流指的是限制一段时间内发生的请求个数。

从作用范围的层次上来看分单机限流和分布式限流,前者是针对单机的,后者是针对集群的,他们的思想都是一样的,只不过是范围不一样,本文分析的都是单机限流。

接下来我们看看并发数限流和qps限流。

并发数限流

并发数限流限制的是同一时刻的并发数,所以不考虑线程安全的话,我们只要用一个int变量就能实现,伪代码如下:

int maxrequest=100;

int nowrequest=0;

public void request(){

if(nowrequest>=maxrequest){

return ;

}

nowrequest++;

//调用接口

try{

invokexxx();

}finally{

nowrequest--;

}

}

显然,上述实现会有线程安全的问题,最直接的做法是加锁:

int maxrequest=100;

int nowrequest=0;

public void request(){

if(nowrequest>=maxrequest){

return ;

}

synchronized(this){

if(nowrequest>=maxrequest){

return ;

}

nowrequest++;

}

//调用接口

try{

invokexxx();

}finally{

synchronized(this){

nowrequest--;

}

}

}

当然也可以用atomicinteger实现:

int maxrequest=100;

atomicinteger nowrequest=new atomicinteger(0);

public void request(){

for(;;){

int currentreq=nowrequest.get();

if(currentreq>=maxrequest){

return;

}

if(nowrequest.compareandset(currentreq,currentreq+1)){

break;

}

}

//调用接口

try{

invokexxx();

}finally{

nowrequest.decrementandget();

}

}

熟悉jdk并发包的同学会说干嘛这么麻烦,这不就是信号量(semaphore)做的事情吗? 对的,其实最简单的方法就是用信号量来实现:

int maxrequest=100;

semaphore reqsemaphore = new semaphore(maxrequest);

public void request(){

if(!reqsemaphore.tryacquire()){

return ;

}

//调用接口

try{

invokexxx();

}finally{

reqsemaphore.release();

}

}

条条大路通罗马,并发数限流比较简单,一般来说用信号量就好。

qps限流

qps限流限制的是一段时间内(一般指1秒)的请求个数。

计数器法

最简单的做法用一个int型的count变量做计数器:请求前计数器+1,如超过阈值并且与第一个请求的间隔还在1s内,则限流。

伪代码如下:

int maxqps=100;

int count;

long timestamp=system.currenttimemillis();

long interval=1000;

public synchronized boolean grant(){

long now=system.currenttimemillis();

if(now

count++;

return count

}else{

timestamp=now;

count=1;

return true;

}

}

该种方法实现起来很简单,但其实是有临界问题的,假如在第一秒的后500ms来了100个请求,第2秒的前500ms来了100个请求,那在这1秒内其实最大qps为200。如下图:

0418f2f2f61a31d5c1d0358bf9bb6e7c.png

计数器法会有临界问题,主要还是统计的精度太低,这点可以通过滑动窗口算法解决

滑动窗口

我们用一个长度为10的数组表示1秒内的qps请求,数组每个元素对应了相应100ms内的请求数。用一个sum变量代码当前1s的请求数。同时每隔100ms将淘汰过期的值。

伪代码如下:

int maxqps=100;

atomicinteger[] count=new atomicinteger[10];

long timestamp=system.currenttimemillis();

long interval=1000;

atomicinteger sum;

volatile int index;

public void init(){

for(int i=0;i

count[i]=new atomicinteger(0);

}

sum=new atomicinteger(0);

}

public synchronized boolean grant(){

count[index].incrementandget();

return sum.incrementandget()

}

//每100ms执行一次

public void run(){

index=(index+1)%count.length;

int val=count[index].getandset(0);

sum.addandget(-val);

}

滑动窗口的窗口越小,则精度越高,相应的资源消耗也更高。

漏桶算法

漏桶算法思路是,有一个固定大小的桶,水(请求)忽快忽慢的进入到漏桶里,漏桶以一定的速度出水。当桶满了之后会发生溢出。

50ea607b13224a2e606269a36644a9e4.png

在维基百科上可以看到,漏桶算法有两种实现,一种是as a meter,另一种是as a queue。网上大多数文章都没有提到其有两种实现,且对这两种概念混乱。

as a meter

第一种实现是和令牌桶等价的,只是表述角度不同。

伪代码如下:

long timestamp=system.currenttimemillis();//上一次调用grant的时间

int bucketsize=100;//桶大小

int rate=10;//每ms流出多少请求

int count;//目前的水量

public synchronized boolean grant(){

long now = system.currenttimemillis();

if(now>timestamp){

count = math.max(0,count-(now-timestamp)*rate);

timestamp = now;

}

if(count+1<=bucketsize){

count++;

return true;

}else{

return false;

}

}

该种实现允许一段时间内的突发流量,比如初始时桶中没有水,这时1ms内来了100个请求,这100个请求是不会被限流的,但之后每ms最多只能接受10个请求(比如下1ms又来了100个请求,那其中90个请求是会被限流的)。

其达到的效果和令牌桶一样。

as a queue

第二种实现是用一个队列实现,当请求到来时如果队列没满则加入到队列中,否则拒绝掉新的请求。同时会以恒定的速率从队列中取出请求执行。

84bfc206ddb154e911bb8f20d66b475f.png

伪代码如下:

queue queue=new linkedblockingqueue(100);

int gap;

int rate;

public synchronized boolean grant(request req){

if(!queue.offer(req)){return false;}

}

// 单独线程执行

void consume(){

while(true){

for(int i=0;i

//执行请求

request req=queue.poll();

if(req==null){break;}

req.dorequest();

}

thread.sleep(gap);

}

}

对于该种算法,固定的限定了请求的速度,不允许流量突发的情况。

比如初始时桶是空的,这时1ms内来了100个请求,那只有前10个会被接受,其他的会被拒绝掉。注意与上文中as a meter实现的区别。

**不过,当桶的大小等于每个ticket流出的水大小时,第二种漏桶算法和第一种漏桶算法是等价的。**也就是说,as a queue是as a meter的一种特殊实现。如果你没有理解这句话,你可以再看看上面as a meter的伪代码,当bucketsize==rate时,请求速度就是恒定的,不允许突发流量。

令牌桶算法

令牌桶算法的思想就是,桶中最多有n个令牌,会以一定速率往桶中加令牌,每个请求都需要从令牌桶中取出相应的令牌才能放行,如果桶中没有令牌则被限流。

5f6c976e099ee6f8607e993ebe831e20.png

令牌桶算法与上文的漏桶算法as a meter实现是等价的,能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。伪代码:

int token;

int bucketsize;

int rate;

long timestamp=system.currenttimemillis();

public synchronized boolean grant(){

long now=system.currenttimemillis();

if(now>timestamp){

token=math.max(bucketsize,token+(timestamp-now)*rate);

timestamp=now;

}

if(token>0){

token--;

return true;

}else{

return false;

}

}

漏桶算法两种实现和令牌桶算法的对比

as a meter的漏桶算法和令牌桶算法是一样的,只是思想角度有所不同。

as a queue的漏桶算法能强行限制数据的传输速率,而令牌桶和as a meter漏桶则能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。

一般业界用的比较多的是令牌桶算法,像guava中的ratelimiter就是基于令牌桶算法实现的。当然不同的业务场景会有不同的需要,具体的选择还是要结合场景。

end

本文介绍了后端系统中常用的限流算法,对于每种算法都有对应的伪代码,结合伪代码理解起来应该不难。但伪代码中只是描述了大致思想,对于一些细节和效率问题并没有关注,所以下篇文章将会分析常用限流api:guava的ratelimiter的源码实现,让读者对于限流有个更清晰的认识。

本人免费整理了java高级资料,涵盖了java、redis、mongodb、mysql、zookeeper、spring cloud、dubbo高并发分布式等教程,一共30g,需要自己领取。

希望与广大网友互动??

点此进行留言吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql and 和where,关于mysql:连接sql查询中where和and子句的区别

本问题已经有最佳答案&#xff0c;请猛点这里访问。下面两个SQL查询有什么区别和号根据以下两个测试结果速度更快(237比460)。据我所知&#xff0c;这是一个标准。。氧化镁不&#xff0c;有细微的差别&#xff0c;你不能说没有差别除了语法之外没有别的区别。虽然只有一个简短的…

matlab里输出恒压的逆变器,基于IGBT逆变器的异步电机变频调速系统的MATLAB仿真...

异步电机变频调速系统电路仿真模型如图(4)所示。直流电压不621V&#xff0c;逆变器为IGBT 的三相半桥逆变器&#xff0c;电机为异步电机模块&#xff0c;其主电路由直流电压源、逆变器和电机依次相连。图(4)变频调速系统控制部分&#xff0c;利用“Step”模块设定频率指令f1*&a…

php 获取京东交易账号,PHP爬虫爬取京东列表

这里使用到了一个php插件下面是源码simple_html_dom.phpdefined(IN_ECS);define(HDOM_TYPE_ELEMENT, 1);define(HDOM_TYPE_COMMENT, 2);define(HDOM_TYPE_TEXT, 3);define(HDOM_TYPE_ENDTAG, 4);define(HDOM_TYPE_ROOT, 5);define(HDOM_TYPE_UNKNOWN, 6);define(HDOM_QUOTE_DOU…

php dns刷新,Windows DNS缓存自动刷新

Windows DNS缓存自动刷新admin • 2018 年 09 月 04 日DNS(域名服务器)DNS(Domain Name Server)是进行域名和与之相对应的ip地址转换的服务器。DNS中保存了一张域名和与之相应的ip地址的表&#xff0c;以解析消息的域名。DNS轮训在统一主机添加多条A记录&#xff0c;这就是DNS轮…

jq上传file到php,jQuery文件上传

插件描述&#xff1a;这是一个文件上传的展示&#xff0c;看很多插件&#xff0c;并不满意就自己写了一个&#xff0c;可能兼容性不是很好&#xff0c;没有准确进行测试过&#xff0c;还请各位不吝赐教更新时间&#xff1a;2019/3/25 下午8:53:17更新说明&#xff1a;修复上传成…

linux误删表空间文件,UNDO表空间下的数据文件被误删除后的处理方法

UNDO表空间下的数据文件被误删除后的处理方法&#xff1a;操作前备份数据库&#xff0c;以避免更大的损失。思路&#xff1a;1、把误删除的数据文件offline2、正常打开数据库后创建新的UNDO表空间及数据文件3、修改相应参数指向新的UNDO表空间4、重新启动数据库验证5、删除旧的…

linux内核有ebpf吗,聊聊很重要的内核技术eBPF

在2018年的 Linux Plumber 大会上&#xff0c;eBPF成了亮点&#xff0c;有24个议题提到了 eBPF&#xff0c;可以预计eBPF会成为一大技术热点。eBPF(Extended Berkeley Packet Filter) 的核心是驻留在 kernel 的高效虚拟机。最初的目的是高效网络过滤框架&#xff0c;前身是 BPF…

oom linux 导致ssh,Linux OOM

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;某个机器看到一条日志:Out of Memory: Kill process xxx (xxx) score 707 or sacrifice child并且syslog, ssh等进程都被kill掉了.简单了解了下OOM(Out of Memory)…

c语言bfs程序讲解,面试算法--二叉树DFS/BFS实现(C语言)

深度优先搜索算法(Depth First Search)DFS是搜索算法的一种。它沿着树的深度遍历树的节点&#xff0c;尽可能深的搜索树的分支。当节点v的所有边都己被探寻过&#xff0c;搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还…

c语言 子进程,子Shell和子进程

Shell 中有很多方法产生子进程&#xff0c;比如以新进程的方式运行 Shell 脚本&#xff0c;使用组命令、管道、命令替换等&#xff0c;但是这些子进程是有区别的。子进程的概念是由父进程的概念引申而来的。在 Linux 系统中&#xff0c;系统运行的应用程序几乎都是从 init(pid为…

学C语言办公本和游戏本,为什么不建议买游戏本?入手前须知,别只看中游戏...

原标题&#xff1a;为什么不建议买游戏本&#xff1f;入手前须知&#xff0c;别只看中游戏作为一名游戏本用户&#xff0c;我自己在用的游戏本已经用了四五年的时间了&#xff0c;从最初的大学生到毕业工作2年时间&#xff0c;这一游戏本给我带来了不少麻烦。最大的麻烦就是“笨…

Android ui 单元测试 覆盖率,Android单元测试—UI测试(Espresso)

前言我们先回顾一下&#xff0c;在上一篇博客中&#xff0c;主要分享了Android单元测试的逻辑测试部分。接下来&#xff0c;我们重点讲解Android单元测试的UI测试部分&#xff01;何为UI测试呢&#xff1f;就是对用户界面的交互元素进行测试&#xff0c;如TextView、ImageView&…

android shape 圆角百分比,Android shape显示圆角问题

当需要定义一个圆角效果,当在ADT中预览,没有有效果时,只要运行就可以了&#xff01;xmlns:Android"http://schemas.android.com/apk/res/android">android:state_pressed"true">android:startColor"#ff8c00"android:endColor"#FFFFFF…

android 删除垃圾文件夹,别再用手机管家清理垃圾了!删除这些文件夹,内存瞬间释放几个G...

随着手机使用时间的增加&#xff0c;手机中缓存的东西越来越多&#xff0c;这时候手机内存空间就会告急&#xff0c;从而影响手机的流畅性。那么在这种时候不要乱清理&#xff0c;我们只需要删除这几个文件夹&#xff0c;就可以帮手机轻松释放好几个G的内存。下面我们就一起来看…

计算机的应用技术课程的看法,统计教学与计算机应用的几点看法论文

统计教学与计算机应用的几点看法论文一、传统教学方法的局限性和弊端统计学是一门关于搜集、整理、汇总、描述和分析数据资料&#xff0c;并在此基础上进行推断和决策的方法论科学&#xff0c;具有很强的应用性、实践性。统计学课程是中等职业学校、财经类专业的基础核心课程。…

jupyter可以打开HTML文件吗,Jupyter ~ 像写文章般的 Coding (附:同一个ipynb文件,执行多语言代码)...

前面用了很久Notebook来交互式编程了&#xff0c;此次说说几个其余的选项&#xff1a;htmlNotebook Markdown此次选Markdown模式(关于Markdown基础能够看以前写的Markdown Base)python和代码同样&#xff0c;Shift回车就能够预览了&#xff0c;怎么样是否是很酷的感受&#xff…

计算机网络技术基础教学内容,计算机网络技术基础

无计算机网络技术基础》课程教案一 计算机网络技术基础》课题&#xff1a; 课题&#xff1a;计算机网络概述(一) ) 教学顺序&#xff1a; 教学顺序&#xff1a;1 教学时数&#xff1a; 教学时数&#xff1a; 2 学时 教学目的&#xff1a;了解计算机网络产生的背景&#xff0c;掌…

计算机表格收入水平怎么算,怎么用excel计算工资所得税

利用Excel表格计算工资所得税?单位工资发放大多采用计算机管理,对一些小企业没有采用工资软件的,一般用Excel表来计算工资。下面小编就教你怎么用excel计算工资所得税。excel计算工资所得税的步骤&#xff1a;1、假设工资的所得税起征点为3500&#xff0c;具体阶段如下表。2、…

同一网段计算机无法共享打印机,Win7同一个局域网内共享打印机不成功的修复方法...

打印机共享需要在同一个局域网内完成&#xff0c;这样打印机可以共享多台电脑。一位用户说自己的打印机和台式Win7系统电脑的连接已经成功&#xff0c;但就是没办法打印机文件&#xff0c;怎么回事呢&#xff1f;win7系统共享打印机的前提是需要关闭杀毒软件和win7系统的防火墙…

嵌入式计算机的特点和应用,以下描述中,()不是嵌入式操作系统的特点。A.面向应用,可以进行裁剪和移植B.用 - 信管网...

第4题&#xff1a;在分布式数据库中包括分片透明、复制透明、位置透明和逻辑透明等基本概念&#xff0c;其中&#xff1a;()是指局部数据模型透明&#xff0c;即用户或应用程序无需知道局部场地使用的是哪种数据模型。A&#xff0e;分片透明B&#xff0e;复制透明C&#xff0e;…