Gunicorn y Uvicorn
Gunicorn gestiona procesos de worker para aplicaciones WSGI y ASGI; Uvicorn implementa el servidor ASGI. FastAPI en producción en 0.115+ comúnmente usa Gunicorn con UvicornWorker para concurrencia multi-proceso más I/O asíncrono.
Receta
gunicorn app.main:app \
-w 4 \
-k uvicorn.workers.UvicornWorker \
-b 0.0.0.0:8000 \
--timeout 60 \
--graceful-timeout 30 \
--access-logfile -Cuándo usar esto:
- Despliegues de FastAPI/Starlette en producción
- Flask/Django WSGI con workers síncronos (
-k syncpor defecto) - Modelo de proceso único en contenedores con pool de workers interno
- Despliegues sin interrupción que necesiten manejo de SIGTERM
Ejemplo Funcional
Archivo de configuración de Gunicorn ajustado para FastAPI con logging y número de workers desde la variable de entorno.
# gunicorn.conf.py
import multiprocessing
import os
bind = f"0.0.0.0:{os.environ.get('PORT', '8000')}"
worker_class = "uvicorn.workers.UvicornWorker"
workers = int(os.environ.get("WEB_CONCURRENCY", multiprocessing.cpu_count()))
timeout = 60
graceful_timeout = 30
keepalive = 5
accesslog = "-"
errorlog = "-"
loglevel = os.environ.get("LOG_LEVEL", "info")gunicorn -c gunicorn.conf.py app.main:appLo que esto demuestra:
- El patrón
WEB_CONCURRENCYcoincide con las convenciones de Heroku/Render UvicornWorkerejecuta ASGI por proceso de worker- Logs de acceso/error a stdout para recolectores de logs de contenedores
Análisis Profundo
Modelos de Worker
| Pila Tecnológica | Clase de Worker |
|---|---|
| Flask/Django síncrono | sync (por defecto) |
| FastAPI asíncrono | uvicorn.workers.UvicornWorker |
| gevent (legado) | gevent |
Puntos de Partida para el Ajuste
- Workers:
2-4 x núcleos de CPUpara tareas síncronas ligadas a CPU; menos para ML intensivo en memoria - Timeout: superior al tiempo de petición p99; evitar matar peticiones legítimas lentas
- Keepalive: coincidir con la configuración de keepalive del proxy inverso
Notas de Python
# Solo para desarrollo - recarga de un solo worker
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000Errores Comunes
- Demasiados workers en una aplicación de ML - OOM mata el contenedor. Solución: reducir workers o externalizar la inferencia.
- Workers síncronos para una aplicación puramente de I/O asíncrono - subutiliza la concurrencia. Solución: UvicornWorker o uvicorn puro con async.
- Timeout más corto que la consulta a la base de datos - 502 durante informes. Solución: aumentar el timeout o mover trabajos largos a una cola.
- Sin timeout gradual en el despliegue - peticiones en curso abortadas. Solución:
--graceful-timeout+ retardo del hookpreStopen K8s. - Ejecutar uvicorn --reload en producción - inseguro e inestable. Solución: configuración de gunicorn sin reload.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Hypercorn | Necesidades de ASGI HTTP/2 | El estándar del equipo es Gunicorn |
| uWSGI | Tiendas Django legadas | FastAPI nuevo |
| Múltiples réplicas de uvicorn | Modelo de un proceso por pod de K8s | Querer un pool de workers dentro del contenedor |
Preguntas Frecuentes
¿gunicorn vs uvicorn solo?
Gunicorn supervisa múltiples workers de Uvicorn; un solo uvicorn es suficiente para desarrollo y producción pequeña con escalado externo.
¿Cómo calculo los workers?
Empezar con el número de CPU para I/O asíncrono; la mitad de la CPU para síncrono ligado a CPU; medir latencia y RSS bajo carga.
¿Django usa UvicornWorker?
Las vistas asíncronas de Django 5.2 pueden; la mayoría de los despliegues de Django siguen siendo workers Gunicorn síncronos a menos que la ruta asíncrona sea explícita.
¿Qué pasa con los websockets?
UvicornWorker soporta websockets; los workers Gunicorn síncronos no.
¿Cómo expongo métricas?
Directorio multiproceso de Prometheus cuando se usan múltiples workers síncronos; middleware ASGI para métricas de peticiones.
¿Cómo recargan código los workers?
Desplegar una nueva imagen de contenedor - no depender de la recarga HUP en infraestructura inmutable.
¿Workers de hilo?
gthread para algo de solapamiento de I/O WSGI - menos común que ASGI asíncrono para nuevos servicios FastAPI.
¿Cómo enlazo IPv6?
[::]:8000 cuando la plataforma requiere doble pila - verificar la configuración del balanceador de carga.
¿Terminación SSL?
En el balanceador de carga o el ingress - no usualmente en Gunicorn dentro del contenedor.
¿Cómo interactúa esto con Kubernetes?
Un contenedor ejecuta Gunicorn con N workers; HPA escala pods según CPU/RPS - ver la página de Kubernetes.
Relacionado
- Conceptos Básicos de Despliegue - Introducción a WSGI/ASGI
- Dockerizar Python - CMD usa Gunicorn
- Despliegues sin Interrupción - apagado gradual
- Estado de Salud y Preparación - sondas
- Monitorización de Rendimiento (APM) - ajuste de latencia
Versiones de la Pila Tecnológica: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.