gunicorn uvicorn worker.py comment honorer le paramètre limit_concurrency
FastAPI utilise gunicorn pour lancer des workers uvicorn comme décrit dans https://www.uvicorn.org/settings/
Cependant, gunicorn ne permet pas de lancer uvicorn avec des paramètres personnalisés comme également mentionné dans https://github.com/encode/uvicorn/issues/343
Le problème a suggéré de remplacer les config_kwargs dans le fichier source comme https://github.com/encode/uvicorn/blob/master/uvicorn/workers.py
Nous l'avons essayé mais uvicorn n'honore pas le paramètre limit_concurrency
dans plusieurs fichiers uvicorn dans la source:
https://github.com/encode/uvicorn/blob/master/uvicorn/workers.py
# fail
config_kwargs = {
"app": None,
"log_config": None,
"timeout_keep_alive": self.cfg.keepalive,
"timeout_notify": self.timeout,
"callback_notify": self.callback_notify,
"limit_max_requests": self.max_requests, "limit_concurrency": 10000,
"forwarded_allow_ips": self.cfg.forwarded_allow_ips,
}
https://github.com/encode/uvicorn/blob/master/uvicorn/main.py
# fail
kwargs = {
"app": app,
"host": host,
"port": port,
"uds": uds,
"fd": fd,
"loop": loop,
"http": http,
"ws": ws,
"lifespan": lifespan,
"env_file": env_file,
"log_config": LOGGING_CONFIG if log_config is None else log_config,
"log_level": log_level,
"access_log": access_log,
"interface": interface,
"debug": debug,
"reload": reload,
"reload_dirs": reload_dirs if reload_dirs else None,
"workers": workers,
"proxy_headers": proxy_headers,
"forwarded_allow_ips": forwarded_allow_ips,
"root_path": root_path,
"limit_concurrency": 10000,
"backlog": backlog,
"limit_max_requests": limit_max_requests,
"timeout_keep_alive": timeout_keep_alive,
"ssl_keyfile": ssl_keyfile,
"ssl_certfile": ssl_certfile,
"ssl_version": ssl_version,
"ssl_cert_reqs": ssl_cert_reqs,
"ssl_ca_certs": ssl_ca_certs,
"ssl_ciphers": ssl_ciphers,
"headers": list([header.split(":") for header in headers]),
"use_colors": use_colors,
}
Comment uvicorn peut-il être obligé d'honorer ce paramètre? Nous recevons toujours 503 erreurs de FastAPI
------- MISE À JOUR ----------- le paramètre gunicorn --worker-connections 1000
provoque toujours 503 lors de 100 requêtes parallèles qui sont distribuées à de nombreux travailleurs.
Cependant, je pense que c'est un problème un peu plus compliqué: notre point de terminaison d'API fait beaucoup de travail lourd, prend généralement 5 secondes.
Test de résistance avec 2 cœurs, 2 travailleurs:
- A. Plus de 100 demandes simultanées, forte charge de point final - connexions-travailleurs 1
- Plus de 100 requêtes simultanées, forte charge de point final - connexions-travailleurs 1000
- C.Plus de 100 requêtes simultanées, faible charge du point final - connexions-travailleurs 1
- D.Plus de 100 demandes simultanées, faible charge du point final - connexions-travailleurs 1000
Les deux expériences A et B ont donné 503 réponses, donc en supposant que le paramètre de connexions de travail fonctionne, trop de connexions simulées semblent ne pas causer nos 503 erreurs.
Nous sommes déconcertés par ce comportement, car nous nous attendons à ce que gunicorn / uvicorn fasse la queue le travail et ne génère pas d'erreurs 503.
Réponses
De la doc gunicorn
worker-connections
Le nombre maximum de clients simultanés.
et de uvicorn doc
limit-concurrency
Nombre maximum de connexions ou de tâches simultanées à autoriser, avant d'émettre des réponses HTTP 503.
Selon cette information, les deux paramètres variables font la même chose. Alors
uvicorn --limit-concurrency 100 application:demo_app
est presque le même que
gunicorn --worker-connections 100 -k uvicorn.workers.UvicornWorker application:demo_app
Remarque: je n'ai pas fait de vrai test à ce sujet, veuillez me corriger si je me trompe.
En outre, vous pouvez définir limit-concurrency
(ou limit_concurrency
) en sous-classant la uvicorn.workers.UvicornWorker
classe
from uvicorn.workers import UvicornWorker
class CustomUvicornWorker(UvicornWorker):
CONFIG_KWARGS = {
"loop": "uvloop",
"http": "httptools",
"limit_concurrency": 100
}
et utilisez maintenant ceci CustomUvicornWorker
avec la gunicorn
commande comme,
gunicorn -k path.to.custom_worker.CustomUvicornWorker application:demo_app
Remarque: vous pouvez inspecter self.config.limit_concurrency
en CustomUvicornWorker
classe pour vous assurer que la valeur a été correctement définie.