mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
fix(api): uvicorn worker keepalive (#11663)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,8 @@ import multiprocessing
|
||||
import os
|
||||
import threading
|
||||
|
||||
from uvicorn_worker import UvicornWorker
|
||||
|
||||
from config.env import env
|
||||
|
||||
# Ensure the environment variable for Django settings is set
|
||||
@@ -12,6 +14,7 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.django.production")
|
||||
import django # noqa: E402
|
||||
|
||||
django.setup()
|
||||
|
||||
from api.compliance import warm_compliance_caches # noqa: E402
|
||||
from config.django.production import LOGGING as DJANGO_LOGGERS, DEBUG # noqa: E402
|
||||
from config.custom_logging import BackendLogger # noqa: E402
|
||||
@@ -19,34 +22,28 @@ from config.custom_logging import BackendLogger # noqa: E402
|
||||
BIND_ADDRESS = env("DJANGO_BIND_ADDRESS", default="127.0.0.1")
|
||||
PORT = env("DJANGO_PORT", default=8080)
|
||||
|
||||
|
||||
class ProwlerUvicornWorker(UvicornWorker):
|
||||
CONFIG_KWARGS = {
|
||||
# Keep-alive idle timeout. Must exceed the load balancer idle timeout.
|
||||
"timeout_keep_alive": env.int("GUNICORN_KEEPALIVE", default=75),
|
||||
"loop": "uvloop",
|
||||
"lifespan": "off", # Django ASGIHandler doesn't handle lifespan scopes
|
||||
}
|
||||
|
||||
|
||||
# Required so SSE endpoints can keep the event loop alive while waiting for events
|
||||
worker_class = env(
|
||||
"DJANGO_WORKER_CLASS",
|
||||
default="config.guniconf.ProwlerUvicornWorker",
|
||||
)
|
||||
|
||||
# Server settings
|
||||
bind = f"{BIND_ADDRESS}:{PORT}"
|
||||
|
||||
workers = env.int("DJANGO_WORKERS", default=multiprocessing.cpu_count() * 2 + 1)
|
||||
reload = DEBUG
|
||||
|
||||
# Native ASGI worker (gunicorn 24+). Required so SSE endpoints can keep the
|
||||
# event loop alive while waiting for events.
|
||||
worker_class = env("DJANGO_WORKER_CLASS", default="asgi")
|
||||
|
||||
# Lifespan protocol. Django's ASGIHandler (config.asgi:application) serves only
|
||||
# HTTP scopes and raises "Django can only handle ASGI/HTTP connections, not
|
||||
# lifespan." gunicorn's default ("auto") probes the app with a lifespan scope
|
||||
# to detect support, which triggers that error. We use no lifespan startup or
|
||||
# shutdown hooks, so disable the protocol entirely.
|
||||
asgi_lifespan = env("DJANGO_ASGI_LIFESPAN", default="off")
|
||||
|
||||
# Event loop for the ASGI worker. "auto" uses uvloop when it is installed and
|
||||
# falls back to the stdlib asyncio loop otherwise; uvloop gives the SSE event
|
||||
# loop more headroom under many concurrent open streams.
|
||||
asgi_loop = env("DJANGO_ASGI_LOOP", default="uvloop")
|
||||
|
||||
# Max concurrent connections per ASGI worker. Each open SSE stream holds one
|
||||
# connection for its whole lifetime, so this caps simultaneous SSE clients per
|
||||
# worker (gunicorn's default is 1000). The sync-only `threads` option has no
|
||||
# effect on ASGI workers.
|
||||
worker_connections = env.int("DJANGO_WORKER_CONNECTIONS", default=1000)
|
||||
|
||||
# Preload the application before forking workers in production: the app is
|
||||
# imported once in the master and workers fork from it. In development, disable
|
||||
# preload so the server restarts on code changes.
|
||||
@@ -56,12 +53,6 @@ preload_app = not DEBUG
|
||||
# that may take longer, such as complex API operations.
|
||||
timeout = env.int("GUNICORN_TIMEOUT", default=120)
|
||||
|
||||
# HTTP keep-alive idle timeout. Must exceed the idle timeout of the proxy or load
|
||||
# balancer in front of gunicorn, or it reuses a connection gunicorn just closed
|
||||
# and returns a 502. Default clears the common 60s; raise `GUNICORN_KEEPALIVE` to
|
||||
# stay above a longer one.
|
||||
keepalive = env.int("GUNICORN_KEEPALIVE", default=75)
|
||||
|
||||
# Logging
|
||||
logconfig_dict = DJANGO_LOGGERS
|
||||
gunicorn_logger = logging.getLogger(BackendLogger.GUNICORN)
|
||||
|
||||
Reference in New Issue
Block a user