1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00

fix(gunicorn): at most 8 workers, and why the timeout stays 600 s

This commit is contained in:
catborise 2026-10-07 17:46:24 +03:00
parent 40d66003ea
commit 09f5a837c8
3 changed files with 36 additions and 1 deletions

View file

@ -287,6 +287,7 @@ Where to set them:
- **Docker:** the `environment:` list of `docker-compose.override.yml`; every process in the container gets it.
- **Installer and manual installation:** edit `webvirtcloud/settings.py`, or put the same `environment=` line in both `[program:webvirtcloud]` and `[program:novncd]` of the supervisor config (novncd reads the database too) and export the variables before running `manage.py`.
- **gunicorn** runs at most 8 workers (fewer on hosts with under 4 CPUs); to change it, set `GUNICORN_CMD_ARGS="--workers N"` in the `[program:webvirtcloud]` environment or in `docker-compose.override.yml`.
### HTTPS and reverse proxy

View file

@ -73,14 +73,22 @@ backlog = 2048
#
# Sync workers, each holding its own libvirt connections and blocking for a
# whole long operation; capped so a big host does not start dozens of them
# against sqlite. Override with GUNICORN_CMD_ARGS="--workers N".
MAX_WORKERS = 8
def get_workers():
procs = os.sysconf('SC_NPROCESSORS_ONLN')
return procs * 2 + 1 if procs > 0 else 3
return min(procs * 2 + 1, MAX_WORKERS) if procs > 0 else 3
workers = get_workers()
# worker_class = 'egg:gunicorn#eventlet'
worker_connections = 1000
# Must exceed instances.utils.MIGRATION_TIME_LIMIT (540 s) plus time to answer;
# a lower value would kill a worker in the middle of a live migration.
timeout = 600
keepalive = 2

View file

@ -0,0 +1,26 @@
"""gunicorn runs a bounded number of sync workers."""
import runpy
import unittest
from pathlib import Path
from unittest.mock import patch
from django.conf import settings
CONF = str(Path(settings.BASE_DIR) / "gunicorn.conf.py")
def load(cpus):
with patch("os.sysconf", return_value=cpus):
return runpy.run_path(CONF)
class GunicornConfTestCase(unittest.TestCase):
def test_worker_count_is_capped(self):
self.assertEqual(load(64)["workers"], 8)
def test_small_hosts_keep_two_per_cpu_plus_one(self):
self.assertEqual(load(2)["workers"], 5)
def test_unknown_cpu_count_falls_back(self):
self.assertEqual(load(-1)["workers"], 3)