网站首页 > 技术教程 正文
引言
并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
什么是限流?
限流一个应用程序和使用的策略是一种架构上的决策,该决策会影响整个系统的设计。应该在应用程序设计早期阶段就考虑限流,因为将限流增加到一个已经实现的系统是很不容易的。
限流必须被快速地执行。系统必须有能力检测到活动的增加并且做出相应地反应。在负载消除后,系统也必须能够快速还原到原始状态。这要求持续地捕捉和监控相关恰当的性能数据。
如果某个服务需要暂时地拒绝用户请求,它应该返回某个特定错误码,以便于客户端应用程序明白某个操作被拒绝的原因是因为限流了。客户端应用程序可以等一段时间在重试请求。
当系统自动扩展时,限流可以被用来作为一个临时的措施。如果活动上的爆发是突然的并且预期不会很长时间,在某些情况下,最好是简单地限流,而不是去扩展,,因为扩展会增加运行时成本。
当系统自动扩展时,如果限流被用来作为一个临时的措施,并且如果资源需求增长特别快,系统可能不会继续工作——即使处于限流模式中。如果不能接受这种,考虑维护大容量的储备并且配置更有侵略性的自动扩展策略
接入层限流
接入层通常指请求流量的入口,该层的主要目的有:负载均衡、非法请求过滤、请求聚合、缓存、降级、限流、A/B测试、服务质量监控等等.
对于Nginx接入层限流可以使用Nginx自带了两个模块:连接数限流模块ngx_http_limit_conn_module和漏桶算法实现的请求限流模块ngx_http_limit_req_module。还可以使用OpenResty提供的Lua限流模块lua-resty-limit-traffic进行更复杂的限流场景。
limit_conn用来对某个KEY对应的总的网络连接数进行限流,可以按照如IP、域名维度进行限流。limit_req用来对某个KEY对应的请求的平均速率进行限流,并有两种用法:平滑模式(delay)和允许突发模式(nodelay)。
ngx_http_limit_conn_module
limit_conn是对某个KEY对应的总的网络连接数进行限流。可以按照IP来限制IP维度的总连接数,或者按照服务域名来限制某个域名的总连接数。但是记住不是每一个请求连接都会被计数器统计,只有那些被Nginx处理的且已经读取了整个请求头的请求连接才会被计数器统计。
配置示例:
================================
http {
limit_conn_zone$binary_remote_addr zone=addr:10m;
limit_conn_log_level error;
limit_conn_status 503;
...
server {
...
location /limit {
limit_conn addr 1;
}
================================
limit_conn:要配置存放KEY和计数器的共享内存区域和指定KEY的最大连接数;此处指定的最大连接数是1,表示Nginx最多同时并发处理1个连接;
limit_conn_zone:用来配置限流KEY、及存放KEY对应信息的共享内存区域大小;此处的KEY是“$binary_remote_addr”其表示IP地址,也可以使用如$server_name作为KEY来限制域名级别的最大连接数;
limit_conn_status:配置被限流后返回的状态码,默认返回503;
limit_conn_log_level:配置记录被限流后的日志级别,默认error级别。
limit_conn的主要执行过程如下所示:
1、请求进入后首先判断当前limit_conn_zone中相应KEY的连接数是否超出了配置的最大连接数;
2.1、如果超过了配置的最大大小,则被限流,返回limit_conn_status定义的错误状态码;
2.2、否则相应KEY的连接数加1,并注册请求处理完成的回调函数;
3、进行请求处理;
4、在结束请求阶段会调用注册的回调函数对相应KEY的连接数减1。
limt_conn可以限流某个KEY的总并发/请求数,KEY可以根据需要变化。
按照IP限制并发连接数配置示例:
首先定义IP维度的限流区域:
================================
limit_conn_zone $binary_remote_addrzone=perip:10m;
================================
接着在要限流的location中添加限流逻辑:
================================
location /limit {
limit_conn perip 2;
echo "123";
}
================================
即允许每个IP最大并发连接数为2。
使用AB测试工具进行测试,并发数为5个,总的请求数为5个:
================================
ab -n 5 -c 5 http://localhost/limit
================================
将得到如下access.log输出:
================================
[08/Jun/2016:20:10:51+0800] [1465373451.802] 200
[08/Jun/2016:20:10:51+0800] [1465373451.803] 200
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
================================
此处我们把access log格式设置为log_format main '[$time_local] [$msec] $status';分别是“日期日期秒/毫秒值响应状态码”。
如果被限流了,则在error.log中会看到类似如下的内容:
================================
2016/06/08 20:10:51 [error] 5662#0: *5limiting connections by zone "perip", client: 127.0.0.1, server: _,request: "GET /limit HTTP/1.0", host: "localhost"
================================
按照域名限制并发连接数配置示例:
首先定义域名维度的限流区域:
================================
limit_conn_zone $ server_name zone=perserver:10m;
================================
接着在要限流的location中添加限流逻辑:
================================
location /limit {
limit_conn perserver 2;
echo "123";
}
================================
即允许每个域名最大并发请求连接数为2;这样配置可以实现服务器最大连接数限制。
ngx_http_limit_req_module
limit_req是令牌桶算法实现,用于对指定KEY对应的请求进行限流,比如按照IP维度限制请求速率。
应用级限流
限流总并发/连接/请求数
对于一个应用系统来说一定会有极限并发/请求数,即总有一个TPS/QPS阀值,如果超了阀值则系统就会不响应用户请求或响应的非常慢,因此我们最好进行过载保护,防止大量请求涌入击垮系统。
如果你使用过Tomcat,其Connector其中一种配置有如下几个参数:
acceptCount:如果Tomcat的线程都忙于响应,新来的连接会进入队列排队,如果超出排队大小,则拒绝连接;
maxConnections:瞬时最大连接数,超出的会排队等待;
maxThreads:Tomcat能启动用来处理请求的最大线程数,如果请求处理量一直远远大于最大线程数则可能会僵死。
详细的配置请参考官方文档。另外如Mysql(如max_connections)、Redis(如tcp-backlog)都会有类似的限制连接数的配置。
限流总资源数
如果有的资源是稀缺资源(如数据库连接、线程),而且可能有多个系统都会去使用它,那么需要限制应用;可以使用池化技术来限制总资源数:连接池、线程池。比如分配给每个应用的数据库连接是100,那么本应用最多可以使用100个资源,超出了可以等待或者抛异常。
限流某个接口的总并发/请求数
如果接口可能会有突发访问情况,但又担心访问量太大造成崩溃,如抢购业务;这个时候就需要限制这个接口的总并发/请求数总请求数了;因为粒度比较细,可以为每个接口都设置相应的阀值。可以使用Java中的AtomicLong进行限流:
================================
try{
if(atomic.incrementAndGet() > 限流数) {
//拒绝请求
}
//处理请求
}finally{
atomic.decrementAndGet();
}
=========================================
适合对业务无损的服务或者需要过载保护的服务进行限流,如抢购业务,超出了大小要么让用户排队,要么告诉用户没货了,对用户来说是可以接受的。而一些开放平台也会限制用户调用某个接口的试用请求量,也可以用这种计数器方式实现。这种方式也是简单粗暴的限流,没有平滑处理,需要根据实际情况选择使用;
限流某个接口的时间窗请求数
即一个时间窗口内的请求数,如想限制某个接口/服务每秒/每分钟/每天的请求数/调用量。如一些基础服务会被很多其他系统调用,比如商品详情页服务会调用基础商品服务调用,但是怕因为更新量比较大将基础服务打挂,这时我们要对每秒/每分钟的调用量进行限速;一种实现方式如下所示:
================================
LoadingCache counter =
CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(newCacheLoader() {
@Override
publicAtomicLong load(Long seconds)throwsException {
return newAtomicLong(0);
}
});
longlimit =1000;
while(true) {
//得到当前秒longcurrentSeconds = System.currentTimeMillis() /1000;
if(counter.get(currentSeconds).incrementAndGet() > limit) {
System.out.println("限流了:"+ currentSeconds);
continue;
}
//业务处理
}
================================
我们使用Guava的Cache来存储计数器,过期时间设置为2秒(保证1秒内的计数器是有的),然后我们获取当前时间戳然后取秒数来作为KEY进行计数统计和限流,这种方式也是简单粗暴,刚才说的场景够用了。
解决方案
一个替代的自动扩展策略是只允许应用程序使用有限定上限的资源,当限定达到时,对应用程序限流。系统应该监控资源时如何使用的,这样才能当利用率超过阈值时,系统能够限流某个或多个用户的请求。这将会使得系统继续工作,并且满足任何存在的服务等级协议(SLAs)。
系统可以实现一些限流策略,包括:
拒绝某个在特定时间段内已经访问每秒n次以上的系统APIs的单独用户。这就要求系统计量每个租户或用户使用的资源。
禁用或降级一些非必要的服务功能,以便必要的服务能够以足够的资源无碍的运行。例如,如果应用程序是视频流输出,可以切换到某个低分辨率。
使用负载分级来平滑活动的容量。在某个多租户环境中,该方式将会减少对于每个租户的性能。如果系统必须支持混合不同SLAs的租户,对于高价值的租户的工作可能会立即被处理。对于其它租户的请求可能会被延迟,当消除了待办任务时,才去处理这些请求。优先级队列模式可以用来实现这种方式。
延迟低优先级应用程序或租户的操作。这些操作可以被挂起或限制,产生一个异常来通知租户系统繁忙和该操作应该等会重试。
总结
以 上就是我对Java开发大型互联网企业高并发限流特技问题及其优化总结,分享给大家,觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持!
最后,每一位读到这里的网友,感谢你们能耐心地看完。希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步!都能赢取白富美,走向架构师的人生巅峰!
想了解学习Java方面的技术内容以及Java技术视频的内容可加群:722040762 验证码:头条(06 必过)欢迎大家的加入哟!
猜你喜欢
- 2024-10-13 Nginx 多进程高并发、低时延、高可靠机制在滴滴缓存代理中的应用
- 2024-10-13 linux的TCP连接数量不能超过65535个,如何应对千万的并发的?
- 2024-10-13 Nginx实现高速并发处理的原理详解
- 2024-10-13 高并发下的Nginx限流实战(nginx并发能力是多少)
- 2024-10-13 nginx——控制 Nginx 并发连接数(nginx 并发限流)
- 2024-10-13 Nginx(七) 测试使CPU占用更多能否提升并发数
- 2024-10-13 Nginx凭啥子并发数可以达到3w!(nginx的并发量)
- 2024-10-13 nginx负载均衡-提升服务的并发能力
- 2024-09-28 服务器能承载3000人但来5000人!服务器宕机了!如何救
- 2024-09-28 让腾讯失眠大数据专家,一文带你读懂Linux与高并发,总计4.56G
你 发表评论:
欢迎- 最近发表
-
- Win10 TH2正式版官方ESD映像转换ISO镜像方法详解
- 使用iso镜像升级到Windows 10的步骤
- macOS Ventura 13.2 (22D49) Boot ISO 原版可引导镜像
- 安利一个用ISO镜像文件制作引导U盘的的小工具RUFUS
- CentOS 7使用ISO镜像配置本地yum源
- 用于x86平台的安卓9.0 ISO镜像发布下载:通吃I/A/N、完全免费
- AlmaLinux 9.6发布:升级工具、初步支持IBM Power虚拟化技术
- Rufus写入工具简洁介绍与教程(写入模式)
- 新硬件也能安装使用了,Edge版Linux Mint 21.3镜像发布
- 开源工程师:Ubuntu应该抛弃32位ISO镜像
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)