- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
限流顾名思义是对流量大小进行限制,防止请求数量超过系统的负载能力,导致系统崩溃,起到保护作用。 现实生活中限流也随处可见,节假日出门旅行的人数会剧增,对于旅游景点来说往往会不堪重负,如果不进行人数控制,对整个景点的压力会非常大,游客的体验也会非常差,还容易出现安全事故等危险。 同样的在一线城市地铁限流也非常常见,早高峰为了控制乘车人数和有序进站,地铁往往会在地铁口进行拦截,一定时间内才放行一部分人进站乘车.
具体到程序,限流可以有以下几种场景 。
限流起到了保护作用,那么如何限呢?如果限制得太严,保护是保护到了,但是系统的处理能力下降了,体验会很差;如果限制得太松,就会被一些突增流量冲击到,或者被黑客利用进行安全攻击。如何限流需要根据系统的负载来评估,系统的负载和处理能力是动态的,例如平时的qps是1000,双11一般会进行扩容,也就是加服务节点,qps可能就是5000,这个时候系统处理能力变强的,限流策略也应该相应的调整。还有一种是出于安全的限流,例如同一个客户端ip 1s内对系统发出上万次请求,这种可以确定就是安全攻击,很可能是有人恶意破坏,或者是一些爬虫,这种可以限制请求数,超出的就直接拒绝。 如何限流是限流算法要实现的,常见的限流算法有“两桶两窗”,固定窗口、滑动窗口、漏桶与令牌桶,接下来介绍这四种算法及应用.
固定窗口的思想和实现非常简单,就是统计每个固定每个时间窗口的请求数,超过则拒绝。 如图我们定义了窗口大小为1s,最大请求数100,窗口内超过100的请求数将被拒绝。实现上也非常简单,利用redis的incr自增计数,当前时间秒作为缓存key,每次自增后判断是否超过指定大小即可。 固定窗口的问题是容易出现“突刺现象”,例如在1s内,100个请求都是在前100ms过来的,那么后面的900ms的请求都会被拒绝,而系统此时是空闲的。另外还有“临界问题”,如果100个请求是在后100ms过来的,而下一个1s的100个请求在前100ms过来,此时系统在这200ms内就需要处理200个请求,跟我们想要的不符合。到这里我们很容易想到,1s这个范围太大了,缩小一些就更好了,这种把固定窗口拆成更多个小窗口的做法就是滑动窗口算法了.
滑动窗口的思想是将固定窗口拆成更多个小窗口,随着时间的推移,窗口不断的滑动,统计也在不断的变化。窗口拆分的越多,滑动就会越平滑,统计就会越精确,所消耗的资源就会越多。滑动窗口如果只拆为1个窗口,就退化为固定窗口。 滑动窗口算法可以解决上面固定窗口的问题,像hystrix和sentinel中都使用该算法进行数据统计,用于限流熔断等策略处理。如hystrix中图所示,在一个窗口内拆分了10个桶(bucket),随着时间的推移,会创建新的桶也会丢弃过期的桶,当然窗口的大小和拆分桶的数量都是可配置的.
漏桶算法的思想是将请求先放到一个桶中,然后像滴水一样不断的从中取出请求执行,桶满则溢,后面的请求会被拒绝.
漏桶算法的特点是流入速度不确定,但是流出速度是确定的,漏桶可以很平滑,均衡的处理请求,但是无法应对短暂的突发流量.
令牌桶算法的思想是不断的生成令牌放到一个桶中,请求到来时到桶中申请令牌,申请得到就执行,申请不到就拒绝。如果桶中的令牌满了,新生成的令牌也会丢弃.
与漏桶不同的是,令牌桶是流入速度确定(生成令牌的速度),流出速度不确定,所以它不想漏桶一样可以均衡的处理请求,但是由于有令牌桶这个缓冲,一旦有突增的流量,令牌桶里已有的令牌可以短暂的应对突发流量,由于流出速度是不限制的,此时桶中已有的令牌都可以被申请到,请求一下子就会到我们的服务,给系统带来一定的压力,所以桶的大小需要合适,不宜过大。举个栗子:令牌桶的大小是1000,每秒放100个令牌,经过一段时间后,请求有空闲时,桶里的令牌就会积压,最终保存了满1000个令牌,由于某刻流量突增,有1000个请求到来,此时能申请到1000个令牌,所有请求都会放行,最终达到我们的系统,如果令牌桶过大,系统可能会承受不了这波请求.
guava限流实现的是桶算法,通过RateLimiter.create创建,可以创建两种类型的限流器,SmoothBursty和SmoothWarmingUp,前者定时生成令牌,后者有一个预热的过程。 我们如下示例代码,每秒会创建2个令牌,并且初始化的时候就是2。定时器每200ms会申请一次令牌,每秒申请5次,只有2次成功,所有运行程序每秒有3次success和2次fail.
RateLimiter rateLimiter = RateLimiter.create(2);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (rateLimiter.tryAcquire()) {
System.out.println("success");
} else {
System.out.println("fail");
}
}
}, 0, 200);
既然是桶,那么桶的大小是多少呢?SmoothBursty里最大令牌数由maxPermits字段表示,该字段等于maxBurstSeconds * permitsPerSecond,permitsPerSecond是每秒要生成的令牌数,maxBurstSeconds默认是1。 另外还可以创建SmoothWarmingUp带有预热功能的限流器,预热的作用是通过一个过程才达到permitsPerSecond,相当于让系统有个热身的时间.
RateLimiter rateLimiter = RateLimiter.create(5, 10, TimeUnit.MILLISECONDS);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
log.info("" + rateLimiter.acquire());
}
}, 0, 200);
rateLimiter.acquire()返回的是获取打令牌的时间,运行程序可以看到开始并不是每秒都能产生5个令牌,也就是不是能立刻获取到令牌,获取令牌需要的时间会越来越小,直到预热期过后就能立马获取到令牌了。 guava的限流只能提供单机版的实现,对于集群就无能为力了,并且它通常作为一个工具存在,使用还需要自己封装,集成到服务,并不能开箱即用.
bucket4j是一个java实现,基于令牌桶算法的限流组件。它支持分布式限流,支持多种存储,可以方便与各种框架和监控集成。github上start 1.2K,但是issues数量少,国内估计使用的人也不多,并且官方的实现存储不支持最常用的redis,它专注于限流,如果是自研或者二次开发,是一个很好的参考.
之前我们介绍过它的 熔断功能 ,Resilience4j也提供了限流的实现,可以参考 这里 。相比guava,Resilience4j是框架级别的,可以很方便的使用。但Resilience4j也是单机版的实现,无法支持集群功能。 Resilience4j限流实现的是令牌桶,如下配置,每1s会生成10个令牌.
resilience4j.ratelimiter:
instances:
backendA:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0
registerHealthIndicator: true
eventConsumerBufferSize: 100
流量控制是sentinel最重要的一个功能,sentinel属于后起之秀,文档齐全,支持的场景更加丰富。sentinel支持集群限流,也可以像guava一样预热,还可以基于调用链路进行限流。 sentinel还提供了控制台功能,支持多种数据源的持久化,使用spring cloud的话可以通过spring cloud alibaba引入sentinel。 开源版的sentinel有一些限制,并且使用起来并不是那么方便,例如Resilience4j可以配置一个default针对所有的请求生效,但sentinel需要单个单个url去配置,显得非常麻烦,包括熔断feign接口的配置也是,这个给spring cloud alibaba提了 feature ,也许在下一个版本就会提供支持.
上面讲到的都是应用级别的限流,nginx通常作为网络请求的入口,从运维的角度来说,在这里做限流再合适不过,nginx本身也提供了限流的支持。 nginx比较适合对外的限流,但是我们内部不同系统间的调用一遍不经过nginx,会直接访问到对方的网关,所以两者并不矛盾。 nginx限流通过limit_req和limit_conn两个模块支持,分别对应请求限制和链接限制(一个链接可以有多个请求).
http {
limit_req_zone zone=name:10m rate=100r/s;
server {
location /app/ {
limit_req zone=name burst=500 nodelay;
}
}
如上,定义了一个name zone,访问速率最高是100个每秒,/app路径应用了这个规则。busrt表示爆发的意思,是一个缓冲队列,用于存储突增的请求,这些请求会被缓存不会拒绝,如果超过了burst,nodelay表示不等待直接拒绝。 前面我们说到有些恶意攻击可能每秒发送上万个请求,导致服务崩溃,如果多个应用系统共用一个nginx,那么可以统一在nginx配置处理,不需要每个系统自己去实现.
limit_conn_zone $binary_remote_addr zone=name:10m;
server {
limit_conn name 50;
}
如上,定义了一个name zone,$binary_remote_addr表示远端地址,也就是ip,10m表示存储空间,10m大概可以存储16w的ip地址,我们在server节点应用这个规则,50表示最多50个,超过就会拒绝.
最后此篇关于常见限流算法的文章就讲到这里了,如果你想了解更多关于常见限流算法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
新建表: create table [表名] ( [自动编号字段] int IDENTITY (1,1)&nbs
我的文件中有正在本地化的字符串。其中许多是常见的,并且已经在整个 iOS 中使用。例如。 “保存”、“加载”、“返回”、“收藏夹”、“拍照”。为了与其他应用程序和内置应用程序提供一致的用户体验,是否有
我已经学习了 Qt 的基础知识,现在对这个漂亮的库的深度感兴趣。请帮助我理解: 所有类都是从QObject派生的吗? 为什么可以在QWidget(和派生类)上绘画? return app.exec()
我在 webpack 中设置了一个自调用函数,并使用常见的 JS 来需要一些包: (function() { var $ = require("jquery"); //...my functi
我正在尝试制作一个大量使用词性标记的应用程序。但是 nltk 的 pos 标记功能对我来说似乎不符合标准 - 例如: import nltk text = "Obama delivers his fi
有没有办法处理发送到 MySQL 的常见查询以防止不必要的带宽使用? 最佳答案 选项是: 使用MySQL缓存查询 好:全自动 差:仍然需要访问数据库服务器;有一次缓存让我在一个项目中失望,花了很长时间
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 4 年前。 Improve this qu
关闭。这个问题需要debugging details .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve this questio
我正在尝试调用返回 csv 文件的网络服务。因此,我调用的每个 URL 都有一个后缀,它是一个字符串,表示要生成哪个 csv。然后我想将此 csv 保存到文件中。有很多要生成,所以我从多个线程调用此类
流行手机型号支持的典型触摸点数量是多少?我在基础研究中看到低至 2 和高至 5,但我希望能够将其映射到实际手机和更好的限制! 最佳答案 两部手机的触控点数据: Galaxy S 5 LG
出于好奇 - 我知道有 LAMP - Linux、Apache、MySQL 和 PHP。但是还有哪些其他 Web 堆栈替代方案的缩写呢?像 LAMR - Linux、Apache、MySQL Ruby
我写了一个java代码(使用apache common vfs2)来上传文件到SFTP服务器。最近,我在我的服务器上引入了 PGP 安全性。现在,java 代码无法连接到该服务器。与 FileZill
由于 GLU 被认为对于现代 OpenGL (3.1+) 来说已经过时,那么使用 C/C++ 在 OpenGL 中绘制基本形状(例如椭圆或弧线/饼图)的方法是什么?令人难以置信的是,在 OpenGL
我想知道是否有最流行的 iOS 应用程序的自定义 URL 方案列表,例如 Keynote、Numbers、Pages、Evernote 等。我还想知道这些应用程序使用什么参数网址。 我需要这个的原因是
我正在使用 NDK r10d 移植 C++ myToll Linux 应用程序以在 Android 上运行。 (请注意,这不是带有 apk 的 Android 应用程序,而是从 shell 运行的实用
假设您想要使用 UML 2 部署图为在该领域没有太多知识的人可视化一个常见的 PHP 服务器应用程序。这样一个通用的应用程序可能有三个设备节点(数据库服务器、Web 服务器和客户端)和四个执行环境节点
我正在尝试运行以下代码,以找到两个人之间的共同 friend 。输入如下 A : B C D B : A C D E C : A B D E D : A B C E E : B C D 我无法在输出文
我在 Gitolite 的 manual 中找到的唯一东西在钩子(Hook)上,是: If you want to add your own hook, it's easy as long as it
具体来说,我有一个问题,在 AWS 环境中组织 AZ 故障转移的推荐方法是什么。此外,最好了解典型的 AWS 故障以组织应用程序 HA(高可用性)。 因此,应用程序架构(AWS 服务使用)如下: 它或
我正在尝试编写一个通用的 SecurePagingAndSorting 存储库,它将检查 CRUD 操作的安全性,以节省在所有 JPA 存储库中重复相同的 PreAuthorize(使用不同的权限)。
我是一名优秀的程序员,十分优秀!