一,以固定的速度提供服务
语法:
例子
limit_req_zone $binary_remote_addr zone=test:10m rate=2r/s;server { location / { limit_req zone=test; }}
语法:
imit_req_zone 用于设置限流和共享内存区域的参数,格式为:
limit_req_zone key zone rate。
key: 定义限流对象,
$binary_remote_addr 是 nginx 中的变量,表示基于 remote_addr(客户端IP) 来做限流。
zone: 定义共享内存区来存储访问信息,
访问信息包括每个 IP 地址状态和访问受限请求 URL 的频率等
zone 的定义分为两个部分:由 zone= 关键字标识的区域名称,以及冒号后面的区域大小。
test:10m 表示一个大小为10M,名字为 test 的内存区域。
1M 能存储16000个 IP 地址的访问信息,test 大概可以存储约160000个地址。
nginx 创建新记录的时候,会移除前60秒内没有被使用的记录,
如果释放的空间还是存储不了新的记录,会返回503的状态码。
rate: 设置最大的访问速率。
rate=2r/s(为了好模拟,rate 设置的值比较小),表示每秒最多处理 2个请求。
事实上 nginx 是以毫秒为粒度追踪请求的,rate=2r/s 实际上是每500毫秒1个请求,
即,上一个请求完成后,如果500毫秒内还有请求到达,这些请求会被拒绝
(默认返回503,如果想修改返回值,可以设置limit_req_status)
limit_req_zone 只是设置限流参数,如果要生效的话,必须和 limit_req 配合使用。
limit_req 的格式为:
limit_req zone=name [burst=number] [nodelay]
上面的配置保证了 nginx 以固定的速度提供服务(2r/s),但是这种情况不适用于有突发流量的情况,
我们希望可以尽可能的缓存请求并处理它们
二,增加队列
例子:
limit_req_zone $binary_remote_addr zone=test:10m rate=2r/s;
server { location / { limit_req zone=test burst=5; }}
burst 表示在超过设定的访问速率后能额外处理的请求数。
当 rate=2r/s 时,表示每500ms 可以处理一个请求。
burst=5时,如果同时有10个请求到达,nginx 会处理第1个请求,
剩余9个请求中,会有5个被放入队列,剩余的4个请求会直接被拒绝。
然后每隔500ms从队列中获取一个请求进行处理,
此时如果后面继续有请求进来,如果队列中的请求数目超过了5,会被拒绝,
不足5的时候会添加到队列中进行等待。
我们可以理解为现在的桶可以存5滴水:
三,让队列中请求无需等待:
配置 burst 之后,虽然同时到达的请求不会全部被拒绝,
但是仍需要等待500ms 一次的处理时间,放入桶中的第5个请求需要等待500ms * 4的时间才能被处理,
更长的等待时间意味着用户的流失,在许多场景下,这个等待时间是不可接受的。
此时我们需要增加 nodelay 参数,和 burst 配合使用。
limit_req_zone $binary_remote_addr zone=test:10m rate=2r/s;
server { location / { limit_req zone=test burst=5 nodelay; }}
nodelay 表示不延迟。设置 nodelay 后,第一个到达的请求和队列中的请求会立即进行处理,不会出现等待的请求。
需要注意的是,
虽然队列中的5个请求立即被处理了,但是队列中的位置依旧是按照500ms 的速度依次被释放的。
后面的4个请求依旧是被拒绝的,长期来看并不会提高吞吐量的上限,
长期吞吐量的上限是由设置的 rate 决定的。
说明:
参考自:
https://blog.csdn.net/cold___play/article/details/132094865