我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么做高并发系统中的限流

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么做高并发系统中的限流

这篇文章主要介绍“怎么做高并发系统中的限流”,在日常操作中,相信很多人在怎么做高并发系统中的限流问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么做高并发系统中的限流”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

缓存

缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪。

使用缓存不单单能够提升系统访问速度、提高并发访问量,也是保护数据库、保护系统的有效方式。

大型网站一般主要是“读”,缓存的使用很容易被想到。在大型“写”系统中,缓存也常常扮演者非常重要的角色。

比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及HBase写数据的机制等等也都是通过缓存提升系统的吞吐量或者实现系统的保护措施。甚至消息中间件,你也可以认为是一种分布式的数据缓存。

降级

服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。

根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。

总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。

限流

限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。

一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。

限流的算法

常见的限流算法有:计数器、漏桶和令牌桶算法。

计数器

计数器是最简单粗暴的算法。

比如某个服务最多只能每秒钟处理100个请求。我们可以设置一个1秒钟的滑动窗口,窗口中有10个格子,每个格子100毫秒,每100毫秒移动一次,每次移动都需要记录当前服务请求的次数。

内存中需要保存10次的次数。可以用数据结构LinkedList来实现。格子每次移动的时候判断一次,当前访问次数和LinkedList中最后一个相差是否超过100,如果超过就需要限流了。

怎么做高并发系统中的限流

很明显,当滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。

示例代码如下:

//服务访问次数,可以放在Redis中,实现分布式系统的访问计数 Long counter = 0L; //使用LinkedList来记录滑动窗口的10个格子。 LinkedList<Long> ll = new LinkedList<Long>(); public static void main(String[] args) {   Counter counter = new Counter();   counter.doCheck(); } private void doCheck() {   while (true)   {     ll.addLast(counter);     if (ll.size() > 10)     {       ll.removeFirst();     }     //比较最后一个和第一个,两者相差一秒     if ((ll.peekLast() - ll.peekFirst()) > 100)     {       //To limit rate     }     Thread.sleep(100);   } }

漏桶算法漏桶算法即leaky bucket是一种非常常用的限流算法,可以用来实现流量整形(Traffic Shaping)和流量控制(Traffic  Policing)。

贴了一张维基百科上示意图帮助大家理解:

怎么做高并发系统中的限流

漏桶算法的主要概念如下:

  • 一个固定容量的漏桶,按照常量固定速率流出水滴;

  • 如果桶是空的,则不需流出水滴;

  • 可以以任意速率流入水滴到漏桶;

  • 如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

漏桶算法比较好实现,在单机系统中可以使用队列来实现(.Net中TPL  DataFlow可以较好的处理类似的问题,你可以在这里找到相关的介绍),在分布式环境中消息中间件或者Redis都是可选的方案。

令牌桶算法

令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。

令牌桶算法基本可以用下面的几个概念来描述:

  • 令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。

  • 桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。

  • 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。

  • 如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。

如下图:

怎么做高并发系统中的限流

令牌算法是根据放令牌的速率去控制输出的速率,也就是上图的to network的速率。to  network我们可以理解为消息的处理程序,执行某段业务或者调用某个RPC。

漏桶和令牌桶的比较

令牌桶可以在运行时控制和调整数据处理的速率,处理某时的突发流量。

放令牌的频率增加可以提升整体数据处理的速度,而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。

整体而言,令牌桶算法更优,但是实现更为复杂一些。

限流算法实现

Guava

Guava是一个Google开源项目,包含了若干被Google的Java项目广泛依赖的核心库,其中的RateLimiter提供了令牌桶算法实现:平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。

1. 常规速率:

创建一个限流器,设置每秒放置的令牌数:2个。返回的RateLimiter对象可以保证1秒内不会给超过2个令牌,并且是固定速率的放置。

达到平滑输出的效果

public void test() {      RateLimiter r = RateLimiter.create(2);   while (true)   {             System.out.println(r.acquire());    } }

上面代码执行的结果如下图,基本是0.5秒一个数据。拿到令牌后才能处理数据,达到输出数据或者调用接口的平滑效果。

acquire()的返回值是等待令牌的时间,如果需要对某些突发的流量进行处理的话,可以对这个返回值设置一个阈值,根据不同的情况进行处理,比如过期丢弃。

怎么做高并发系统中的限流

2. 突发流量:

突发流量可以是突发的多,也可以是突发的少。首先来看个突发多的例子。还是上面例子的流量,每秒2个数据令牌。如下代码使用acquire方法,指定参数。

System.out.println(r.acquire(2)); System.out.println(r.acquire(1)); System.out.println(r.acquire(1)); System.out.println(r.acquire(1));

得到如下类似的输出。


怎么做高并发系统中的限流

如果要一次新处理更多的数据,则需要更多的令牌。代码首先获取2个令牌,那么下一个令牌就不是0.5秒之后获得了,还是1秒以后,之后又恢复常规速度。

这是一个突发多的例子,如果是突发没有流量,如下代码:

System.out.println(r.acquire(1)); Thread.sleep(2000); System.out.println(r.acquire(1)); System.out.println(r.acquire(1)); System.out.println(r.acquire(1));

得到如下类似的结果:

怎么做高并发系统中的限流

等了两秒钟之后,令牌桶里面就积累了3个令牌,可以连续不花时间的获取出来。处理突发其实也就是在单位时间内输出恒定。

这两种方式都是使用的RateLimiter的子类SmoothBursty。另一个子类是SmoothWarmingUp,它提供的有一定缓冲的流量输出方案。

 RateLimiter r = RateLimiter.create(2,3,TimeUnit.SECONDS);  while (true) {      System.out.println(r.acquire(1));   System.out.println(r.acquire(1));   System.out.println(r.acquire(1));   System.out.println(r.acquire(1)); }

输出结果如下图,由于设置了缓冲的时间是3秒,令牌桶一开始并不会0.5秒给一个消息,而是形成一个平滑线性下降的坡度,频率越来越高,在3秒钟之内达到原本设置的频率,以后就以固定的频率输出。

图中红线圈出来的3次累加起来正好是3秒左右。这种功能适合系统刚启动需要一点时间来“热身”的场景。

怎么做高并发系统中的限流

Nginx

对于Nginx接入层限流可以使用Nginx自带了两个模块:

  • 连接数限流模块ngx_http_limit_conn_module

  • 漏桶算法实现的请求限流模块 ngx_http_limit_req_module

1. ngx_http_limit_conn_module

我们经常会遇到这种情况,服务器流量异常,负载过大等等。

对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力,影响业务,往往考虑对同一个ip的连接数,并发数进行限制。ngx_http_limit_conn_module  模块来实现该需求。

该模块可以根据定义的键来限制每个键值的连接数,如同一个IP来源的连接数。

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

我们可以在 nginx_conf 的 http{}中加上如下配置实现限制:

#限制每个用户的并发连接数,取名one limit_conn_zone $binary_remote_addr zone=one:10m;  #配置记录被限流后的日志级别,默认error级别 limit_conn_log_level error; #配置被限流后返回的状态码,默认返回503 limit_conn_status 503;

然后在 server{}里加上如下代码:

#限制用户并发连接数为1 limit_conn one 1;

然后我们是使用ab测试来模拟并发请求:ab -n 5 -c 5 http://10.23.22.239/index.html

得到下面的结果,很明显并发被限制住了,超过阈值的都显示503:

怎么做高并发系统中的限流

另外刚才是配置针对单个IP的并发限制,还是可以针对域名进行并发限制,配置和客户端IP类似。

#http{}段配置 limit_conn_zone $ server_name zone=perserver:10m; #server{}段配置 limit_conn perserver 1;

2. ngx_http_limit_req_module

上面我们使用到了ngx_http_limit_conn_module 模块,来限制连接数。那么请求数的限制该怎么做呢?

这就需要通过ngx_http_limit_req_module 模块来实现,该模块可以通过定义的键值来限制请求处理的频率。

特别的,可以限制来自单个IP地址的请求处理频率。限制的方法是使用了漏斗算法,每秒固定处理请求数,推迟过多请求。

如果请求的频率超过了限制域配置的值,请求处理会被延迟或被丢弃,所以所有的请求都是以定义的频率被处理的。

在 http{}中配置

#区域名称为one,大小为10m,平均处理的请求频率不能超过每秒一次。 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

在 server{}中配置

#设置每个IP桶的数量为5 limit_req zone=one burst=5;

上面设置定义了每个IP的请求处理只能限制在每秒1个。并且服务端可以为每个IP缓存5个请求,如果操作了5个请求,请求就会被丢弃。

使用ab测试模拟客户端连续访问10次:

ab -n 10 -c 10 http://10.23.22.239/index.html

如下图,设置了通的个数为5个。一共10个请求,第一个请求马上被处理。第2-6个被存放在桶中。由于桶满了,没有设置nodelay因此,余下的4个请求被丢弃。

怎么做高并发系统中的限流

到此,关于“怎么做高并发系统中的限流”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么做高并发系统中的限流

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

编程语言之高并发系统中限流的示例分析

这篇文章主要介绍了编程语言之高并发系统中限流的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。本文结合作者的
2023-05-30

golang高并发系统限流策略漏桶和令牌桶算法源码分析

本篇内容主要讲解“golang高并发系统限流策略漏桶和令牌桶算法源码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“golang高并发系统限流策略漏桶和令牌桶算法源码分析”吧!漏桶算法漏桶算法
2023-07-02

Mysql怎么用NOSql给高并发系统加速

本篇内容主要讲解“Mysql怎么用NOSql给高并发系统加速”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Mysql怎么用NOSql给高并发系统加速”吧!NoSQLNoSQL,泛指非关系型的数据
2023-06-02

软件系统中高并发的示例分析

这篇文章将为大家详细讲解有关软件系统中高并发的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述当前,数字化在给企业带来业务创新,推动企业高速发展的同时,也给企业的IT软件系统带来了严峻的挑战。面
2023-06-15

Linux系统怎么统计高速网络中的流量

今天就跟大家聊聊有关Linux系统怎么统计高速网络中的流量,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。尽管Linux系统中有许多流量监控工具,但是在用户空间做数据包截取的系统开销过
2023-06-28

Go 中的并发安全模板:我该怎么做?

Go 中的并发安全模板是一个关键问题,对于需要在并发环境下进行操作的程序来说,确保数据的安全性是至关重要的。在处理并发时,我们需要采取一些措施来保护共享资源,避免出现竞态条件和数据竞争。在这篇文章中,我将向大家介绍一些常用的并发安全模板,帮
Go 中的并发安全模板:我该怎么做?
2024-02-08

Java8中怎么正确高效的使用并行流

这篇文章主要为大家展示了“Java8中怎么正确高效的使用并行流”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java8中怎么正确高效的使用并行流”这篇文章吧。正确使用并行流,避免共享可变状态错用
2023-06-25

Java Semaphore怎么实现高并发场景下的流量控制

这篇文章主要介绍“Java Semaphore怎么实现高并发场景下的流量控制”,在日常操作中,相信很多人在Java Semaphore怎么实现高并发场景下的流量控制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-06-22

怎么更改win10系统中的应用权限

这篇文章主要介绍怎么更改win10系统中的应用权限,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!方法/步骤:1. 在桌面左下角点击“开始菜单”图标,随后选择“设置”选项进入。2.在以下的界面中选择“隐私”进入。3.此
2023-06-27

Go语言中如何处理并发文件的文件系统访问权限问题?

Go语言中如何处理并发文件的文件系统访问权限问题?在并发编程中,处理文件系统访问权限是一个重要的问题。在Go语言中,我们可以利用互斥锁(Mutex)和读写锁(RWMutex)来实现对文件的并发访问控制。本文将介绍如何使用互斥锁和读写锁来处理
2023-10-22

Go语言中如何处理并发文件的文件系统文件权限和ACL权限管理问题?

Go语言中如何处理并发文件的文件系统文件权限和ACL权限管理问题?在Go语言中,使用标准库中的os和os/user包可以轻松地处理文件系统文件权限和ACL权限的管理问题。在处理并发文件时,我们可以通过如下步骤来实现对文件权限的控制。获取文件
2023-10-22

Go语言中如何处理并发文件的文件系统文件权限和ACL权限管理问题

在Go语言中处理并发文件的文件系统文件权限和ACL权限管理问题,可以使用os包和syscall包中提供的函数和方法来实现。1. 文件系统文件权限:可以使用os包中的Chmod函数来更改文件的权限。示例代码如下:```gopackage ma
2023-10-09

xp系统中怎么开放guest远程关机的权限

这篇文章主要讲解了“xp系统中怎么开放guest远程关机的权限”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“xp系统中怎么开放guest远程关机的权限”吧!  单击“开始”菜单,单击“控制面
2023-06-14

编程热搜

目录