限流--单机限流

前边一篇《聊一聊限流》讲述了限流的原理和应用场景,以及两种常用的限流算法,此篇将详细讲一下限流的技术实现。由于现在的系统架构大多都变成了分布式架构,而非传统的单机架构,限流也就分成了两个粒度,单机限流和分布式限流,所谓单机限流也就是jvm级别限流,是请求已经进入了具体某一台服务器上了采取的一种限流方式和自我保护措施,而分布式限流主要是对客户端请求的一种管控,在应用入口层对请求做的一种访问限制,两种限流方式的区别在于限流的作用时机和控制粒度,分布式限流主要是在应用入口拦截,控制的是服务器集群的访问(比如nginx代理层限流),单机限流大多是在接口访问

层拦截,控制的是请求对接口的访问频率(接口限流),但是也不是绝对(分布式限流也可以做到接口限流),作用时机和粒度如下图:

此篇我们的主题是单机限流,分布式限流在后续篇章中会提到和讲解,所谓单机限流是针对传统应用单体架构的一种限流方式,单机限流的目的是应用的自我保护,举个例子:大家都乘过地铁,早晚高峰入口都会限流,因为地铁每次的接待能力有限,并且地铁站的容纳能力也有限,如果不限流那么会导致一下子很多乘客涌进地铁站,但是地铁一次性有接待不聊那么多人,就有可能产生争抢和踩踏等安全事件。如果把地铁站当做一个应用,那么这种情况就是不限流导致系统崩溃现象。

切回主题,单机限流也就是jvm限流,只能限制当前jvm中运行的应用程序,目前单机限流有很多种实现方式,常用的就是Guava的RateLimiter、Semaphore信号器和AomicInteger原子变量,具体每种方式的原理和使用方式,接下来将一一分析和描述。

一、Semaphore限流

Semaphore是jdk1.5引入并发包后的一个并发组件,其基于AQS实现同步控制,对于接口限流,Semaphore的实现有点类似令牌桶的思想,首先初始化允许并发访问的个数(可以理解为令牌数),然后每一次请求过来申请一个令牌,如果拿到就允许访问并执行后续逻辑,逻辑结束后释放令牌到令牌桶。具体的代码实现如下:

运行代码可以看到:

首次同时5个线程进来获得访问许可,然后执行逻辑,每个执行完,释放许可,其他线程获得后可以继续执行,总之会保证最大并发为5的访问量,从而达到了限流的效果。

二、AomicInteger限流

AomicInteger原子变量也是jdk1.5引入并发包中的一个构件,原理是使用CAS乐观锁的方式来修改变量的值,其实现限流的原理是设置一个初始大小为0的变量,然后再设置一个并发大小阈值,每次请求来的时候先判断当前原子变量的值有没有超过并发阈值,如果超过就报访问异常,否则允许访问并把原子变量CAS加1,逻辑执行结束时再通过CAS方式把原子变量的值减1,实现代码如下:

运行代码,结果如下:

使用线程池创建了10个线程并发访问exec方法,发现只有5个访问成功,使用 AomicInteger 简单粗暴超过域值就拒绝请求,可能只是瞬时的请求量高,也会拒绝请求。

AomicInteger和Semaphore相比,存在很明显的缺陷,如果是瞬时的高并发,AomicInteger直接简单粗暴的拒绝了请求,而Semaphore可以使请求在阻塞队列中排队,而不是马上拒绝请求,可以实现一个流量削峰的目的。

三、Guava之RateLimiter限流

RateLimiter是基于令牌桶实现限流,和前边两种限流方式区别之处在于,AomicInteger和Semaphore更多关注于并发量的控制,而RateLimiter更注重于频率的控制,比如1秒内限制多少个请求,超过就拒绝或者阻塞到下一秒。代码如下:

运行代码,结果如下:

RateLimiter有两种常用的方法,acquire和tryAcquire,acquire是阻塞方式获取访问资格,如果超过每秒访问次数限制就阻塞到下一秒并返回等待的时间,tryAcquire是尝试获取访问资格且不阻塞,如果获取成功就返回true,否则返回false。从上述代码和运行结果中可以看到RateLimiter设置的访问速率是0.5,也

就是每秒允许0.5次访问,也即是两秒才允许一次访问,那么第一次请求后,过2秒钟才会允许下一次请求。

总结

通过上述一系列描述,我们对限流有了比较深刻的认识,对单机限流与分布式限流也有了初步的了解,通过AomicInteger和Semaphore以及RateLimiter编码实现限流,我们对各自的应用场景和优缺点也有了大致的掌握,希望在日常开发中有所帮助。至于分布式场景限流,将在后续篇幅讲述。

本文分享自微信公众号 - PersistentCoder(TyphoonChan),作者:叔牙

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊一聊限流

    1)旅游景点;很多人去过故宫,每逢节假日都会迎来人流高峰,为了维护秩序和安全,每天限定售票数量

    叔牙
  • 限流--分布式限流

    上一篇《限流--单机限流》讲述了单机限流的原理和技术实现,那么在现在分布式架构盛行的互联网时代,对于资源紧俏或者出于安全防范的目的,对一些核心的接口会做...

    叔牙
  • 基于多线程实现通用搜索

    说起搜索,大家心里边都有一些概念,我们平时使用的百度和谷歌,其实就是给我们拱了搜索的能力,当我们输入一个关键字点击搜索后,搜索引擎会返回给我们一大堆相关...

    叔牙
  • Spring Cloud 入门教程9、服务限流/API限流(Zuul+RateLimiter)

    RateLimiter是Google开源的实现了令牌桶算法的限流工具(速率限制器)。http://ifeve.com/guava-ratelimiter/

    KenTalk
  • Google平滑限流方案——Guava

    ·acceptCount:如果Tomcat的线程都忙于响应,新来的连接会进入队列排队,如果超出排队大小,则拒绝连接

    黑洞代码
  • 限流,永远都不是一件简单的事!

    随着微服务的流行,服务之间的稳定性变得越发重要,往往我们会花很多经历在维护服务的稳定性上,限流和熔断降级是我们最常用的两个手段。前段时间在群里有些小伙伴对限流的...

    用户5397975
  • Sentinel 集群限流设计原理

    为了充分利用硬件的资源,诸如 Dubbo 都提供了基于权重的负载均衡机制,例如可以将8C16G的机器设置的权重是4C8G的两倍,这样充分利用硬件资源,假如现在需...

    丁威
  • 高并发场景下如何实现系统限流?

    在分布式高可用设计中,限流应该是应用最广泛的技术手段之一,今天一起来讨论一下,为什么需要限流,以及常见的限流算法都有哪些。

    MickyInvQ
  • 微服务-高并发下接口如何做到优雅的限流

    通俗的来讲,一根管子往池塘注水,池塘底部有一个口子往外出水,当注水的速度过快时,池塘的水会溢出,此时,我们的做法换根小管子注水或者把注水管子的口堵住一半,这就是...

    阿伟
  • Java并发:分布式应用限流实践

    任何限流都不是漫无目的的,也不是一个开关就可以解决的问题,常用的限流算法有:令牌桶,漏桶。在之前的文章中,也讲到过,但是那是基于单机场景来写。

    搜云库技术团队

扫码关注云+社区

领取腾讯云代金券