gunicorn 偶尔会冻结,直到工作人员在带烧瓶的简单 docker web 应用程序中超时

jtl*_*ton 6 flask gunicorn docker

我用 Flask 和 gunicorn 构建了一个简单的 docker web 应用程序。一切正常,但有时在发出请求时,响应会挂起。在工人超时之前,我看不到任何日志记录。因此,似乎该工作人员正忙于某事,超时,然后新工作人员接收请求并立即响应。

我只用 1 名工人设置了它。我知道我可以添加另一个工人。但除了我的手动戳之外,没有其他要求。没有其他事情发生。所以我非常好奇这个工人或主要的 gunicorn 工人还会在容器中做什么(心跳,错误处理那么昂贵)?

我的 Dockerfile:

FROM python:3.6-slim

WORKDIR /app

COPY . .

RUN pip install -r requirements.txt --no-cache-dir

EXPOSE 5000

CMD ["gunicorn", "-w", "1", "-t", "30", "--worker-tmp-dir", "/dev/shm", "-b", "0.0.0.0:5000", "app:app"]
Run Code Online (Sandbox Code Playgroud)

我的微不足道的应用程序:

import logging
import model
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.errorhandler(Exception)
def handle_error(e):
    code = 500
    app.log_exception(e)
    return jsonify(message=str(e)), code

@app.route("/predict", methods=["POST", "GET"])
def predict():
    result = model.predict(None)
    return jsonify(result)

model = model.mcascorer()

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
else:
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)
Run Code Online (Sandbox Code Playgroud)

我称之为预测的超小“模型”:

class mcascorer:

    def predict_proba(self, features):
        return 'hello'

    def predict(self, features):
        return 'hello'
Run Code Online (Sandbox Code Playgroud)

通常会立即响应,但在超时期间日志如下所示:

[2020-05-21 18:09:28 +0000] [9] [DEBUG] Closing connection.

[2020-05-21 18:09:58 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)

[2020-05-21 18:09:58 +0000] [9] [INFO] Worker exiting (pid: 9)

[2020-05-21 18:09:58 +0000] [11] [INFO] Booting worker with pid: 11

[2020-05-21 18:09:58 +0000] [11] [DEBUG] GET /predict
Run Code Online (Sandbox Code Playgroud)

看起来该工人被其他事情阻止了 - 但我不知道那会是什么。同时进入的心跳查询不应该花那么长时间,但它会挂起很多秒 - 我实际上为工作人员设置的整个超时时间。唯一发生的另一件事是错误记录,但不确定为什么会阻塞或花费这么长时间。即使它正在写入磁盘,这似乎也很奇怪。

我能找到的最接近的问题是:Docker: Running a Flask app via Gunicorn - Worker timeouts? 表现不佳? 链接到本文:https : //pythonspeed.com/articles/gunicorn-in-docker/

我按照他们的指南更新了 Dockerfile 以获取 tmp 内存位置“--worker-tmp-dir”、“/dev/shm”

我没有添加更多的工人。我知道我可以,但我真的很想知道发生了什么,而不是盲目地投入资源。任何想法都非常感谢。

Ser*_*tch 0

这里讨论: https: //github.com/benoitc/gunicorn/issues/1923 他们提出了 2 个解决方案:

  1. 通过--threads 2或更高gunicorn
  2. 通过--preload标志 对于我来说,第一个解决方案有效。我还没有尝试过第二个。