令牌桶算法

令牌桶(Token Bucket)

匿名 (未验证) 提交于 2019-12-02 23:39:01
概要   限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。 令牌桶算法   令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 当桶满时,新添加的令牌被丢弃或拒绝。 令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。令牌桶算法基本可以用下面的几个概念来描述: 令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。 桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。 如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。 令牌算法是根据放令牌的速率去控制输出的速率,也就是上图的to network的速率。to network我们可以理解为消息的处理程序,执行某段业务或者调用某个RPC。 使用RateLimiter完成简单的大流量限流 import com.google.common.util.concurrent

实战限流(guava的RateLimiter)

匿名 (未验证) 提交于 2019-12-02 21:52:03
常用的限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法,也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或者取不到立即返回失败,下图来自网上: 本次实战,我们用的是guava的RateLimiter,场景是spring mvc在处理请求时候,从桶中申请令牌,申请到了就成功响应,申请不到时直接返回失败; 对于的源码可以在我的git下载,地址是:https://github.com/zq2599/blog_demos ,里面有多个工程,本次实战的工程为guavalimitdemo,如下图红框所示: 创建一个maven工程,在pom中把guava的依赖添加进来: <dependency> <groupId> com.google.guava </groupId> <artifactId> guava </artifactId> <version> 18.0 </version> </dependency> 把限流服务封装到一个类中AccessLimitService,提供tryAcquire()方法,用来尝试获取令牌,返回true表示获取到,如下所示: @Service public class AccessLimitService {

RateLimiter服务限流实现

匿名 (未验证) 提交于 2019-12-02 21:52:03
Ŀ¼ 1、针对单机的服务流量进行控制,避免突发大流量造成服务异常。2、对业务无侵入。 现在主流的几种限流方式: 通过限制单位时间段内调用量来限流 通过限制系统的并发调用程度来限流 使用漏桶(Leaky Bucket)算法来进行限流 (使用令牌桶(Token Bucket)算法来进行限流 通过限制某个服务的单位时间内的调用量来进行限流。我们需要做的就是通过一个计数器统计单位时间段某个服务的访问量,如果超过了我们设定的阈值, 则该单位时间段内则不允许继续访问,或者把接下来的请求放入队列中等待到下一个单位时间段继续访问。 优点:实现简单,阈值可动态配置。 缺点:若单位时间内前一小段时间内就被大流量消耗完,则将导致该时间段内剩余的时间都拒绝服务。该现象为:“突刺消耗”。 通过并发限制来限流,我们通过严格限制某服务的并发访问程度,其实也就限制了该服务单位时间段内的访问量, 比如限制服务的并发访问数是100,而服务处理的平均耗时是10毫秒,该服务每秒能提供( 1000 / 10 ) * 100 = 10,000 次。 优点:有更严格的限制边界,适合连接数、线程数的一个限制。 缺点:对服务来说,并发阈值调优困难,难以准确判定服务阈值设置多少合适。一般采用Semaphore实现,但Semaphore没有提供重设信号量的方法,所以阈值动态配置也是问题。 请求流量以不确定速率申请资源

常用限流算法

匆匆过客 提交于 2019-12-02 14:57:27
引言 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。今天我们要聊的就是限流(Rate Limit),限流的目的很简单,就是为了保护系统不被瞬时大流量冲垮, 限流这个概念我其实很早之前就有去了解过,不过无奈之前工作所接触业务的并发量实在是谈不上限流。目前公司大促峰值QPS在2w往上,自然而然需要用到限流,特别是类似秒杀这种瞬时流量非常大但实际成单率低的业务场景。 目前比较常用的限流算法有三种 计数器固定窗口算法 计数器滑动窗口算法 漏桶算法 令牌桶算法 计数器固定窗口算法 计数器固定窗口算法是最简单的限流算法,实现方式也比较简单。就是通过维护一个单位时间内的计数值,每当一个请求通过时,就将计数值加1,当计数值超过预先设定的阈值时,就拒绝单位时间内的其他请求。如果单位时间已经结束,则将计数器清零,开启下一轮的计数。 但是这种实现会有一个问题,举个例子: 假设我们设定1秒内允许通过的请求阈值是200,如果有用户在时间窗口的最后几毫秒发送了200个请求,紧接着又在下一个时间窗口开始时发送了200个请求,那么这个用户其实在一秒内成功请求了400次,显然超过了阈值但并不会被限流。其实这就是临界值问题,那么临界值问题要怎么解决呢? 代码实现 -- [CounterRateLimit.java](https://github.com/WangJunnan/learn/blob

Net Core的流控服务

强颜欢笑 提交于 2019-12-01 10:25:13
Net Core的流控服务 先前有一篇博文,梳理了流控服务的场景、业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发,并在生产系统进行了大半年的验证,稳定可靠。今天整理一下核心设计和实现思路,开源到Github上,分享给大家 https://github.com/zhouguoqing/FlowControl 一、令牌桶算法实现 先回顾一下令牌桶算法示意图 随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms) 往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水), 如果桶已经满了就不再加了. 新请求来临时, 会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务. 令牌添加速度支持动态变化,实时控制处理的速率. 令牌桶有两个关键的属性: 令牌桶容量(大小)和时间间隔, 有两个关键操作, 从令牌桶中取Token;令牌桶定时的Reset重置。 我们看TokenBucket类: using System; namespace CZ.FlowControl.Service { using CZ.FlowControl.Spi; /// <summary> /// 令牌桶 /// </summary> public abstract class TokenBucket :

慌了,大厂最后一面居然问我高并发系统下的限流?

拈花ヽ惹草 提交于 2019-12-01 05:11:33
开涛大神在博客中说过: 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流 。本文结合作者的一些经验介绍限流的相关概念、算法和常规的实现方式。 缓存 缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪。使用缓存不单单能够提升系统访问速度、提高并发访问量,也是保护数据库、保护系统的有效方式。大型网站一般主要是“读”,缓存的使用很容易被想到。在大型“写”系统中,缓存也常常扮演者非常重要的角色。比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及HBase写数据的机制等等也都是通过缓存提升系统的吞吐量或者实现系统的保护措施。甚至消息中间件,你也可以认为是一种分布式的数据缓存。 降级 服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。 限流 限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行

实战限流(guava的RateLimiter)

落花浮王杯 提交于 2019-11-30 04:20:56
关于限流 常用的限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法,也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或者取不到立即返回失败,下图来自网上: 本次实战,我们用的是guava的RateLimiter,场景是spring mvc在处理请求时候,从桶中申请令牌,申请到了就成功响应,申请不到时直接返回失败; 源码下载 对于的源码可以在我的git下载,地址是: https://github.com/zq2599/blog_demos ,里面有多个工程,本次实战的工程为guavalimitdemo,如下图红框所示: 实战开发 创建一个maven工程,在pom中把guava的依赖添加进来: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> 把限流服务封装到一个类中AccessLimitService,提供tryAcquire()方法,用来尝试获取令牌,返回true表示获取到,如下所示: @Service public class

使用Guava的RateLimiter做限流

谁都会走 提交于 2019-11-30 00:38:26
一、常见的限流算法 目前常用的限流算法有两个:漏桶算法和令牌桶算法。 1.漏桶算法 漏桶算法的原理比较简单,请求进入到漏桶中,漏桶以一定的速率漏水。当请求过多时,水直接溢出。可以看出,漏桶算法可以强制限制数据的传输速度。 2.令牌桶算法 令牌桶算法的原理是系统以一定速率向桶中放入令牌,如果有请求时,请求会从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务。这种算法可以应对突发程序的请求,因此比漏桶算法好。 在Wikipedia上,令牌桶算法是这么描述的: 每秒会有r个令牌放入桶中,或者说,每过1/r 秒桶中增加一个令牌 桶中最多存放b个令牌,如果桶满了,新放入的令牌会被丢弃 当一个n字节的数据包到达时,消耗n个令牌,然后发送该数据包 如果桶中可用令牌小于n,则该数据包将被缓存或丢弃 二、RateLimiter Guava中开源出来一个令牌桶算法的工具类RateLimiter,可以轻松实现限流的工作。RateLimiter对简单的令牌桶算法做了一些工程上的优化,具体的实现是SmoothBursty。需要注意的是,RateLimiter的另一个实现SmoothWarmingUp,就不是令牌桶了,而是漏桶算法。也许是出于简单起见,RateLimiter中的时间窗口能且仅能为1S,如果想搞其他时间单位的限流,只能另外造轮子。 RateLimiter有一个有趣的特性是

最近学习了限流与RateLimiter

♀尐吖头ヾ 提交于 2019-11-29 02:09:55
前言 分布式环境下应对高并发保证服务稳定几招,按照个人理解,优先级从高到低分别为缓存、限流、降级、熔断,每招都有它的作用,本文重点就讲讲限流这部分。 坦白讲,其实上面的说法也不准确,因为 服务降级、熔断本身也是限流的一种 ,因为它们本质上也是阻断了流量进来,但是本文希望大家可以把限流当做一个单纯的名词来理解,看一下对请求做流控的几种算法及具体实现方式。 为什么要限流 其实很好理解的一个问题,为什么要限流,自然就流量过大了呗,一个对外服务有很多场景都会流量增大: 业务用户量不断攀升 各种促销 网络爬虫 恶意刷单 注意这个"大",1000QPS大吗?5000QPS大吗?10000QPS大么?没有答案,因为没有标准,因此,"大"一定是和正常流量相比的大。流量一大,服务器扛不住,扛不住就挂了,挂了没法提供对外服务导致业务直接熔断。怎么办,最直接的办法就是从源头把流量限制下来,例如服务器只有支撑1000QPS的处理能力,那就每秒放1000个请求,自然保证了服务器的稳定,这就是限流。 下面看一下常见的两种限流算法。 漏桶算法 漏桶算法的原理比较简单,水(请求)先进入到漏桶里,人为设置一个最大出水速率,漏桶以<=出水速率的速度出水,当水流入速度过大会直接溢出(拒绝服务): 因此,这个算法的核心为: 存下请求 匀速处理 多于丢弃 因此这是一种 强行限制请求速率 的方式,但是缺点非常明显,主要有两点

RateLimiter服务限流实现

房东的猫 提交于 2019-11-28 21:45:55
目录 服务限流 需求 算法 通过限制单位时间段内调用量来限流 通过限制系统的并发调用程度来限流 漏桶算法 令牌桶算法 代码 限流设计 环境配置 配置文件 限流服务 切面拦截 测试 测试环境 测试结果 总结 服务限流 需求 1、针对单机的服务流量进行控制,避免突发大流量造成服务异常。2、对业务无侵入。 算法 现在主流的几种限流方式: 通过限制单位时间段内调用量来限流 通过限制系统的并发调用程度来限流 使用漏桶(Leaky Bucket)算法来进行限流 (使用令牌桶(Token Bucket)算法来进行限流 通过限制单位时间段内调用量来限流 通过限制某个服务的单位时间内的调用量来进行限流。我们需要做的就是通过一个计数器统计单位时间段某个服务的访问量,如果超过了我们设定的阈值, 则该单位时间段内则不允许继续访问,或者把接下来的请求放入队列中等待到下一个单位时间段继续访问。 优点:实现简单,阈值可动态配置。 缺点:若单位时间内前一小段时间内就被大流量消耗完,则将导致该时间段内剩余的时间都拒绝服务。该现象为:“突刺消耗”。 通过限制系统的并发调用程度来限流 通过并发限制来限流,我们通过严格限制某服务的并发访问程度,其实也就限制了该服务单位时间段内的访问量, 比如限制服务的并发访问数是100,而服务处理的平均耗时是10毫秒,该服务每秒能提供( 1000 / 10 ) * 100 = 10