NGINX:请求限制队列中查询的超时行为(突发)

NGINX:请求限制队列中查询的超时行为(突发)

目前,我们的队列大小为 3000 个请求。

location /api/v2 {
     limit_req zone=bursted burst=3000;
     include /etc/nginx/proxy.conf;
 }

速率限制为每秒 10 个请求。

 limit_req_zone $limit zone=api_slow:10m rate=1r/s;
 limit_req_zone $server_name zone=bursted:10m rate=10r/s;

Keep-Alive 超时为 30 秒。换句话说,当队列已满时,每 30 秒应拒绝 2700 个请求并显示错误代码 408。

 reset_timedout_connection on;
 client_body_timeout 10;
 send_timeout 2;
 keepalive_timeout 30;

在高峰时段,我在日志中找不到任何被 NGINX 拒绝的请求,原因是请求在队列中等待转发到 servlet 容器时超时,错误代码为 408。只有 503 错误代码被拒绝,这与请求速率开销相对应。

delaying request, excess: 2958.320, by zone "bursted"
limiting requests, excess: 3000.730 by zone "bursted"

如果队列中的请求挂起时间过长,NGINX 是否会通过超时拒绝这些请求?这个超时是多少?它的配置在哪里?

答案1

似乎对 nginx 速率限制和超时的工作原理有些困惑。没有暂停用于速率限制。您只需设置速率和队列大小。任何超过该速率的请求都将被添加到队列中,以便稍后处理。一旦队列完全填满,任何其他请求都将被拒绝,并显示 503 状态代码。


在你的例子中您已将速率设置为每秒 10 个请求 (10r/s),突发大小为 3000,区域“突发”大小为 10 兆字节。并且此速率限制适用于每个定义的服务器的单独计数。

换句话说,您的服务器每 0.1 秒接受并处理一个请求,最多可以排队 3000 个超出的请求,然后以定义的速率处理这些请求:每 0.1 秒一个。您的突发区域可以存储大约 160,000 个 IP 地址。

这意味着如果 3011 个请求在一秒钟内到达,nginx 会立即处理前 10 个请求,将另外 3000 个请求放入队列,第 3011 个请求将被拒绝并返回 503 状态代码。然后,队列将以定义的速率(每 0.1 秒一个请求)进行处理。只要没有新请求到达,队列就会变短,并且可以再次将新请求添加到队列中。但是,虽然队列已经容纳了 3000 个请求,但每个额外的请求都将被拒绝并返回 503 状态代码。

这种线性处理突发队列的行为可能会使您的网站看起来很慢。为了防止这种情况,您可以将参数添加nodelaylimit_req zone=bursted burst=3000 nodelay;。这将使来自突发队列的所有请求立即得到处理,同时将队列中的插槽标记为“已占用”,然后再次以定义的速率逐个插槽“释放”,因此定义的速率限制会随着时间的推移而得到满足。

limit_req_status 444;顺便说一句:您可以通过添加到配置块将拒绝请求的状态代码从 503 更改为 444 http

更多详细信息请参阅:


您的配置中的两个超时

client_body_timeout 10;将使你的服务器在收到请求后最多等待 10 秒,等待客户端主体发送。如果在这段时间内客户端没有发送主体,服务器将关闭连接并返回 408 状态代码。

keepalive_timeout 30;将使你的服务器关闭 30 秒后仍处于打开状态的客户端的任何连接。但根据我的测试,请求在突发队列中等待的时间不计入 keepalive_timeout。


执行负载测试使用AB或者围城

相关内容