具有 2 个工作线程和 2 个线程的 Gunicorn config.py 文件仅并行处理 2 个请求

Bez*_*ran 5 python gevent flask greenlets gunicorn

原始github问题中没有答案: https://github.com/tiangolo/meinheld-gunicorn-flask-docker/issues/48

在下面的简单设置中,我期望 Gunicorn 能够并行处理至少 4 个请求,但我只得到 2 个请求。在下面的配置中,我们可以看到 2 个工作线程和 2 个线程。

此外,我们尝试使用 2 个线程配置工作人员数量 == 1,然后我们在给定时刻仅处理 1 个请求。所以看起来,gunicorn + meinheld 设置只能在每个工作进程中处理 1 个请求,这是非常低效的。

我们在每个设置中并行发送 53 个请求。

simple_app.py:

import sys

from flask import Flask, request
import json
import time

app = Flask(__name__)


@app.route("/", methods=['POST'])
def hello():
    headers = request.headers
    data = json.loads(request.data)
    version = "{}.{}".format(sys.version_info.major, sys.version_info.minor)
    message = "Hello World from Flask in a Docker container running Python {} with Meinheld and Gunicorn (default): {}:{}".format(
        version, headers, json.dumps(data)
    )
    print(message)
    time.sleep(15)
    return message
Run Code Online (Sandbox Code Playgroud)

Gunicorn_dev_conf.py:

import json
import multiprocessing
import os
workers_per_core_str = os.getenv("WORKERS_PER_CORE", "2")
web_concurrency_str = os.getenv("WEB_CONCURRENCY", None)
host = os.getenv("HOST", "0.0.0.0")
port = os.getenv("PORT", "80")
bind_env = os.getenv("BIND", None)
use_loglevel = os.getenv("LOG_LEVEL", "debug")
if bind_env:
  use_bind = bind_env
else:
  use_bind = "{host}:{port}".format(host=host, port=port)
cores = multiprocessing.cpu_count()
workers_per_core = float(workers_per_core_str)
default_web_concurrency = workers_per_core * cores
if web_concurrency_str:
  web_concurrency = int(web_concurrency_str)
  assert web_concurrency > 0
else:
  web_concurrency = int(default_web_concurrency)
# Gunicorn config variables
loglevel = use_loglevel
workers = web_concurrency
workers = 2
reuse_port = True
bind = use_bind
keepalive = 120
errorlog = "-"
threads = 2
# For debugging and testing
log_data = { "loglevel": loglevel, "workers": workers, "bind": bind,
# Additional, non-gunicorn variables
   "workers_per_core": workers_per_core, "host": host, "port": port}
accesslog = "-"
preload_app = False
print_config =  True
# max_requests = 1900
# max_requests_jitter = 50
sendfile = True
print(json.dumps(log_data), flush=True)
Run Code Online (Sandbox Code Playgroud)

docker运行命令:

docker run --rm --name demo_dev --privileged -it -p 8080:80 -v ./gunicorn_dev_conf.py:/app/gunicorn_conf.py:rw -v ./simple_app.py:/app/main.py tiangolo/meinheld-gunicorn-flask:python3.8-alpine3.11
Run Code Online (Sandbox Code Playgroud)

并行卷曲命令:

for i in {1..53}
do
echo "Welcome num$i; $(date)"
curl "http://localhost:8080/" -d @simpleJson.json -H 'content-type: application/json' -o dir_$i&&echo "num"$i"; $(date)" &
done
Run Code Online (Sandbox Code Playgroud)

simpleJson.json:

{
 "field1": [
     {
         "field2": "09-090"
     }
 ]
}
Run Code Online (Sandbox Code Playgroud)

输出:

10.0.2.100 - - [05/Aug/2021:12:16:20 +0000] "POST / HTTP/1.1" 200 251 "-" "curl/7.61.1"
Hello World from Flask in a Docker container running Python 3.8 with Meinheld and Gunicorn (default): Host: localhost:8080
User-Agent: curl/7.61.1
Accept: */*
Content-Type: application/json
Content-Length: 70

:{"field1": [{"field2": "09-090"}]}
10.0.2.100 - - [05/Aug/2021:12:16:20 +0000] "POST / HTTP/1.1" 200 251 "-" "curl/7.61.1"
Hello World from Flask in a Docker container running Python 3.8 with Meinheld and Gunicorn (default): Host: localhost:8080
User-Agent: curl/7.61.1
Accept: */*
Content-Type: application/json
Content-Length: 70

:{"field1": [{"field2": "09-090"}]}

>> WAIT 15 seconds...


10.0.2.100 - - [05/Aug/2021:12:16:35 +0000] "POST / HTTP/1.1" 200 251 "-" "curl/7.61.1"
Hello World from Flask in a Docker container running Python 3.8 with Meinheld and Gunicorn (default): Host: localhost:8080
User-Agent: curl/7.61.1
Accept: */*
Content-Type: application/json
Content-Length: 70

:{"field1": [{"field2": "09-090"}]}
10.0.2.100 - - [05/Aug/2021:12:16:35 +0000] "POST / HTTP/1.1" 200 251 "-" "curl/7.61.1"
Hello World from Flask in a Docker container running Python 3.8 with Meinheld and Gunicorn (default): Host: localhost:8080
User-Agent: curl/7.61.1
Accept: */*
Content-Type: application/json
Content-Length: 70

:{"field1": [{"field2": "09-090"}]}
Run Code Online (Sandbox Code Playgroud)