【问题标题】:Why does uWSGI not reject requests when the listen queue should be full?为什么当侦听队列应该满时 uWSGI 不拒绝请求?
【发布时间】:2021-02-27 12:01:24
【问题描述】:

给出以下最小示例:

# myproject.py

import time

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello():
    time.sleep(5)
    return 'hello'


if __name__ == '__main__':
    app.run(host='0.0.0.0')
# wsgi.py

from myproject import app

if __name__ == '__main__':
    app.run()
uwsgi --http-socket 0.0.0.0:8080 --workers 1 --listen 2 --module wsgi:app

我现在预计同时发送 3 个以上的请求(1 个在工作线程中进行,2 个在队列中)将导致只有 3 个被服务,而其他的被拒绝。

但是,情况似乎并非如此。像这样发送 10 个请求时

curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080 & \
curl http://127.0.0.1:8080

所有的都成功地一个接一个地送达。为什么会这样?我是否误解/错误配置了什么?

(我使用的是 Ubuntu 20.04,以防这很重要。)

【问题讨论】:

标签: python request queue webserver uwsgi


【解决方案1】:

我不确定确定,低级网络不是我的专业领域,但我相信我已经找到了答案。

我发现几年前的一个问题与您的问题非常相似。有人看到 uwsgi 排队的响应超出了指定的 listen 值应允许的数量。 https://uwsgi.unbit.narkive.com/QKdRyejv/when-the-backlog-is-full-is-uwsgi-supposed-to-accept-connections

在页面底部附近我们看到:

是的,这是 linux 的预期行为, 监听队列总是强制为 8(在 BSD 中为 5)。

为了确认这实际上是正确的,我做了更多的挖掘,导致我发现 listen 值实际上只是等待多少的 提示,并且实现可能会监听不同的金额。

https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html

backlog 参数为实现提供了一个提示,实现应使用该提示来限制套接字侦听队列中未完成连接的数量。实现可能会对积压施加限制并默默地减少指定的值。通常,较大的 backlog 参数值将导致侦听队列的长度更大或相等。实现应支持在 中定义的积压值直至 SOMAXCONN。

listen() ignores the backlog argument? 引导我查看实际的 linux 内核源代码以确认原始声明。

http://lxr.linux.no/#linux+v2.6.36/net/core/request_sock.c#L44 我们看到了似乎是确认的内容

43        nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog);
44        nr_table_entries = max_t(u32, nr_table_entries, 8);
45        nr_table_entries = roundup_pow_of_two(nr_table_entries + 1);

这似乎首先使用nr_table_entriessysctl_max_syn_backlog(常数256),以较小者为准。在我们的示例中,nr_table_entries 应该是 2。

接下来它会选择一个最大值和 8,所以我们的 2 被丢弃并使用 8。

然后它向上取整到 2 的下一个最高幂。

我用更多的流量(100 个并发请求)淹没了您的示例服务器,但除了 9 个之外,其他所有请求都失败了。我相当确信这可以解释您所看到的行为。你实际上不可能有这么低的监听值。

【讨论】:

  • 哇。多么了不起的调查和一个很好的解释。非常感谢。现在完全有道理了。
猜你喜欢
  • 2018-11-12
  • 2016-01-16
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 2023-02-14
相关资源
最近更新 更多