Tob*_*ann 3 python queue webserver request uwsgi
给出以下最小示例:
# 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')
Run Code Online (Sandbox Code Playgroud)
# wsgi.py
from myproject import app
if __name__ == '__main__':
app.run()
Run Code Online (Sandbox Code Playgroud)
uwsgi --http-socket 0.0.0.0:8080 --workers 1 --listen 2 --module wsgi:app
Run Code Online (Sandbox Code Playgroud)
我现在预计,同时发送 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
Run Code Online (Sandbox Code Playgroud)
全部都一一成功送达。为什么会这样呢?我是否误解/错误配置了什么?
(我使用的是 Ubuntu 20.04,以防万一这很重要。)
小智 6
我不确定,低级网络不是我的专业领域,但我相信我已经找到了答案。
我发现几年前的一个问题与你的非常相似。有人发现 uwsgi 排队的响应数量超出了指定listen值应允许的数量。
https://uwsgi.unbit.narkive.com/QKdRyejv/when-the-backlog-is-full-is-uwsgi-supposed-to-accept-connections
在页面底部附近我们可以看到:
是的,这是 Linux 的预期行为,监听队列的最小大小始终强制为 8(在 BSD 中为 5)。
为了确认这实际上是正确的,我做了更多的挖掘,发现监听值实际上只是等待多少个的提示,并且实现可能会监听不同的数量。
https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html
backlog 参数为实现提供了一个提示,实现应使用该提示来限制套接字侦听队列中未完成连接的数量。实现可能会对积压施加限制并默默地减少指定值。通常,较大的积压参数值将导致侦听队列的长度较大或相等。实现应支持高达 SOMAXCONN 的积压值,在 <sys/socket.h> 中定义。
Listen() 忽略积压参数?引导我检查实际的 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);
Run Code Online (Sandbox Code Playgroud)
这似乎首先使用nr_table_entriesor sysctl_max_syn_backlog(常数 256),以较小者为准。在我们的示例中nr_table_entries应该是 2。
接下来,它选择其中的最大值和 8,因此我们的 2 被丢弃并使用 8。
然后四舍五入到下一个最高的 2 次方。
我用更多流量(100 个并发请求)淹没了您的示例服务器,但除了 9 个之外的所有请求都失败了。我相当确信这可以解释您所看到的行为。实际上你的聆听价值不可能那么低。