在开发分布式高并发系统时有三把利器用来保护系统:缓存、降级、限流

缓存

缓存的目的是提升系统访问速度和增大系统处理容量

降级

降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再打开

限流

限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理

问题描述

1、某天A君突然发现自己的接口请求量突然涨到之前的10倍,没多久该接口几乎不可使用,并引发连锁反应导致整个系统崩溃。如何应对这种情况呢?生活给了我们答案:比如老式电闸都安装了保险丝,一旦有人使用超大功率的设备,保险丝就会烧断以保护各个电器不被强电流给烧坏。同理我们的接口也需要安装上“保险丝”,以防止非预期的请求对系统压力过大而引起的系统瘫痪,当流量过大时,可以采取拒绝或者引流等机制。

2、缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页),因此需有一种手段来限制这些场景的并发/请求量,即限流。

3、系统在设计之初就会有一个预估容量,长时间超过系统能承受的TPS/QPS阈值,系统可能会被压垮,最终导致整个服务不够用。为了避免这种情况,我们就需要对接口请求进行限流。

4、限流的目的是通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待。

5、一般开发高并发系统常见的限流模式有控制并发和控制速率,一个是限制并发的总数量(比如数据库连接池、线程池),一个是限制并发访问的速率(如nginx的limitconn模块,用来限制瞬时并发连接数),另外还可以限制单位时间窗口内的请求数量(如Guava的RateLimiter、nginx的limitreq模块,限制每秒的平均速率)。其他还有如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。

相关概念:

PV:

page view 页面总访问量,每刷新一次记录一次。

UV:

unique view 客户端主机访问,指一天内相同IP的访问记为1次。

QPS:

query per second,即每秒访问量。qps很大程度上代表了系统的繁忙度,没次请求可能存在多次的磁盘io,网络请求,多个cpu时间片,一旦qps超过了预先设置的阀值,可以考量扩容增加服务器,避免访问量过大导致的宕机。

RT:

response time,每次请求的响应时间,直接决定用户体验性。

本文主要介绍应用级限流方法,分布式限流、流量入口限流(接入层如NGINX limitconn和limitreq 模块)。

应用级限流

一、控制并发数量

属于一种较常见的限流手段,在实际应用中可以通过信号量机制(如Java中的Semaphore)来实现。操作系统的信号量是个很重要的概念,Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

举个例子,我们对外提供一个服务接口,允许最大并发数为10,代码实现如下:

在以上代码中,虽然有30个线程在执行,但是只允许10个并发的执行。Semaphore的构造方法Semaphore(int permits) 接受一个整型的数字,表示可用的许可证数量。Semaphore(10)表示允许10个线程获取许可证,也就是最大并发数是10。Semaphore的用法也很简单,首先线程使用Semaphore的acquire()获取一个许可证,使用完之后调用release()归还许可证,还可以用tryAcquire()方法尝试获取许可证,信号量的本质是控制某个资源可被同时访问的个数,在一定程度上可以控制某资源的访问频率,但不能精确控制,控制访问频率的模式见下文描述。

二、控制访问速率

在工程实践中,常见的是使用令牌桶算法来实现这种模式,常用的限流算法有两种:漏桶算法和令牌桶算法。

漏桶算法

漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。

对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。

令牌桶算法

如图所示,令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务,令牌桶算法通过发放令牌,根据令牌的rate频率做请求频率限制,容量限制等。

在Wikipedia上,令牌桶算法是这么描述的:

1、每过1/r秒桶中增加一个令牌。

2、桶中最多存放b个令牌,如果桶满了,新放入的令牌会被丢弃。

3、当一个n字节的数据包到达时,消耗n个令牌,然后发送该数据包。

4、如果桶中可用令牌小于n,则该数据包将被缓存或丢弃。

令牌桶控制的是一个时间窗口内通过的数据量,在API层面我们常说的QPS、TPS,正好是一个时间窗口内的请求量或者事务量,只不过时间窗口限定在1s罢了。以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。令牌桶的另外一个好处是可以方便的改变速度,一旦需要提高速率,则按需提高放入桶中的令牌的速率。

在我们的工程实践中,通常使用Google开源工具包Guava提供的限流工具类RateLimiter来实现控制速率,该类基于令牌桶算法来完成限流,非常易于使用,而且非常高效。如我们不希望每秒的任务提交超过1个

首先通过RateLimiter.create(1.0);创建一个限流器,参数代表每秒生成的令牌数,通过limiter.acquire(i);来以阻塞的方式获取令牌,令牌桶算法允许一定程度的突发(允许消费未来的令牌),所以可以一次性消费i个令牌;当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)来设置等待超时时间的方式获取令牌,如果超timeout为0,则代表非阻塞,获取不到立即返回,支持阻塞或可超时的令牌消费。

从输出来看,RateLimiter支持预消费,比如在acquire(5)时,等待时间是4秒,是上一个获取令牌时预消费了3个两排,固需要等待3*1秒,然后又预消费了5个令牌,以此类推。

RateLimiter通过限制后面请求的等待时间,来支持一定程度的突发请求(预消费),在使用过程中需要注意这一点,Guava有两种限流模式,一种为稳定模式(SmoothBursty:令牌生成速度恒定,平滑突发限流),一种为渐进模式(SmoothWarmingUp:令牌生成速度缓慢提升直到维持在一个稳定值,平滑预热限流) 两种模式实现思路类似,主要区别在等待时间的计算上。

SmoothBursty 模式:

RateLimiter limiter = RateLimiter.create(5); RateLimiter.create(5)表示桶容量为5且每秒新增5个令牌,即每隔200毫秒新增一个令牌;limiter.acquire()表示消费一个令牌,如果当前桶中有足够令牌则成功(返回值为0),如果桶中没有令牌则暂停一段时间,比如发令牌间隔是200毫秒,则等待200毫秒后再去消费令牌,这种实现将突发请求速率平均为了固定请求速率。

SmoothWarmingUp模式:

RateLimiter limiter = RateLimiter.create(5,1000, TimeUnit.MILLISECONDS);

创建方式:

RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit),permitsPerSecond表示每秒新增的令牌数,warmupPeriod表示在从冷启动速率过渡到平均速率的时间间隔。速率是梯形上升速率的,也就是说冷启动时会以一个比较大的速率慢慢到平均速率;然后趋于平均速率(梯形下降到平均速率)。可以通过调节warmupPeriod参数实现一开始就是平滑固定速率。

放在Controller中用Jemter压测

注:RateLimiter控制的是速率,Samephore控制的是并发量。RateLimiter的原理就是令牌桶,它主要由许可发出的速率来定义,如果没有额外的配置,许可证将按每秒许可证规定的固定速度分配,许可将被平滑地分发,若请求超过permitsPerSecond则RateLimiter按照每秒 1/permitsPerSecond 的速率释放许可。注意:RateLimiter适用于单体应用,且RateLimiter不保证公平性访问。

使用上述方式使用RateLimiter的方式不够优雅,自定义注解+AOP的方式实现(适用于单体应用),详细见下面代码:

自定义注解

自定义切面类

测试controller

压测结果:

三、控制单位时间窗口内请求数

某些场景下,我们想限制某个接口或服务 每秒/每分钟/每天 的请求次数或调用次数。例如限制服务每秒的调用次数为50,实现如下:

到此应用级限流的一些方法就介绍完了。假设将应用部署到多台机器,应用级限流方式只是单应用内的请求限流,不能进行全局限流。因此我们需要分布式限流和接入层限流来解决这个问题。

分布式限流

自定义注解+拦截器+Redis实现限流 (单体和分布式均适用,全局限流)

自定义注解:

拦截器:

controller:

配置文件:

访问效果如下,10s内访问接口超过4次以上就过滤请求,原理和计数器算法类似:

接入层限流

主要介绍nginx 限流,采用漏桶算法。

限制原理:可一句话概括为:“根据客户端特征,限制其访问频率”,客户端特征主要指IP、UserAgent等。使用IP比UserAgent更可靠,因为IP无法造假,UserAgent可随意伪造。

用limit_req模块来限制基于IP请求的访问频率:

http://nginx.org/en/docs/http/ngxhttplimitreqmodule.html

也可以用tengine中的增强版:

http://tengine.taobao.org/documentcn/httplimitreqcn.html

1、并发数和连接数控制的配置:

2、ngxhttplimitconnmodule 可以用来限制单个IP的连接数:

ngxhttplimitconnmodule模块可以按照定义的键限定每个键值的连接数。可以设定单一 IP 来源的连接数。

并不是所有的连接都会被模块计数;只有那些正在被处理的请求(这些请求的头信息已被完全读入)所在的连接才会被计数。

以上文章部分出自网络,参考链接如下:

https://blog.csdn.net/fanrenxiang/article/details/80683378

https://blog.csdn.net/top_code/article/details/53242262

https://blog.csdn.net/u010889390/article/details/82151903

最后给大家分享:

Java面试题总结+各知识点学习思维导图

资料获取方式:私信发送【资料】获取资料

希望能帮助到你面试前的复习且找到一个好的工作,也节省你在网上搜索资料的时间来学习。

最后

欢迎大家一起交流,喜欢文章记得关注我点赞转发哟,感谢支持!

api压测工具_高并发之API接口,分布式,防刷限流,如何做?相关推荐

  1. web版本 开源压测工具_免费压测工具

    很多的web应用在搭建服务器完成后,为了让搭建的服务能够满足用户的访问需求,通常需要测试自己应用的并发连接能力.需要使用一些压测工具,本文介绍一些免费的开源的压测工具,可以用于简单的压力测试(实验均在 ...

  2. python 压测工具_流量压测工具 | 亚马逊AWS官方博客

    (可用于测试AWS ELB.EC2.Auto Scaling.HA) 一群勤劳的小蜜蜂 很多时候我们需要进行负载均衡.Web服务器的并发式压力测试,但像Siege, JMeter等工具都是从一个源IP ...

  3. jdk自带压测工具_压测工具JMeter的使用

    最近接了压测的需求,顺带熟悉下压测工具的使用.这里推荐JMeter,安装快捷.请求方便,省了一大堆麻烦的事情.Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做 ...

  4. tcp压测工具_【解决方案】性能压测及分析调优实践

    [关键导读]结合一次重保活动的性能压测需求,详解了整体的性能测试策略及性能分析思路,并在实施过程中有效利用了网易易测的NPT性能测试平台一站式完成了压测场景设计.执行.业务指标监控.性能指标分析等活动 ...

  5. web版本 开源压测工具_标星 1.3K 的 Web 框架压测库,助你更好的选择框架

    大家好,我是你们的章鱼猫. 目前开源界有很多的 Web 框架,而一款好的 Web 框架能够给你在开发效率和后期维护上减少很多不必要的麻烦.所以在项目初期选择一款好的 Web 框架至关重要. 在 Go ...

  6. web版本 开源压测工具_开源了一个简单的http服务压测工具Alex,自带web ui,golang实现...

    Alex是基于vegeta library和boom封装的压力测试web UI.Vegeta提供稳定的qps压力源,boom提供稳定的并发数压力源. github地址 https://github.c ...

  7. java常用压测工具_几款常用压测工具推荐

    ab ab是apache自带的压力测试工具,使用起来非常方便. 安装 如果安装了apache, 那么ab已经安装好了,如果不想安装apache的话,可以通过以下方式安装ab # ubuntu sudo ...

  8. java 压测工具_几款常用压测工具推荐

    ab ab是apache自带的压力测试工具,使用起来非常方便. 安装 如果安装了apache, 那么ab已经安装好了,如果不想安装apache的话,可以通过以下方式安装ab # ubuntu sudo ...

  9. 高并发之API接口,分布式,防刷限流,如何做?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 在开发分布式高并发系统时有三把利器用来保护系统:缓存.降级 ...

最新文章

  1. Atitit r2017 r6 doc list on home ntpc.docx
  2. 一篇文章搞定GVIM(根据工作经验持续更新)
  3. 怎样使用OpenCV进行人脸识别
  4. armv8的Serror的理解
  5. Leave List-Processing 新解
  6. 王爽《汇编语言第三版》实验10-1代码实现
  7. Hive元数据信息表详解
  8. ubuntu系统备份和还原_如何使用Aptik在Ubuntu中备份和还原您的应用程序和PPA
  9. socket io 不使用redis_Redis这么快,线程模型竟然是单线程
  10. 软件工程 - 设计模式学习之工厂方法模式Factory Method
  11. 解决 unity 2d 中人物碰撞后抖动旋转问题
  12. linux发布微软消息队列,消息队列RabbitMQ入门与5种模式详解
  13. 大数据可视化平台有什么特点
  14. [纯前端]打造自己的ORK管理软件
  15. NanoPC-T4 RK3399和PC有线本地网络传输摄像头视频python
  16. 在JSP中使用CELL插件
  17. python画折线统计图画区间_matplotlib-折线图、散点图
  18. Unity 本地化比较实用的实现方案
  19. RGB 和 CYMK 的区别
  20. Unity多选题功能开发

热门文章

  1. 【Elasticsearch】实施现代电子商务搜索
  2. 【linux】Grok Debugger本地安装过程
  3. 【Elasticsearch】es 5.3.0 bulk index 性能调优实践
  4. 【MySQL】MySQL RROR! The server quit without updating PID file
  5. 【Linux】性能优化-linux命令nicstat 网络性能监控
  6. 【Kafka】kafka消费 Increase the fetch size, or decrease the maximum message size the broker will allow
  7. 【Spark】Spark ListenerBus 和 MetricsSystem 体系分析
  8. java : JSR107缓存规范
  9. Flink】Flink连接prometheus 端口报错 Invalid host/port configuration. Host xxx Port -1
  10. typora设置代码不自动换行