3

I am running Flask through Gunicorn and I have a big problem. I get [CRITICAL] WORKER_TIMEOUT errors. To fix this I added "preload_app = True" to my gunicorn config. Add it almost works. The problem I am having is gunicorn will not start unless I send the SIGINT signal. Tis only happens with preload_app.

Here is the out put:

(.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

Notice the ^C before anything happens. Unless I interrupt the wait is indefinite. In addition to not starting, when I do want to terminate, I must "pkill -9 ". It will hang for hours with any other method.

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

My Flask App:

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)

The beginning of 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)

0 Answers0