常见的限流方式有:

  • 限制总并发数(数据库连接池、线程池等等)

  • 限制瞬时并发数(如Nginx的limit_conn模块)

  • 限制时间窗口的平均速率(如Guava的RateLimiter、Nginx的limit_req模块)

  • 限制远程接口的调用速率、限制消息系统的消费速率

1.1 接入层限流

抗疫项目中,一般ISV会把Nginx作为业务的接入层,通过Nginx将请求分发到后端的应用集群上。接入层(流量层)是整个系统的咽喉入口, 越早挡掉请求越好,扛不住的流量越往后端传递,对后端的压力越大。

1.1.1 Nginx限流

官方提供两个模块:

  • limit_conn模块 (限制瞬时并发数)

  • limit_req模块 (限制单位时间内的请求数,速率限制,采用的漏桶算法)

limit_req

某口罩预约项目NG限流配置:

http {
......
# $binary_remote_addr 通过remote_addr这个标识来做限制
# zone=xxx:10m 生成一个大小为10M,名字为xxx的内存区域,用来存储访问的频次信息,64位可以存放163840个IP地址。
# rate=xx r/s 限制相同标识的客户端的访问频次
limit_req_zone $binary_remote_addr zone=req_perip:10m rate=30r/m; #30r/m: 限制两秒钟一个请求
limit_req_zone $binary_remote_addr zone=req_query:10m rate=5r/s; #5r/m: 限制每秒五个请求
}
server {
location /mask-appointment-service/appointment/ {
......
limit_req zone=req_perip burst=4; # 通过req_perip区域来限制
limit_req_status 507;      # 限流返回值507
......
}
location /mask-appointment-service/query/ {
......
limit_req zone=req_query; # 通过req_query区域来限制
limit_req_status 509;     # 限流返回值507
......
}
}

上述Nginx配置分别配置了 limit_req 两个规则,预约 和 查询。

  • 预约: 针对某个唯一的来源IP做速率的控制,速率为30r/m(每2秒1个请求)。

  • 查询: 针对某个唯一的来源IP做速率的控制,速率为5r/s (每1秒5个请求)。

特别注意:

rate=30r/m 很多时候会让人理解成每分钟30个请求, 其实并不是。官网的解释:

速率以每秒请求数r/s的形式指定。如果希望速率小于每秒一个请求,可以按每分钟请求数 r/m 来指定。例如,每秒半个请求为: 30r/m。

The rate is specified in requests per second (r/s). If a rate of less than one request per second is desired, it is specified in request per minute (r/m). For example, half-request per second is 30r/m.

几个写法含义:

limit_req_zone $binary_remote_addr zone=limit_login:10m rate=10r/m;

代表单ip每6秒1个请求(60/10=6)

limit_req_zone $binary_remote_addr zone=limit_login:10m rate=20r/m;

代表单ip每3秒1个请求(60/20=3)

limit_req_zone $binary_remote_addr zone=limit_login:10m rate=30r/m;

代表单ip每2秒1个请求(60/30=2)(官方文档叫half-request per second 1秒半个请求)

limit_req_zone $binary_remote_addr zone=limit_login:10m rate=1r/s;

代表单ip每秒1个请求

limit_req_zone $binary_remote_addr zone=limit_login:10m rate=2r/s;

代表单ip每秒2个请求

PS:

size ?该如何设置呢?

一个二进制的IP地址在64位机器上占用63个字节,设置10M的话: 10x1024x1024/64 = 163840,64位可以存放163840个IP地址。

limit_conn

limit_conn 这里不详细说了,有兴趣同学可以自行了解一下。

Nginx限流总结

Nginx属于接入层面,不能解决所有问题,比如内部调用的一些接口无法保证是否有限流控制,同时也只能挡掉http请求,比如rpc请求无法限制,所以在应用层实现限流还是很有必要的。上述Nginx限流都是对于单NG的,如果行业合作伙伴的接入层有多个Nginx,该怎么办呢?

  • 解决方案1: Nginx前面部署负载均衡,通过一致性哈希按照限流的key把请求转发到接入层的NG(相同key的请求打到同一台Nginx上)

  • 解决方案2: 通过 Nginx+Lua(OpenResty)调用分布式限流逻辑实现。

更多信息可以查看官方文档

[limit_req - Nginx] http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

[limit_conn - Nginx] http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

1.1.2 Openresty

有需要动态和精细控制的需求,可以通过Openresty做接入,OpenResty提供了lua-resty-limit-traffic 的Lua限流模块,基于Nginx的limit.conn和limit.req实现,通过可编程的方式进行复杂场景限流设计。比如变化限流速率,变化桶的大小等动态特性,可以按照更复杂的业务逻辑进行限流处理。

lua-resty-limit-traffic

resty.limit.req 模块

示例代码


local limit_req = require "resty,limit.req"
local lim, err = limit_req.new("mylimit", 5, 9)
local delay, err = lim:incoming(ngx.var.binary_remote_addr, true)
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
return ngx.exit(500)
end
if delay >= 0.001 then
ngx.sleep(delay)
end

resty.limit.req 和 Nginx 的 limit_req 实现的效果和功能一样,但是这里用 Lua 来表达限速逻辑,可以在别的代码里面去引入。

更多其它模块和用法可以查看官方文档:

[lua-resty-limit-traffic - Openresty] https://github.com/openresty/lua-resty-limit-traffic

1.1.3 四层限流

OSI 四层限流可以通过SLB、WAF等四层接入进行流量的限流,也可以通过F5等硬负载四层设备来实现对流量控制。四层流量控制异常设计的面比较大,一般情况下慎用。

1.1.4 API路由网关

在微服务架构中,API路由网关作为内部系统的入口,非常适合做API限流操作,网关层的限流可以简单地针对不同业务的接口进行限流。业界较有名的Zuul、Dubbo都可以对限流进行较好的设计,当然还有我们的 Sentinel开源方案,Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。这里就不详细说了,有需要查阅相关资料。

1.2 应用层限流

1.2.1 单机单应用限流

我们可以在服务器内部通过编写一些算法进行限流,也可以调用一些类库中存在的API,比如Google Guava类库的RateLimiter,Guava RateLimiter 是 Google Guava 提供的生产级别的限流工具,RateLimiter 基于令牌桶流控算法,可以有效控制 单 JVM 下某个逻辑操作的频率。

Guava 的 RateLimiter 提供了以下核心方法 create()acquire()tryAcquire(),其中 create() 创建令牌桶,acquire() 获取令牌,支持同时获取 N 个令牌,tryAcquire(long timeout, TimeUint unit)支持在限定时间内获取令牌,如果获取不到将返回 false。

示例代码如下:


import com.google.common.util.concurrent.RateLimiter;
public class GuavaRateLimiterDemo {
// 每秒 100 个令牌
private final RateLimiter rateLimiter = RateLimiter.create(100.0);
void doBusiness() {
rateLimiter.acquire();
// 继续操作用户业务
}
}

由于 acquire() 会一直等待,并且 Guava 不保证公平分发,所以会出现线程持续等待情况,需要考虑超时情况下面请求直接结束。

示例代码如下:


import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.TimeUnit;
public class GuavaRateLimiterDemo {
// 每秒 100 个令牌
private final RateLimiter rateLimiter = RateLimiter.create(100.0);
void doBusinessWithTryAcquire() {
boolean isPermit = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
if (!isPermit) {
throw new RuntimeException("business overheated.");
}
// 继续操作用户业务
}
}

RateLimiter 不仅实现了令牌桶,还做了不少优化,可以满足不同场景的需求。

它支持「预热」warmupPeriod,tryAcquire 操作还支持立即计算返回,避免无效等待。

更多信息可以查看官方文档

[RateLimiter (Guava: Google Core Libraries for Java 19.0 API)]) https://guava.dev/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html

缺点:

Guava RateLimiter(以及其他基于令牌桶算法的实现)缺点是只能针对单机,无法在分布式环境下面共享流量数据, 不适用于分布式服务。如果想使用的话,需要提前计算好每个示例负载均衡之后的流量阈值。

1.2.2 分布式限流

这一类的限流策略跟上面 API 路由网关模式的限流相似,同样是依赖配置中心管理,限流逻辑会配套服务化的框架完成。

抗击疫情-某口罩预约项目限流实战

2.1 挑战

在抗疫期间,我们联合政府机构,外部的合作伙伴紧急上线了口罩预约的服务。由于在疫情期间,口罩预约是个大热点,在开放预约入口1分钟内,预约系统面临着每秒峰值XX w+的并发压力。针对这种秒杀预约的场景,联合ISV对业务系统进行了一系列的改造优化, 这里我们重点来看看该项目是怎么通过不断消减请求和限流来保障流量突增时系统的稳定性的。

2.2 实战

2.2.1 第一层: 合法性限流拦截

在口罩预约开放时间段内,用户执行的第一个动作是填写预约信息,并获取手机验证码进行提交。我们可以在这一层就将不合法的请求给拦截掉(刷单行为、是否已登录,预约渠道是否合法), 允许合法的用户访问到服务器。

  1. 预约时使用手机验证码,用来拉长用户访问时间。(输入验证码到提交预约整个过程可能需要五秒时间,降低访问峰值)

  2. 防火墙进行IP限制策略配置,防止不合法刷单行为。

  3. 非预约时间段内隐藏口罩预约入口页面。

2.2.2 第二层: 负载限流与服务限流

合法性限流只能限制无效、非法的请求。但对于口罩预约场景来说,仍然会有大量的合法有效请求进入系统。在项目上线前,协助ISV进行如下的分流和限流的优化。

  1. 查询和预约读写分离,分流数据库的压力。

  2. 静态资源请求上CDN,分担了总请求处理的压力。

  3. 扩容了Nginx代理层和后台服务集群,共同来负载请求压力。

  4. Nginx入层进行了第二层的限流熔断。(详细配置请参考上述文档中的Nginx限流方案)。

  5. 获取手机验证码会调用三方短信服务网关,在应用接口层面单独进行了限流。

通过上面介绍,相信大家对限流算法有了一定理解那么像大厂在大促期间如何能抗住那么大的并发的呢?  可以看看我之前写的这篇亿级并发:《十亿级并发手册,教你玩懂高并发》

好了,我是欧子,我们下期见~

互联网大厂的微服务架构系统应对超大流量解决方案相关推荐

  1. SpringCloud - 微服务架构系统

    过渡分布式微服务 以前的架构还是最原始阶段,官网.论坛.云平台等应用即一台服务器搞定一切.对应的web服务器.数据库.静态文件资源等,部署到一台服务器上即可.一般每秒几百请求没啥问题,结合内核参数调优 ...

  2. GTS来了!阿里微服务架构下的分布式事务解决方案

    阿里妹导读:分布式事务已经成为微服务落地最大的阻碍,也是非常具有挑战性的一个技术难题. 为此,今天我们邀请阿里高级技术专家于皋,和大家深入探讨微服务架构下,分布式事务的各种解决方案,并重点为大家解读阿 ...

  3. 微服务架构下的轻量级定时任务解决方案

    微服务的概念可以说给程序设计打开了一个新世界,带来了众多的优点,但是也将一些以往容易处理的问题变得复杂,例如:缓存.事务.定时任务等.缓存可以用中间件例如redis.memcached等,事务有诸多分 ...

  4. 微服务架构下得分布式事务解决方案

    1.开源解决方案 框架名称 GitHub地址 社区开源项目dts https://github.com/venusteam/dts tcc-transaction https://github.com ...

  5. 无论什么级别程序员,“微服务架构”都是你必须过的坎!

    近几年,微服务架构迅速在整个技术社区窜红,被认为是 IT 软件架构的未来方向.一线互联网公司由于具有大量的业务体量和业务场景,比如阿里.百度.网易,很早就开始入坑微服务架构. 但说起微服务,不少人还是 ...

  6. 微服务架构面试送送送命题!

    近几年,微服务架构迅速在整个技术社区窜红,被认为是 IT 软件架构的未来方向.一线互联网公司由于具有大量的业务体量和业务场景,比如阿里.网易,很早就开始入坑微服务架构. 但说起微服务,不少人还是有这样 ...

  7. 微服务架构的核心要点和实现原理

    https://blog.csdn.net/qiansg123/article/details/80131044 微服务架构中职能团队的划分 传统单体架构将系统分成具有不同职责的层次,对应的项目管理也 ...

  8. 架构解密从分布式到微服务:微服务架构到底是什么?

    架构解密从分布式到微服务:微服务架构到底是什么? https://www.toutiao.com/i6937907188505657870/?tt_from=weixin&utm_campai ...

  9. 微服务架构的核心要点和实现原理解析

    摘要:本文中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务在读者正在工作的项目中起到积极的作用. 微服务架构中职能团队的划分 传统单体架构将系统分成具 ...

最新文章

  1. Theano3.3-练习之逻辑回归
  2. 大规模神经网络最新文献综述:训练高效DNN、节省内存使用、优化器设计
  3. mysql mariadb 选择_MariaDB 选择数据库
  4. 数学教材里的神秘数表在国外红出圈,网友:引人入胜、猜不到结局
  5. 机皇再翻车!微信、支付宝关停其指纹支付功能,用户难以原谅
  6. @WebService作用
  7. 【数学建模】Lingo软件介绍+常用函数总结+样例
  8. 常用视频像素格式 YUV422 YUV420
  9. ubuntu 无法定位软件包
  10. 人工智能在医疗领域的应用
  11. canvas_requestAnimationFrame帧率显示fps
  12. 北大计算机专业研究生录取分数线,北京大学考研分数线是多少
  13. 大数据技术之_13_Azkaban学习_Azkaban(阿兹卡班)介绍 + Azkaban 安装部署 + Azkaban 实战...
  14. PTA-学生成绩录入及查询 zym广东外语外贸大学
  15. 第一(关于list及dict)
  16. Win11封杀盗版office!不用找新密钥,这200套全行业终极模板够你用一辈子,一会儿删...
  17. 奔波真是辛苦啊,然而生命终将逝去,只希望当一切都结束的时候,能够没有遗憾吧。
  18. 如何理解光圈、ISO、快门、曝光这几个概念?
  19. JFFS2文件系统挂载过程(5)
  20. python计算平方根算法_每日一程-16.python-巴比伦平方根算法

热门文章

  1. 练习2-6 计算物体自由下落的距离
  2. 计算机毕业设计java+ssm婚纱影楼信息网站(源码+系统+mysql数据库+Lw文档)
  3. keil5“魔法棒”配置
  4. 一个APP原型制作demo
  5. IDA安装keypatch插件
  6. 热敏打印机实现打印小票
  7. 负值瞬时频率出现原因及解决方法总结
  8. 用C#控制台写飞行棋(第二篇)
  9. 2018服务器 芯片组,【2018年核心平台年终盘点 】多核心处理器大普及,显卡体验/消费双升级...
  10. css3情侣游戏,11个基于HTML/CSS/JS的情人节表白可爱小游戏、小动画【情人节主题征文】...