From 91639387e0aef44cf07f99f85b58d5af6e7839be Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:34:15 +0800 Subject: [PATCH] perf: support gunicorn-gthread & use daphne-websocket (#16703) * perf: support gunicorn-gthread & use daphne-websocket * perf: support gunicorn-wsgi & gunicorn-asgi --------- Co-authored-by: Bai --- .../management/commands/services/command.py | 37 ++++++++++++----- .../management/commands/services/hands.py | 1 + .../commands/services/services/__init__.py | 1 + .../commands/services/services/gunicorn.py | 3 +- .../services/services/gunicorn_wsgi.py | 40 +++++++++++++++++++ apps/jumpserver/conf.py | 2 + apps/jumpserver/settings/custom.py | 2 + 7 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 apps/common/management/commands/services/services/gunicorn_wsgi.py diff --git a/apps/common/management/commands/services/command.py b/apps/common/management/commands/services/command.py index 27ce96846..fb292e64a 100644 --- a/apps/common/management/commands/services/command.py +++ b/apps/common/management/commands/services/command.py @@ -21,6 +21,7 @@ if SERVER_SIZE == 'auto': class Services(TextChoices): gunicorn = 'gunicorn', 'gunicorn' + gunicorn_wsgi = 'gunicorn_wsgi', 'gunicorn_wsgi' celery_ansible = 'celery_ansible', 'celery_ansible' celery_default = 'celery_default', 'celery_default' celery_combine = 'celery_combine', 'celery_combine' @@ -36,7 +37,8 @@ class Services(TextChoices): def get_service_object_class(cls, name): from . import services services_map = { - cls.gunicorn.value: services.GunicornService, + cls.gunicorn: services.GunicornService, + cls.gunicorn_wsgi: services.GunicornWSGIService, cls.flower: services.FlowerService, cls.celery_default: services.CeleryDefaultService, cls.celery_ansible: services.CeleryAnsibleService, @@ -47,10 +49,15 @@ class Services(TextChoices): @classmethod def web_services(cls): + services = [cls.gunicorn] + if GUNICORN_WSGI_ENABLED: + services.append(cls.gunicorn_wsgi) + if SERVER_SIZE == 'small' or os.environ.get('FLOWER_ENABLED', '1') == '0': - return [cls.gunicorn] + return services else: - return [cls.gunicorn, cls.flower] + services.append(cls.flower) + return services @classmethod def celery_services(cls): @@ -123,16 +130,28 @@ class BaseActionCommand(BaseCommand): parser.add_argument('-f', '--force', nargs="?", const=True) def get_services_kwargs(self, options): - worker = options.get('worker', 4) - if SERVER_SIZE == 'small': worker = 1 + else: + worker = options.get('worker', 4) - return { - 'gunicorn': { - 'worker': worker + if GUNICORN_WSGI_ENABLED: + kwargs = { + 'gunicorn': { + 'worker': 1, + 'bind_port': WS_PORT, + }, + 'gunicorn_wsgi': { + 'worker': worker, + } } - } + else: + kwargs = { + 'gunicorn': { + 'worker': worker, + }, + } + return kwargs def initial_util(self, *args, **options): service_names = options.get('services') diff --git a/apps/common/management/commands/services/hands.py b/apps/common/management/commands/services/hands.py index fb289aea4..103e12984 100644 --- a/apps/common/management/commands/services/hands.py +++ b/apps/common/management/commands/services/hands.py @@ -26,3 +26,4 @@ LOG_DIR = os.path.join(BASE_DIR, 'data', 'logs') APPS_DIR = os.path.join(BASE_DIR, 'apps') TMP_DIR = os.path.join(BASE_DIR, 'tmp') CELERY_WORKER_COUNT = CONFIG.CELERY_WORKER_COUNT or 10 +GUNICORN_WSGI_ENABLED = CONFIG.GUNICORN_WSGI_ENABLED or False \ No newline at end of file diff --git a/apps/common/management/commands/services/services/__init__.py b/apps/common/management/commands/services/services/__init__.py index 430e9891e..dfeb8c4df 100644 --- a/apps/common/management/commands/services/services/__init__.py +++ b/apps/common/management/commands/services/services/__init__.py @@ -4,3 +4,4 @@ from .celery_default import * from .celery_combine import * from .flower import * from .gunicorn import * +from .gunicorn_wsgi import * diff --git a/apps/common/management/commands/services/services/gunicorn.py b/apps/common/management/commands/services/services/gunicorn.py index 794928e09..b654198fc 100644 --- a/apps/common/management/commands/services/services/gunicorn.py +++ b/apps/common/management/commands/services/services/gunicorn.py @@ -8,6 +8,7 @@ class GunicornService(BaseService): def __init__(self, **kwargs): self.worker = kwargs.get('worker', 2) + self.bind_port = kwargs.get('bind_port', HTTP_PORT) super().__init__(**kwargs) @property @@ -15,7 +16,7 @@ class GunicornService(BaseService): print("\n- Start Gunicorn WSGI HTTP Server") log_format = '%(h)s %(t)s %(L)ss "%(r)s" %(s)s %(b)s ' - bind = f'{HTTP_HOST}:{HTTP_PORT}' + bind = f'{HTTP_HOST}:{self.bind_port}' cmd = [ 'gunicorn', 'jumpserver.asgi:application', diff --git a/apps/common/management/commands/services/services/gunicorn_wsgi.py b/apps/common/management/commands/services/services/gunicorn_wsgi.py new file mode 100644 index 000000000..6015f118f --- /dev/null +++ b/apps/common/management/commands/services/services/gunicorn_wsgi.py @@ -0,0 +1,40 @@ +from ..hands import * +from .base import BaseService + +__all__ = ['GunicornWSGIService'] + + +class GunicornWSGIService(BaseService): + + def __init__(self, **kwargs): + self.worker = kwargs.get('worker', 2) + super().__init__(**kwargs) + + @property + def cmd(self): + print("\n- Start Gunicorn WSGI HTTP Server") + + log_format = '%(h)s %(t)s %(L)ss "%(r)s" %(s)s %(b)s ' + bind = f'{HTTP_HOST}:{HTTP_PORT}' + cmd = [ + 'gunicorn', 'jumpserver.wsgi', + '-b', bind, + '-k', 'gthread', + '--threads', '10', + '-w', str(self.worker), + '--max-requests', '4096', + '--access-logformat', log_format, + '--access-logfile', '-' + ] + if DEBUG: + cmd.append('--reload') + return cmd + + @property + def cwd(self): + return APPS_DIR + + def start_other(self): + from terminal.startup import CoreTerminal + core_terminal = CoreTerminal() + core_terminal.start_heartbeat_thread() \ No newline at end of file diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 0599261de..d1a0dda99 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -641,6 +641,8 @@ class Config(dict): 'WS_LISTEN_PORT': 8070, 'CELERY_WORKER_COUNT': 10, + 'GUNICORN_WSGI_ENABLED': False, + 'SYSLOG_ADDR': '', # '192.168.0.1:514' 'SYSLOG_FACILITY': 'user', 'SYSLOG_SOCKTYPE': 2, diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index fe916dbea..6bc2bdad7 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -298,3 +298,5 @@ JDMC_BASE_URL = f"http+unix://{quote(JDMC_SOCK_PATH, safe='')}" # WebHook WEBHOOK_ENABLED = CONFIG.WEBHOOK_ENABLED WEBHOOK_TOKEN = CONFIG.WEBHOOK_TOKEN + +GUNICORN_WSGI_ENABLED = CONFIG.GUNICORN_WSGI_ENABLED \ No newline at end of file