Day08-流量限制(三)

前言

昨天有讲到怎麽运用 nginx 来做基本的分流、限流,但因为昨天举的例子比较简单,真实世界的应用可能会更复杂,所以今天要针对限流的部分讲一些真实世界可能会遇到的例子~

针对不同的 endpoint 做限制

就如前天提到的,既然每个 API endpoint 要做的事情不一样,所需要的资源(CPU、时间、$$$)也会不同,所以针对所有 API 都做相同的流量限制显然不太合理,应该要针对高成本的 API(如发手机验证简讯、重设密码等等)做更严格的流量限制

那具体而言要怎麽做呢?首先是你可以一次宣告多个 zone,譬如说用来限制「发送手机验证简讯」的 limit_verifyPhone、限制「重设密码」 limit_resetPassword 等等,接着根据他们的 API 路径把套用上去

http {
    limit_req_zone $binary_remote_addr zone=limit_verifyPhone:10m rate=2r/m;
    limit_req_zone $binary_remote_addr zone=limit_resetPassword:10m rate=1r/m;

    server {
        location /api/verifyPhone {
            limit_req zone=limit_verifyPhone;
            proxy_pass http://backend;
        }  
        location /api/resetPassword {
            limit_req zone=limit_resetPassword;
            proxy_pass http://backend;
        }
    }
}

因为 nginx 会从最长的路径开始匹配(路径越长优先权越高),因此如果有 /api/resetPassword/api/verifyPhone 的请求进来,就会直接被对应的 location 抓走,也就会受到 limit_resetPasswordlimit_verifyPhone 的限制。反之如果不是这两个路径,那才会被优先权最低的 location /api 给捡走,没有经过任何流量限制就直接转发到後端服务器

queue 起来或是直接拒绝?

了解怎麽对不同 endpoint 做限制後,接着我们来探讨另外一个问题:你希望过量的请求是先被 queue 起来待会再处理?还是直接拒绝掉?

这问题其实没有标准答案,端看你的需求。如果你希望所有请求最後都能成功被处理,就算多等一下也无所谓,那就可以先 queue 起来;反之如果你担心一下子来太多请求会无法在短时间内处理完,那就可以先把过量的请求拒绝掉,让 client 端知道他发太多请求了。不过不管你想要的是哪一种处理方式,nginx 都可以帮你做到,只不过没特别设定的话 nginx 预设行为是把过量的请求直接拒绝掉。

那如果想要把过量的请求 queue 起来的话,应该要怎麽设定呢?很简单,只要在 limit_req 的结尾加上 burst=<queue size> 就可以了。假如你设定的限流是「每分钟最多 100 个请求」,而且设定 burst=200,在这情况下一分钟内突然来了 300 个请求,那 nginx 就会把前 200 个请求以「平均每分钟一百个的速度」慢慢推送给 API server,至於那多出来的 100 个过量请求就直接跟他们 say goodbye

http {
    limit_req_zone $binary_remote_addr zone=limit_verifyPhone:10m rate=3r/m;
    limit_req_zone $binary_remote_addr zone=limit_resetPassword:10m rate=1r/m;

    server {
        location /api/verifyPhone {
            # 如果一下子来太多电话认证的请求,就先 queue 起来慢慢处理,避免一下子发出太多简讯
            limit_req zone=limit_verifyPhone burst=5;
            proxy_pass http://backend;
        }  
        location /api/resetPassword {
            limit_req zone=limit_resetPassword;
            proxy_pass http://backend;
        }
    }
}

而根据使用情境不同,你也可以只挑部分 API 设定 burst,像上面的例子就只有在 /api/verifyPhone 设定 burst=5,如果来的是大量 /api/resetPassword 的请求,那还是会直接被回绝掉

小结

今天对於 nginx 限流的部分讲了一些更复杂的例子,相信大家看到这边应该都更了解怎麽在 nginx 做限流了,但关於 nginx burst 的部分还没完全讲完,明天还会做一些小补充。如果对於今天的内容有什麽问题欢迎在下方留言,都没问题的话就明天见罗~


<<:  Day9 Methods and v-on

>>:  【Day07】事件处理 Handling Events

17. 当mentor比你想像的重要多

前言 这篇文章觉得很适合给要当mentor的人,在你当之前应该要先听过这篇演讲,然後反思一下你想对...

ASP.NET MVC 从入门到放弃(Day29)-MVC 实作一个web api

在前一天我有提到如何将Web Api 加入 Swagger 今天就来实作一个会员查询资料的POST ...

第 23 集:Bootstrap 客制化 Grid 格线系统

此篇会教学如何将 Bootstrap grid 格线系统,自干一个出来。 事前准备 Gird Sy...

Python - 费式数列之呼吸

费式数列 (引用至维基面科) 斐波那契数列(义大利语:Successione di Fibonacc...

模型架构--3

ArcFace 在2018年发表,在SphereFace的基础上改进对特徵向量归一化和角度间隔,强化...