昨天 Day08 时有跟大家介绍 nginx limit_req
里面的 burst
参数该怎麽使用,简单来说就是用来设定 queue 的长度,若 queue 爆了就直接拒绝。而今天要讲的是另一个参数 delay
,跟 burst
合在一起使用可以做出很多不同的变化哦~
考虑以下这个设定档,譬如说我希望平均而言每秒最多就一个 /api
开头的请求进来,所以设定 1r/s,又因为 burst=10
的关系,所以最多可以允许 10 个请求同时进来排队(第 11 个就直接拜拜),nginx 再以 1r/s 的速度慢慢转送给 API server,在 10 秒内把请求处理完
http {
# 每秒最多一个请求 1r/s
limit_req_zone $binary_remote_addr zone=limit:10m rate=1r/s;
server {
location /api {
# queue 的长度是 10
limit_req zone=limit burst=10;
proxy_pass http://backend;
}
}
}
如果画成图的话就长这样,一开始有很多个请求同时进来,因为不超过十个,所以他们会被 queue 起来,再以 1r/s 的速度往 API server 送
但这样有个坏处,譬如说很多时候前端网站为了提升使用者体验,可能会同时发起多个请求(GET /api/aaa
、GET /api/bbb
、GET /api/ccc
),并且预期他们会被平行处理(这样才能提高效率嘛)。但由於 nginx 1r/s 的限制,就算你同时发了三个请求到後端,最後一个请求 GET /api/ccc
还是要先排队两秒才会开始被处理,因此会大幅降低效率
那有没有什麽方法既可以做到限流,但又不要限得这麽死呢?解法就是在 limit_req
的最後加上 nodelay
,来看看以下这个设定档,除了加上 nodelay
之外其他部分都长得一样,而这边的 nodelay
可以把限制稍微放宽一点
http {
limit_req_zone $binary_remote_addr zone=limit:10m rate=1r/s;
server {
location /api {
limit_req zone=limit burst=10 nodelay; # HERE
proxy_pass http://backend;
}
}
}
怎麽个放宽法呢?在加上 nodelay
之前,因为 rate=1r/s
的关系,所以「每秒只能有一个请求被转送到 API server」,但有了 burst=10 nodelay
之後,就变成「每 10 秒最多可以有 10 个请求被转送到 API server」,虽然平均而言还是一秒一个,但就多了许多弹性
画成图的话,假如你在连续几秒内一口气送了 11 个请求,因为 burst=10 nodelay
的关系,前 10 请求个会被马上送进去 API server 处理,第 11 个请求则是等到 10 秒过後才会被送进去(毕竟每 10 秒最多只能有 10 个请求)
因爲加上 nodelay
後就可以同时处理多个请求,所以可以成功解决上面提到的「前端同时发起多个请求的问题」,不会再需要每个请求都排队,在限流的同时也兼顾到了效能,是非常好的做法哦~
从前天开始总共花了三天讲怎麽在 nginx 做限流,这几天的内容比较复杂一点,如果不熟悉 nginx 的朋友们读起来可能会觉得有些吃力,但愿意认真花时间下去了解的话会发现 nginx 的限流真的非常好用,不只可以保护你的 API server,而且效能上的表现也很不错。所以如果看不太懂的话可以多看几遍,真有什麽看不懂的地方也可以在下方留言,我会尽量回答大家的问题的~
<<: day 16 - 开启git worktree 进行redis lua-script 测试比较
>>: Flutter体验 Day 16-滚动组件-Sliver
我第一次在微软 release 产品时,学到一件很意外的事是:这世界上政治敏感区域原来不只有台湾跟中...
前言 今天一样是 jinja 的内容,会讲到模板的继承。这个在网页有固定排版或是格式的时候很好用,不...
Flutter toast 在等待http response 或者需要等待的情境 通常会用到转圈圈 ...
BERT (Bidirectional Encoder Representations from T...
D2: 基本语法 输入输出 输入: scanf 输出: printf 如果我今天想要输出一个数字35...