Day09-流量限制(四)

前言

昨天 Day08 时有跟大家介绍 nginx limit_req 里面的 burst 参数该怎麽使用,简单来说就是用来设定 queue 的长度,若 queue 爆了就直接拒绝。而今天要讲的是另一个参数 delay,跟 burst 合在一起使用可以做出很多不同的变化哦~

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 送

burst

但这样有个坏处,譬如说很多时候前端网站为了提升使用者体验,可能会同时发起多个请求GET /api/aaaGET /api/bbbGET /api/ccc),并且预期他们会被平行处理(这样才能提高效率嘛)。但由於 nginx 1r/s 的限制,就算你同时发了三个请求到後端,最後一个请求 GET /api/ccc 还是要先排队两秒才会开始被处理,因此会大幅降低效率

nodelay

那有没有什麽方法既可以做到限流,但又不要限得这麽死呢?解法就是在 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

因爲加上 nodelay 後就可以同时处理多个请求,所以可以成功解决上面提到的「前端同时发起多个请求的问题」,不会再需要每个请求都排队,在限流的同时也兼顾到了效能,是非常好的做法哦~

小结

从前天开始总共花了三天讲怎麽在 nginx 做限流,这几天的内容比较复杂一点,如果不熟悉 nginx 的朋友们读起来可能会觉得有些吃力,但愿意认真花时间下去了解的话会发现 nginx 的限流真的非常好用,不只可以保护你的 API server,而且效能上的表现也很不错。所以如果看不太懂的话可以多看几遍,真有什麽看不懂的地方也可以在下方留言,我会尽量回答大家的问题的~


<<:  day 16 - 开启git worktree 进行redis lua-script 测试比较

>>:  Flutter体验 Day 16-滚动组件-Sliver

离职倒数10天:做产品才知道政治敏感不只存在两岸之间

我第一次在微软 release 产品时,学到一件很意外的事是:这世界上政治敏感区域原来不只有台湾跟中...

Day 8 jinja (3)

前言 今天一样是 jinja 的内容,会讲到模板的继承。这个在网页有固定排版或是格式的时候很好用,不...

[Day11] Flutter with GetX flutter toast & Overlay

Flutter toast 在等待http response 或者需要等待的情境 通常会用到转圈圈 ...

Day 22 bert 文字情感分类

BERT (Bidirectional Encoder Representations from T...

D2. 学习基础C、C++语言

D2: 基本语法 输入输出 输入: scanf 输出: printf 如果我今天想要输出一个数字35...