Почему добавление preload_app в gunicorn предотвращает его запуск до тех пор, пока не будет отправлен SIGINT? - PullRequest
0 голосов
/ 18 июня 2020

Я использую Flask через Gunicorn, и у меня большая проблема. Я получаю [КРИТИЧЕСКИЕ] ошибки WORKER_TIMEOUT. Чтобы исправить это, я добавил «preload_app = True» в свою конфигурацию Gunicorn. Добавить почти работает. Проблема, с которой я столкнулся, заключается в том, что стрельба не запускается, если я не отправлю сигнал SIGINT. Это происходит только с preload_app.

Вот результат:

(.venv) ubuntu@server:/opt/mayapp$ gunicorn -c etc/gunicorn.conf.py myapp:app
^C[2020-06-18 18:02:46 +0000] [23412] [INFO] Starting gunicorn 19.10.0
[2020-06-18 18:02:46 +0000] [23412] [INFO] Listening at: http://0.0.0.0:8000 (23412)
[2020-06-18 18:02:46 +0000] [23412] [INFO] Using worker: eventlet
[2020-06-18 18:02:46 +0000] [23416] [INFO] Booting worker with pid: 23416
[2020-06-18 18:02:46 +0000] [23417] [INFO] Booting worker with pid: 23417
[2020-06-18 18:02:46 +0000] [23418] [INFO] Booting worker with pid: 23418
[2020-06-18 18:02:46 +0000] [23419] [INFO] Booting worker with pid: 23419
[2020-06-18 18:02:46 +0000] [23420] [INFO] Booting worker with pid: 23420

Обратите внимание на ^ C, прежде чем что-либо произойдет. Если я не прервусь, ожидание будет неопределенным. В дополнение к тому, чтобы не запускаться, когда я действительно хочу завершить работу, я должен "pkill -9". Он будет зависать часами с любым другим способом.

My gunicorn.conf.py:

# file gunicorn.conf.py
# coding=utf-8
# Reference: https://github.com/benoitc/gunicorn/blob/master/examples/example_config.py
import os
import multiprocessing

_ROOT = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..'))
_VAR = os.path.join(_ROOT, 'var')
_ETC = os.path.join(_ROOT, 'etc')

loglevel = 'info'
# errorlog = os.path.join(_VAR, 'log/api-error.log')
# accesslog = os.path.join(_VAR, 'log/api-access.log')
errorlog = "-"
accesslog = "-"

# bind = 'unix:%s' % os.path.join(_VAR, 'run/gunicorn.sock')
bind = '0.0.0.0:8000'

workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'eventlet'
preload_app = True

timeout = 3 * 60  # 3 minutes
keepalive = 24 * 60 * 60  # 1 day

capture_output = True

debug = True

Мое Flask Приложение:

import eventlet
eventlet.monkey_patch()

from flask import Flask, render_template, make_response
from flask_session import Session
from flask_cors import CORS

import os

app = Flask(__name__)

GEVENT_SUPPORT = True
cors = CORS(app)

app.secret_key = os.urandom(24)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_KEY_PREFIX'] = "myapp"
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
app.config['GOOGLE_LOGIN_REDIRECT_SCHEME'] = "https"

if os.getenv('MYAPP', 'PROD') == 'DEV':
    app.debug = True

app._static_folder = os.path.abspath("./app/templates/prod/static/")
if os.getenv('VTABLE', 'PROD') == 'DEV':
        app._static_folder = os.path.abspath("./app/templates/dev/static/")

Session(app)

from app import routes
import app.sock as sock

if __name__ == 'app':
    if os.getenv('VTABLE', 'PROD') == 'DEV':
        sock.socketio.run(app, host='0.0.0.0', port=5000, keyfile='key.pem', certfile='cert.pem')
    else:
        sock.socketio.run(app, host='0.0.0.0', port=5000)

Начало app / sock.py:

from flask_session import Session
from flask_socketio import SocketIO
from flask_socketio import send, emit, join_room, leave_room

from cachelib.file import FileSystemCache
from engineio.payload import Payload
from engineio.async_drivers import eventlet
from werkzeug.middleware.proxy_fix import ProxyFix

import json
import random
import time
import uuid
from uuid import UUID

from app import app
from app import routes

Session(app)
socketio = SocketIO(app, async_mode='eventlet')

session = routes.session

@socketio.on('player_join')
def on_join(player_key):
    join_room(player_key)
...