|
1 | 1 | """
|
2 |
| -Conf file extracted from: |
| 2 | +Conf file adapted from: |
3 | 3 | https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/docker-images/gunicorn_conf.py
|
4 | 4 | """
|
5 |
| -# pylint: disable=invalid-name |
6 | 5 |
|
7 | 6 | import multiprocessing
|
8 |
| -import os |
| 7 | +from typing import Optional |
9 | 8 |
|
10 | 9 | from prometheus_client import multiprocess
|
| 10 | +from pydantic import BaseSettings, conint, root_validator, validator |
11 | 11 |
|
12 |
| -workers_per_core_str = os.getenv("WORKERS_PER_CORE", "1") |
13 |
| -max_workers_str = os.getenv("MAX_WORKERS") |
14 |
| -use_max_workers = None |
15 |
| -if max_workers_str: |
16 |
| - use_max_workers = int(max_workers_str) |
17 |
| -web_concurrency_str = os.getenv("WEB_CONCURRENCY", None) |
18 | 12 |
|
19 |
| -host = os.getenv("HOST", "0.0.0.0") |
20 |
| -port = os.getenv("PORT", "8000") |
21 |
| -bind_env = os.getenv("BIND", None) |
22 |
| -use_loglevel = os.getenv("LOG_LEVEL", "info") |
23 |
| -if bind_env: |
24 |
| - use_bind = bind_env |
25 |
| -else: |
26 |
| - use_bind = f"{host}:{port}" |
| 13 | +class GunicornSettings(BaseSettings): |
| 14 | + keep_alive: int = 5 |
| 15 | + timeout: int = 120 |
| 16 | + graceful_timeout: int = 120 |
| 17 | + log_level: str = "info" |
| 18 | + host: str = "0.0.0.0" |
| 19 | + port: str = "8000" |
| 20 | + bind: Optional[str] |
| 21 | + access_log: str = "-" |
| 22 | + error_log: str = "-" |
| 23 | + workers_per_core: float = 1.0 |
| 24 | + max_workers: Optional[int] |
| 25 | + web_concurrency: Optional[conint(gt=0)] |
| 26 | + workers: Optional[int] |
27 | 27 |
|
28 |
| -cores = multiprocessing.cpu_count() |
29 |
| -workers_per_core = float(workers_per_core_str) |
30 |
| -default_web_concurrency = workers_per_core * cores |
31 |
| -if web_concurrency_str: |
32 |
| - web_concurrency = int(web_concurrency_str) |
33 |
| - assert web_concurrency > 0 |
34 |
| -else: |
35 |
| - web_concurrency = max(int(default_web_concurrency), 2) |
36 |
| - if use_max_workers: |
37 |
| - web_concurrency = min(web_concurrency, use_max_workers) |
38 |
| -accesslog_var = os.getenv("ACCESS_LOG", "-") |
39 |
| -use_accesslog = accesslog_var or None |
40 |
| -errorlog_var = os.getenv("ERROR_LOG", "-") |
41 |
| -use_errorlog = errorlog_var or None |
42 |
| -graceful_timeout_str = os.getenv("GRACEFUL_TIMEOUT", "120") |
43 |
| -timeout_str = os.getenv("TIMEOUT", "120") |
44 |
| -keepalive_str = os.getenv("KEEP_ALIVE", "5") |
| 28 | + @validator("bind") |
| 29 | + def set_bind(cls, bind, values): |
| 30 | + return bind if bind else f"{values['host']}:{values['port']}" |
| 31 | + |
| 32 | + @root_validator(skip_on_failure=True) |
| 33 | + def set_workers(cls, values): |
| 34 | + if values["workers"] is not None: |
| 35 | + return values |
| 36 | + elif values["web_concurrency"]: |
| 37 | + values["workers"] = values["web_concurrency"] |
| 38 | + else: |
| 39 | + cores = multiprocessing.cpu_count() |
| 40 | + default_workers = values["workers_per_core"] * cores |
| 41 | + workers = max(int(default_workers), 2) |
| 42 | + if values["max_workers"]: |
| 43 | + workers = min(workers, values["max_workers"]) |
| 44 | + values["workers"] = workers |
| 45 | + return values |
| 46 | + |
| 47 | + |
| 48 | +gunicorn_settings = GunicornSettings() |
45 | 49 |
|
46 | 50 | # Gunicorn config variables
|
47 |
| -loglevel = use_loglevel |
48 |
| -workers = web_concurrency |
49 |
| -bind = use_bind |
50 |
| -errorlog = use_errorlog |
| 51 | +# https://docs.gunicorn.org/en/stable/settings.html#settings |
| 52 | +loglevel = gunicorn_settings.log_level |
| 53 | +workers = gunicorn_settings.workers |
| 54 | +bind = gunicorn_settings.bind |
| 55 | +errorlog = gunicorn_settings.error_log |
51 | 56 | worker_tmp_dir = "/dev/shm"
|
52 |
| -accesslog = use_accesslog |
53 |
| -graceful_timeout = int(graceful_timeout_str) |
54 |
| -timeout = int(timeout_str) |
55 |
| -keepalive = int(keepalive_str) |
| 57 | +accesslog = gunicorn_settings.access_log |
| 58 | +graceful_timeout = gunicorn_settings.graceful_timeout |
| 59 | +timeout = gunicorn_settings.timeout |
| 60 | +keepalive = gunicorn_settings.keep_alive |
56 | 61 |
|
57 | 62 |
|
58 | 63 | # For debugging and testing
|
|
66 | 71 | "errorlog": errorlog,
|
67 | 72 | "accesslog": accesslog,
|
68 | 73 | # Additional, non-gunicorn variables
|
69 |
| - "workers_per_core": workers_per_core, |
70 |
| - "use_max_workers": use_max_workers, |
71 |
| - "host": host, |
72 |
| - "port": port, |
| 74 | + "workers_per_core": gunicorn_settings.workers_per_core, |
| 75 | + "use_max_workers": gunicorn_settings.max_workers, |
| 76 | + "host": gunicorn_settings.host, |
| 77 | + "port": gunicorn_settings.port, |
73 | 78 | }
|
74 | 79 |
|
75 | 80 |
|
|
0 commit comments