Nginx的请求速率限制模块的两个关键参数rate和burst和相关代码语句的详细说明。

01-参考文章

本文参考文章下面两篇文章写成(建议阅读前先看下下面两篇文章):
NGINX速率限制原理及源码分析
Nginx限速模块初探

02-参数rate和burst的详细解释

rate的单位是 r/s,单位直译过来是 次数/秒,即每秒内允许的最大请求次数。
常常发生的误解:比如 rate 的值为 5,那么这代表每秒内允许的最大请求数为5吗?
答案是:并不完全是每秒内允许的最大请求数为5。

如果你没有设置burst参数,并且你在200ms的范围内连续发起了5次请求,那么只有第1次请求会被执行,后面的4次都会被丢弃。具体的例子可参考文章:Nginx限速模块初探,这篇文章中有具体的例子。
为什么会这样?因为Nginx是在毫秒级别来执行请求的,因为1秒=1000毫秒,所以 5 r/s 代表的真正意义为 1 次/200毫秒,即每200毫秒执行一次请求。
所以其实 5 r/s 是定义了一个时间窗口,一个时间窗口的宽度可执行一次请求,在这个例子中,时间窗口的宽度为 200毫秒,即每200毫秒执行一次请求。

但实际情况是,经常会有200毫秒内超过1次请求的情况发生,此时怎么办呢?burst参数就起作用了。burst代表Nginx一次最多能接收多少个请求,请求数如果在burst的范围内,那么这些请求即使超过了1或超过了rate的数值,也能被Nginx安排到队列中。
burst有两种工作模式,一种是有delay的工作模式(burst的默认工作模式),一种是没有delay的工作模式,即nodelay的工作模式。
以rate = 5 r/s = 1 次/200毫秒,burst = 10 为例 来说明这个问题。
当处于delay的工作模式时:
这是burst的默认工作模式。假设客户端在短时间内(比如200毫秒内)发起了11次请求,那么此时Nginx会把前10次请求加入到burst的队列槽位中,把最后一次丢弃,然后每隔200毫秒执行一个请求,同时在处理期间每隔200毫秒释放掉一个队列槽位的占用,这个被释放掉的队列槽位可以新填入一个后续请求,然后后续请求依次被执行。
当处于nodelay的工作模式时:
同样假设客户端在短时间内(比如200毫秒内)发起了11次请求,此时Nginx也会把前10次请求加入到队列槽位中,把最后一次丢弃,然后在一个时间窗口单位时间内(即200毫秒内)把这10次请求全部执行完。请注意,虽然这10次请求全部执行完了,但是队列槽位的占用仍没被释放,而是每隔200毫秒,即一个时间窗口的单位释放一个队列槽位的占用,这个被释放掉的队列槽位可以新填入一个后续请求,然后后续请求依次被执行。

03-实际例子及代码详解

对应于上面两个参数的详解,例子的相应代码如下:

# 限速配置,限速配置需放在server块之外
limit_req_zone $binary_remote_addr zone=ip_limit_01s:10m rate=5r/s;
......
server {
    
    
		location / {
    
    
			# 限速配置
			limit_req zone=ip_limit_01s burst=10 nodelay;
		}
}

代码详解:

limit_req_zone $binary_remote_addr zone=ip_limit_01s:10m rate=5r/s;

在上述Nginx配置语句中,limit_req_zone 是一个用于配置基于客户端IP地址的请求速率限制的指令。

具体来说,这个指令用于定义一个请求限制区域(request zone),该区域将被用于存储有关客户端请求速率的信息。这个信息包括客户端的IP地址、请求计数等。这样,Nginx就能够跟踪每个客户端的请求频率,并根据预定义的速率进行限制。

让我们分解这个具体的例子:

扫描二维码关注公众号,回复: 17155689 查看本文章
  • $binary_remote_addr: 这是一个Nginx变量,表示客户端的二进制格式的IP地址。这是作为限制的依据,以便针对不同的客户端进行限制。除了$binary_remote_addr,Nginx 还提供了其他一些变量,可以作为请求速率限制的依据。以下是其中一些常见的变量:
  1. $binary_remote_addr: 客户端的二进制格式的IP地址。

  2. $remote_addr: 客户端的IP地址。

  3. $http_user_agent: 客户端的User-Agent头,表示客户端的浏览器、操作系统等信息。

  4. $server_name: 当前请求的服务器名。

  5. $host: 当前请求的Host头,用于标识请求的目标主机。

  6. $request_uri: 完整的请求URI,包括参数。

  7. $scheme: 请求的协议(http或https)。

  8. $http_referer: 表示引导用户代理到当前页的URI。

    你可以根据具体的需求选择合适的变量作为限制依据。例如,如果你想根据不同的User-Agent对请求进行速率限制,你可以使用$http_user_agent。在配置 limit_req_zone 指令时,只需将适当的变量替换到$binary_remote_addr的位置即可。
    提问:$binary_remote_addr$remote_addr有何区别?
    $binary_remote_addr$remote_addr 都是用于表示客户端的IP地址,但它们之间有一些区别:

    1. 数据格式:
      • $binary_remote_addr: 表示客户端IP地址的二进制格式。
      • $remote_addr: 表示客户端IP地址的文本格式。
    2. 用途:
      • $binary_remote_addr: 主要用于在 limit_req_zone 中作为限制区域的依据。由于是二进制格式,它在内存中的存储效率更高,适合用于大规模请求限制。
      • $remote_addr: 通常用于在日志中记录客户端的IP地址,或者在其他地方需要IP地址的文本表示时使用。
  • zone=ip_limit_01s:10m: 这部分定义了请求限制区域的名称(ip_limit_01s)和其最大大小(10m,即10兆字节)。名称会在后面配置具体的server块的限制请求数时使用到,限制区域的大小用于存储请求的状态信息。

  • rate=5r/s: 这个在本文前面我已经讲得很清楚、很具体了,这里就不再作过多说明了。

limit_req zone=ip_limit_01s burst=10 nodelay;

这句代码就没什么好讲的了。这句代码就是调用了上一句代码中定义的请求限制区域“ip_limit_01s”,然后把burst的队列槽位值设为10,并且以 nodelay 的模式运行。前面已经说得很清楚了,就没什么好说的了。

04-rate值可不可以为小数?

提问:Nginx的限制请求速率的模块中的rate值可不可以设置为小数? 比如 rate 可不可以为0.5?
答:不可以。应设置为整数。

05-请求超过允许速率Nginx会提示什么?

提问:如果超过请求允许速率,会发生什么情况?
答,会提示503错误,如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wenhao_ir/article/details/134913876