@@ -767,6 +767,77 @@ upstream backend {
767767
768768` server ` 块后还可以添加诸如 ` max_fails ` (最大失败次数)、` fail_timeout ` (失败超时时间)等参数来控制节点的故障转移行为。
769769
770+ ## 速率、请求与连接数限制 {#limiting}
771+
772+ Nginx 提供了多种不同维度的限制功能,帮助减轻恶意流量对服务的影响,保护后端稳定运行,将更多资源分配给正常用户。以下介绍 Nginx 自带的限制功能,如果需要更复杂的规则,可以参考 [ Lua] ( #lua ) 部分。
773+
774+ ### 速率限制 {#rate-limiting}
775+
776+ [ ` limit_rate ` ] ( https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate ) 指令可以限制每个请求的速率。例如:
777+
778+ ``` nginx
779+ location /downloads/ {
780+ limit_rate 100k; # 限制下载速率为 100KiB/s
781+ }
782+ ```
783+
784+ !!! tip "Nginx 使用的单位"
785+
786+ 在 Nginx 配置中,`k`、`m`、`g` 均使用 1024 作为基数,而不是 1000。即分别是 KiB(Kibibyte)、MiB(Mebibyte)、GiB(Gibibyte)等。
787+
788+ 如果希望做到类似「[ 下载 2M 后限速到 10KB/s] ( https://github.com/tuna/issues/issues/1174 ) 」(当然实际没有部署过这种配置)的效果,可以使用 [ ` limit_rate_after ` ] ( https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate_after ) 指令:
789+
790+ ``` nginx
791+ location /downloads/ {
792+ limit_rate_after 2m; # 先允许下载 2MiB
793+ limit_rate 10k; # 然后限速到 10KiB/s
794+ }
795+ ```
796+
797+ 但是,由于 ` limit_rate ` 只限制单个请求的速率,因此如果用户开启多个并发连接下载,实际的总速率会超过限制,因此还需要配合下面介绍的请求与连接数限制机制。
798+
799+ ### 请求限制 {#request-limiting}
800+
801+ [ ` ngx_http_limit_req_module ` ] ( https://nginx.org/en/docs/http/ngx_http_limit_req_module.html ) 模块可以限制单位时间内的请求数量。和[ 反代缓存] ( #reverse-proxy-caching ) 有些类似的是,我们需要先使用 [ ` limit_req_zone ` ] ( https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone ) 定义一个共享内存区域来存储请求计数器:
802+
803+ ``` nginx
804+ http {
805+ # ...
806+ limit_req_zone $binary_remote_addr zone=global:10m rate=20r/s;
807+ }
808+ ```
809+
810+ 这里定义了一个名字为 ` global ` 的区域,大小为 10MB。在使用 ` $binary_remote_addr ` 作为 key 的情况下,一个 IPv4 地址为 4 字节,IPv6 地址为 16 字节,每个 IP 的状态需要 128 字节(64 位系统)。这个 zone 限制为每秒 20 个请求(` 20r/s ` )。
811+
812+ 在需要限制请求的地方使用 [ ` limit_req ` ] ( https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req ) 指令:
813+
814+ ``` nginx
815+ location /downloads/ {
816+ limit_req zone=global burst=10 nodelay;
817+ }
818+ ```
819+
820+ ` limit_req ` 使用漏桶(leaky bucket)算法来限制请求速率,想象一个底部有个洞的水桶,这个水桶的大小是 burst,从底部的洞流出来的水速率是 rate,外部的请求就是往水桶里倒水。如果水桶满了,那么新的请求就会被拒绝(` nodelay ` )或者延迟(` delay=0 ` ,默认行为)。
821+
822+ ### 连接数限制 {#connection-limiting}
823+
824+ [ ` ngx_http_limit_conn_module ` ] ( https://nginx.org/en/docs/http/ngx_http_limit_conn_module.html ) 模块可以限制并发连接数。同样,使用 [ ` limit_conn_zone ` ] ( https://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn_zone ) 定义一个共享内存区域:
825+
826+ ``` nginx
827+ http {
828+ # ...
829+ limit_conn_zone $binary_remote_addr zone=addr:10m;
830+ }
831+ ```
832+
833+ 之后使用 ` limit_conn ` 指令限制连接数:
834+
835+ ``` nginx
836+ location /downloads/ {
837+ limit_conn addr 5; # 每个 IP 最多允许 5 个并发连接
838+ }
839+ ```
840+
770841## Rewrite {#rewrite}
771842
772843## 日志 {#logging}
0 commit comments