为什么 uWSGI 在监听队列应该满的时候不拒绝请求?
Why does uWSGI not reject requests when the listen queue should be full?
给定以下最小示例:
# 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 个在 worker 中进行,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
全部一一服务成功。为什么会这样?我 misunderstand/misconfigure 有什么事吗?
(我正在使用 Ubuntu 20.04,以防这很重要。)
我不确定,低级网络不是我的专业领域,但我相信我已经找到了答案。
我发现了一个多年前的问题,与您的问题非常相似。有人看到 uwsgi 排队的响应比指定的 listen
值应该允许的多。
https://uwsgi.unbit.narkive.com/QKdRyejv/when-the-backlog-is-full-is-uwsgi-supposed-to-accept-connections
我们在页面底部附近看到了这个:
Yes, this is the expected behaviour for linux, the minimal size of the
listen queue is always forced to 8 (in BSD to 5).
为了确认这实际上是正确的,我做了更多的挖掘,让我发现 listen 值实际上只是一个 提示 等待多少,以及实现可能会听不同的数量。
https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html
The backlog argument provides a hint to the implementation which the implementation shall use to limit the number of outstanding connections in the socket's listen queue. Implementations may impose a limit on backlog and silently reduce the specified value. Normally, a larger backlog argument value shall result in a larger or equal length of the listen queue. Implementations shall support values of backlog up to SOMAXCONN, defined in <sys/socket.h>.
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_entries
或 sysctl_max_syn_backlog
(常量 256),以较小者为准。在我们的例子中 nr_table_entries
应该是 2.
接下来它选择最大值和 8,所以我们的 2 被丢弃并使用 8。
然后四舍五入到 2 的下一个最高次方。
我用更多流量(100 个并发请求)淹没了您的示例服务器,但只有 9 个失败。我相当相信这可以解释您所看到的行为。你实际上不能有这么低的聆听价值。
给定以下最小示例:
# 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 个在 worker 中进行,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
全部一一服务成功。为什么会这样?我 misunderstand/misconfigure 有什么事吗?
(我正在使用 Ubuntu 20.04,以防这很重要。)
我不确定,低级网络不是我的专业领域,但我相信我已经找到了答案。
我发现了一个多年前的问题,与您的问题非常相似。有人看到 uwsgi 排队的响应比指定的 listen
值应该允许的多。
https://uwsgi.unbit.narkive.com/QKdRyejv/when-the-backlog-is-full-is-uwsgi-supposed-to-accept-connections
我们在页面底部附近看到了这个:
Yes, this is the expected behaviour for linux, the minimal size of the listen queue is always forced to 8 (in BSD to 5).
为了确认这实际上是正确的,我做了更多的挖掘,让我发现 listen 值实际上只是一个 提示 等待多少,以及实现可能会听不同的数量。
https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html
The backlog argument provides a hint to the implementation which the implementation shall use to limit the number of outstanding connections in the socket's listen queue. Implementations may impose a limit on backlog and silently reduce the specified value. Normally, a larger backlog argument value shall result in a larger or equal length of the listen queue. Implementations shall support values of backlog up to SOMAXCONN, defined in <sys/socket.h>.
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_entries
或 sysctl_max_syn_backlog
(常量 256),以较小者为准。在我们的例子中 nr_table_entries
应该是 2.
接下来它选择最大值和 8,所以我们的 2 被丢弃并使用 8。
然后四舍五入到 2 的下一个最高次方。
我用更多流量(100 个并发请求)淹没了您的示例服务器,但只有 9 个失败。我相当相信这可以解释您所看到的行为。你实际上不能有这么低的聆听价值。