首页 网站首页 商业信息 限流 查看内容

一文读懂限流算法及方案介绍

电商运营 2023-7-28 19:30 9469人围观 限流

作者:京东科技 康志兴

利用处景

现代互联网很多营业场景,比如秒杀、下单、查询商品详情,最大特点就是高并发,而常常我们的系统不能承受这么大的流量,继而发生了很多的应对办法:CDN、消息行列、多级缓存、异地多活。

可是不管若何优化,毕竟由硬件的物理特征决议了我们系统性能的上限,假如强行接收一切请求,常常形成雪崩。

这时辰限流熔断就发挥感化了,限制请求数,快速失利,保证系统满负载又不超限。

极致的优化,就是将硬件利用率进步到100%,但永久不会跨越100%

常用限流算法

1. 计数器

间接计数,简单暴力,举个例子:

比如限流设定为1小时内10次,那末每次收到请求就计数加一,并判定这一小时内计数能否大于上限10,没跨越上限就返回成功,否则返回失利。

这个算法的弱点就是在时候临界点会有较大瞬间流量。

继续上面的例子,理想状态下,请求匀速进入,系统匀速处置请求:


一文读懂限流算法及计划先容

但现真相况中,请求常常不是匀速进入,假定第n小时59分59秒的时辰忽然进入10个请求,全数请求成功,到达下一个时候区间时革新计数。那末第n+1小时刚起头又打进10个请求,即是瞬间进入20个请求,必定不合适“1小时10次”的法则,这类现象叫做“突刺现象”。


一文读懂限流算法及计划先容

为处理这个题目,计数器算法经过优化后,发生了滑动窗口算法:

我们将时候间隔均匀分隔,比如将一分钟分为6个10秒,每一个10秒内零丁计数,总的数目限制为这6个10秒的总和,我们把这6个10秒成为“窗口”。

那末每过10秒,窗口往前滑动一步,数目限制变成新的6个10秒的总和,如图所示:


一文读懂限流算法及计划先容

那末假如在临界时,收到10个请求(图中灰色格子),鄙人一个时候段到姑且,橙色部分又进入10个请求,但窗口内包括灰色部分,所以已经到达请求上线,不再接收新的请求。

这就是滑动窗口算法。

可是滑动窗口照旧有缺点,为了保证匀速,我们要分别尽能够多的格子,而格子越多,每一个格子可以接收的请求数就越少,这样就限制了系统瞬间处置才能。

2. 漏桶


一文读懂限流算法及计划先容

漏桶算法实在也很简单,假定我们有一个牢固容量的桶,流速(系统处置才能)牢固,假如一段时候水龙头水流太大,水就溢出了(请求被抛弃了)。

用编程的说话来说,每次请求进来都放入一个先辈先出的行列中,行列满了,则间接返回失利。别的有一个线程池牢固间隔不竭地从这个行列中拉取请求。

消息行列、jdk的线程池,都有类似的设想。

3. 令牌桶

令牌桶算法比漏桶算法稍显复杂。

首先,我们有一个牢固容量的桶,桶里寄存着令牌(token)。桶一路头是空的,token以一个牢固的速度往桶里添补,直到到达桶的容量,过剩的令牌将会被抛弃。每当一个请求过来时,就会尝试从桶里移除一个令牌,假如没有令牌的话,请求没法经过。


一文读懂限流算法及计划先容

漏桶和令牌桶算法的区分:

漏桶的特点是消耗才能牢固,当请求量超越消耗才能时,供给一定的冗余才能,把请求缓存下来匀速消耗。优点是对下流庇护更好。

令牌桶碰到激增流量会更自在,只要存在令牌,则可以一并消耗掉。合适有突发特征的流量,如秒杀场景。

限流计划

一、容器限流

1. Tomcat

tomcat可以设置毗连器的最大线程数属性,该属性maxThreads是Tomcat的最大线程数,当请求的并发大于maxThreads时,请求就会排队履行(排队数设备:accept-count),这样就完成了限流的目标。

<Connector port="8080" protocol="HTTP/1.1"          connectionTimeout="20000"          maxThreads="150"          redirectPort="8443" />

2. Nginx

Nginx 供给了两种限流手段:一是控制速度,二是控制并发毗连数。

  • 控制速度
  • 我们需要利用 limit_req_zone设置来限制单元时候内的请求数,即速度限制,示例设置以下:
  • limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
  • 第一个参数:$binary_remote_addr 暗示经过remote_addr这个标识来做限制,“binary_”的目标是缩写内存占用量,是限制同一客户端ip地址。
  • 第二个参数:zone=mylimit:10m暗示天生一个巨细为10M,名字为one的内存地区,用来存储拜候的频次信息。
  • 第三个参数:rate=2r/s暗示答应不异标识的客户真个拜候频次,这里限制的是每秒2次,还可以有比如30r/m的。
  • 并发毗连数
  • 操纵 limit_conn_zonelimit_conn 两个指令即可控制并发数,示例设置以下
  • limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; server { ... limit_conn perip 10; # 限制同一个客户端ip limit_conn perserver 100; }

只要当 request header 被后端处置后,这个毗连才停止计数

二、办事端限流

1. Semaphore

JUC包中供给的信号量工具,它的内部保护了一个同队伍列,我们可以在每个请求进来的时辰,尝试获得信号量,获得不到可以阻塞大概快速失利

简单样例:

Semaphore sp = new Semaphore(3);sp.require(); // 阻塞获得System.out.println("履行营业逻辑");sp.release();

2. RateLimiter

Guava中基于令牌桶实现的一个限流工具,利用很是简单,经过方式create()建立一个桶,然后经过acquire()大概tryAcquire()获得令牌:

RateLimiter rateLimiter = RateLimiter.create(5); // 初始化令牌桶,每秒往桶里寄存5个令牌rateLimiter.acquire(); // 自旋阻塞获得令牌,返回阻塞的时候,单元为秒rateLimiter.tryAcquire(); // 获得令牌,返回布尔成果,跨越超不时候(默以为0,单元为毫秒)则返回失利

RateLimiter在实现时,答应暴增请求的突发情况存在。

举个例子,我们有一个速度为每秒5个令牌的RateLimiter:

当令牌桶空了的时辰,假如继续获得一个令牌,那末会鄙人一次补充令牌的时辰返回成果

但假如间接获得5个令牌,并不是期待桶内补齐5个令牌后再返回,而是仍然会在令牌桶补充下一个令牌的时辰间接返回,而预支令牌所需的补充时候会鄙人一次请求时停止抵偿

public void testSmoothBursty() {    RateLimiter r = RateLimiter.create(5);    for (int i = 0; i++ < 2; ) {               System.out.println("get 5 tokens: " + r.acquire(5) + "s");        System.out.println("get 1 tokens: " + r.acquire(1) + "s");        System.out.println("get 1 tokens: " + r.acquire(1) + "s");        System.out.println("get 1 tokens: " + r.acquire(1) + "s");        System.out.println("end");    }}/*** 控制台输出* get 5 tokens: 0.0s	  初始化时桶是空的,间接从空桶获得5个令牌* get 1 tokens: 0.998068s 滞后效应,需要替前一个请求停止期待* get 1 tokens: 0.196288s* get 1 tokens: 0.200391s* end* get 5 tokens: 0.195756s* get 1 tokens: 0.995625s 滞后效应,需要替前一个请求停止期待* get 1 tokens: 0.194603s* get 1 tokens: 0.196866s* end*/

3. Hystrix

Netflix开源的熔断组件,支持两种资本隔离战略:THREAD(默许)大概SEMAPHORE

  • 线程池:每个command运转在一个线程中,限流是经过线程池的巨细来控制的
  • 信号量:command是运转在挪用线程中,可是经过信号量的容量来停止限流

线程池战略对每一个资本建立一个线程池以停止流量管控,优点是资本隔离完全,弱点是轻易形成资本碎片化。

利用样例:

// HelloWorldHystrixCommand要利用Hystrix功用 public class HelloWorldHystrixCommand extends HystrixCommand {      private final String name;     public HelloWorldHystrixCommand(String name) {           super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));             this.name = name;     }     // 假如继续的是HystrixObservableCommand,要重写Observable construct()     @Override     protected String run() {             return "Hello " + name;     } } 

挪用该command:

String result = new HelloWorldHystrixCommand("HLX").execute();System.out.println(result);  // 打印出Hello HLX 

Hystrix已经在2018年停止开辟,官方保举替换项目Resilience4j

更多利用先容可检察:Hystrix熔断器的利用

4. Sentinel

阿里开源的限流熔断组件,底层统计采用滑动窗口算法,限流方面有两种利用方式:API挪用和注解,内部采插槽链来统计和履行校验法则。

经过为方式增加注解@SentinelResource(String name)大概手动挪用SphU.entry(String name)方式开启流控。

利用API手动挪用流控示例:

@Testpublic void testRule() {    // 设置法则.    initFlowRules();    int count = 0;    while (true) {        try (Entry entry = SphU.entry("HelloWorld")) {            // 被庇护的逻辑            System.out.println("run " + ++count + " times");        } catch (BlockException ex) {            // 处置被流控的逻辑            System.out.println("blocked after " + count);            break;        }    }}// 输出成果:// run 1 times// run 2 times// run 3 times

关于Sentinel的具体先容可检察:Sentinel-散布式系统的流量尖兵

三、散布式下限流计划

线上情况下,假如对共用资本(如数据库、下流办事)做同一流量限制,那末单机限流明显不能满足,而需要散布式流控计划。

散布式限流首要采纳中心系统流量管控的计划,由一其中心系统同一管控流量配额。

这类计划的弱点就是中心系统的牢靠性,所以一般需要备用计划,在中心系统不成用时,退化为单机流控。

1. Tair经过incr方式实现简单窗口

实现方式是利用incr()自增方式来计数并与阈值停止巨细比力。

public boolean tryAcquire(String key) {    // 以秒为单元构建tair的key    String wrAPPedKey = wrapKey(key);    // 每次请求+1,初始值为0,key的有用期设备5s    Result<Integer> result = tairManager.incr(NAMESPACE, wrappedKey, 1, 0, 5);    return result.isSuccess() && result.getValue() <= threshold;}private String wrapKey(String key) {    long sec = System.currentTimeMillis() / 1000L;    return key + ":" + sec;}

【备注】incr方式的参数说明

// 方式界说:Result incr(int namespace, Serializable key, int value, int defaultValue, int expireTime)/* 参数寄义:namespace - 申请时分派的 namespacekey - key 列表,不跨越 1kvalue - 增加量defaultValue - 第一次挪用 incr 时的 key 的 count 初始值,第一次返回的值为 defaultValue + value。expireTime - 数据过期时候,单元为秒,可设相对时候或绝对时候(Unix 时候戳)。*/

2. Redis经过lua剧本实现简单窗口

与Tair实现方式类似,不外redis的incr()方式不能原子性的设备过期时候,所以需要利用lua剧本,在第一次挪用返回1时,设备下过期时候为1秒。

local currentcurrent = redis.call("incr",KEYS[1])if tonumber(current) == 1 then     redis.call("expire",KEYS[1],1)endreturn current

3. Redis经过lua剧本实现令牌桶

实现思绪是获得令牌后,用SET记录“请求时候”和“残剩token数目”。

每次请求令牌时,经过这两个参数和请求的时候、流速等参数停止计较,返回能否获得令牌成功。

获得令牌lua剧本:

local ratelimit_info = redis.pcall('HMGET',KEYS[1],'last_time','current_token')local last_time = ratelimit_info[1]local current_token = tonumber(ratelimit_info[2])local max_token = tonumber(ARGV[1])local token_rate = tonumber(ARGV[2])local current_time = tonumber(ARGV[3])local reverse_time = 1000/token_rateif current_token == nil then  current_token = max_token  last_time = current_timeelse  local past_time = current_time-last_time  local reverse_token = math.floor(past_time/reverse_time)  current_token = current_token+reverse_token  last_time = reverse_time*reverse_token+last_time  if current_token>max_token then    current_token = max_token  endendlocal result = 0if(current_token>0) then  result = 1  current_token = current_token-1end redis.call('HMSET',KEYS[1],'last_time',last_time,'current_token',current_token)redis.call('pexpire',KEYS[1],math.ceil(reverse_time*(max_token-current_token)+(current_time-last_time)))return result

初始化令牌桶lua剧本:

local result=1redis.pcall("HMSET",KEYS[1],"last_mill_second",ARGV[1],"curr_permits",ARGV[2],"max_burst",ARGV[3],"rate",ARGV[4])return result

高端人脉微信群

高端人脉微信群

人脉=钱脉,我们相信天下没有聚不拢的人脉,扫码进群找到你所需的人脉,对接你所需的资源。

商业合作微信

商业合作微信

本站创始人微信,13年互联网营销经验,擅长引流裂变、商业模式、私域流量,高端人脉资源丰富。

精彩点评

相关推荐

平台大洗牌,被限流该怎么办?

平台大洗牌,被限流该怎么办?

最近平台大洗牌,评论区问最多的就是,如果被限流了该怎么办,今天就详细的解答这个问

降级-熔断-限流-傻傻分不清楚

降级-熔断-限流-傻傻分不清楚

1. 熔断1.1 熔断来源我们家用电闸上都有保险丝模块,当电压出现短路问题时,自动跳闸

血泪教训:小红书被限流怎么办?怎么恢复正常?

血泪教训:小红书被限流怎么办?怎么恢复正常?

很多新手小白刚开始运营小红书的时候,多半会经历很长一段数据低迷的情况。一方面,是

小红书无故被限流了??这里有你不知道的小红书限流小 ...

小红书无故被限流了??这里有你不知道的小红书限流小 ...

自从有消息爆出小红书内测直播功能之后,小红书成为了当下最受关注的平台之一。而正在

《抖音限流/降权/违规词手册》

《抖音限流/降权/违规词手册》

为了让更多小伙伴能够自己找到并解决【抖音限流】问题,今天为大家梳理一份抖音「限流

闲鱼被限流了,教你恢复元气

闲鱼被限流了,教你恢复元气

作者:咸鱼暴增系统很多朋友在使用小闲的时候都有可能碰到没有流量了,或者流量降低了

司马南为何被限流?多篇文章和视频下架!

司马南为何被限流?多篇文章和视频下架!

连续两天,灵灵看世界针对司马南污蔑、挑衅张文宏和陶斯亮提出质疑和批评,结果是:司

一文搞清楚限流、熔断和降级

一文搞清楚限流、熔断和降级

限流是对系统的被请求频率以及内部的部分功能的执行频率加以限制,防止因突发的流量激

作品播放量低,账号是不是被限流了,该怎么办呢?

作品播放量低,账号是不是被限流了,该怎么办呢?

前天我新发布的视频的播放量创历史了,有史以来最低的,你是不是也遇到过这样的情况?

一招判断自己的微头条是否被限流,被限流后,到底该怎么解决呢?

一招判断自己的微头条是否被限流,被限流后,到底该怎么解决呢?

对于一个自媒体创作者来说,辛辛苦苦创作的内容,发表后阅读量寥寥无几,那种心痛只有

阿里巴巴开源限流系统 Sentinel 全解析

阿里巴巴开源限流系统 Sentinel 全解析

今年下半年阿里开源了自研的限流系统 Sentinel,官方对 Sentinel 的介绍中用到了一系

展现量少怀疑被限流,打开它让你一看究竟,稍做修改也许爆了

展现量少怀疑被限流,打开它让你一看究竟,稍做修改也许爆了

不少友友顽强坚持,笔耕不辍,作品不少,但展现量不高,毕竟展现量才是根本,没有展现

文章被限流了怎么办?如何采取行动进行补救?我以昨天的文章为例

文章被限流了怎么办?如何采取行动进行补救?我以昨天的文章为例

文章被限流,是大家一直以来热议的一个话题,往往也只能表示无奈,没有任何办法,毕竟

第一批蹦迪选手已经“阳康”?武汉夜店开始限流了。

第一批蹦迪选手已经“阳康”?武汉夜店开始限流了。

月初我们找了22位知名的夜店老板做了一期专访,话题是关于“放开后夜店生意变好了吗?

如何判断账号是否被限流?没流量?赶紧查看这个地方

如何判断账号是否被限流?没流量?赶紧查看这个地方

只要查看一个地方,就可以知道你的账号是不是被限流了,好多朋友播放量突然间大幅度降

头条被限流可能是因为这几个原因,浅谈一下头条推荐机制

头条被限流可能是因为这几个原因,浅谈一下头条推荐机制

前段时间写了一篇文章刚发第一天没什么流量,突然第二天流量暴涨了,随之问题也跟着来

一篇文章说清楚头条“限流”那些事儿

一篇文章说清楚头条“限流”那些事儿

相信很多创作者都遇到辛苦写的微头条没有展现,也没有阅读量的情况,有些创作者知道这

抖音限流原因归纳总结与破解之道

抖音限流原因归纳总结与破解之道

2022年随着5G的来临,短视频作为目前最高阶最有效的信息展现方式,风口期必将持续不断

5种限流算法,7种限流方式,挡住突发流量?

5种限流算法,7种限流方式,挡住突发流量?

最近几年,随着微服务的流行,服务和服务之间的依赖越来越强,调用关系越来越复杂,服

主流的四种限流策略,我都可以通过redis实现

主流的四种限流策略,我都可以通过redis实现

引言在web开发中功能是基石,除了功能以外运维和防护就是重头戏了。因为在网站运行期

商业洽谈 文章投递 寻求报道
电话咨询: 15924191378
关注微信