66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
# gunicorn.conf.py
|
|
|
|
# Server socket
|
|
bind = "127.0.0.1:7000" # match your nginx proxy_pass port
|
|
backlog = 2048
|
|
|
|
# Worker — eventlet requires exactly 1 worker process.
|
|
# Concurrency is handled by eventlet's cooperative green-thread pool.
|
|
worker_class = "eventlet"
|
|
workers = 1
|
|
worker_connections= 2000
|
|
timeout = 300
|
|
keepalive = 75
|
|
|
|
# preload_app must be False with the eventlet worker.
|
|
#
|
|
# With preload_app = True, gunicorn loads the WSGI app in the master process
|
|
# before forking workers. At that point gunicorn's own internals have already
|
|
# imported `logging` and other stdlib modules, creating real OS RLocks.
|
|
# The eventlet worker calls eventlet.monkey_patch() at its own import time —
|
|
# but that import happens *after* the master has already loaded the app, so
|
|
# the patch arrives too late and eventlet emits:
|
|
# "1 RLock(s) were not greened"
|
|
#
|
|
# With preload_app = False, workers are forked first. The eventlet worker
|
|
# module is imported inside each worker process, its module-level
|
|
# monkey_patch() fires before the app is loaded, and all subsequent imports
|
|
# (including logging) get the green versions from the start.
|
|
preload_app = False
|
|
|
|
# Application
|
|
wsgi_app = "run:app"
|
|
|
|
# Logging
|
|
accesslog = "logs/gunicorn_access.log"
|
|
errorlog = "logs/gunicorn_error.log"
|
|
loglevel = "warning" # suppress routine socket close noise
|
|
capture_output = False # don't capture eventlet's stderr Errno 9 messages
|
|
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(a)s" %(D)sµs'
|
|
|
|
# Process naming
|
|
proc_name = "it_ticket_system"
|
|
daemon = False
|
|
pidfile = "/tmp/it_tickets.pid"
|
|
|
|
|
|
def post_fork(server, worker):
|
|
"""Called after a worker is forked. Patch eventlet per-worker."""
|
|
import eventlet
|
|
eventlet.monkey_patch()
|
|
|
|
|
|
def worker_exit(server, worker):
|
|
"""
|
|
Called when a worker exits. Cleanly close any remaining eventlet sockets
|
|
to prevent [Errno 9] Bad file descriptor errors in the logs.
|
|
These errors are benign (connections recover automatically) but noisy.
|
|
"""
|
|
try:
|
|
import eventlet.greenio
|
|
# Hub cleanup — tells eventlet to stop watching all open file descriptors
|
|
hub = eventlet.hubs.get_hub()
|
|
if hasattr(hub, 'abort'):
|
|
hub.abort(wait=False)
|
|
except Exception:
|
|
pass |