Requisitos del Entorno
Para realizar esta implementación se requiere un sistema operativo basado en Linux (Ubuntu 18.04 o superior), junto con las siguientes versiones de software:
- Servidor Web: Nginx 1.14+
- Servidor de Aplicaciones: uWSGI 2.0.18
- Framework: Flask 1.1.2
- Gestor de Procesos: Supervisor 4.1.0
- Interpretador: Python 3.6+
Fundamentos de la Arquitectura
Antes de proceder con la configuración, es crucial entender el rol de cada componente en la pila tecnológica:
- WSGI: Actúa como una interfaz de comunicación estandarizada entre el servidor web y la aplicación Python. Define cómo el servidor solicita datos a la aplicación mediante objetos llamables.
- uWSGI: Es una implementación del protocolo WSGI escrita en C, diseñada para manejar conexiones de alto rendimiento. A diferencia de un servidor HTTP puro, uWSGI procesa las solicitudes y delega la lógica de negocio a la aplicación.
- Nginx: Funciona como un proxy inverso que gestiona el tráfico de entrada, distribuyendo solicitudes hacia las instancias uWSGI y manejando recursos estáticos.
Preparación del Código Fuente
Crearemos un archivo principal que exponga la aplicación Flask. Cambiaremos el nombre de la variable de instancia para diferenciarla del estándar inicial.
Inicialización del objeto aplicacion
service_instance = Flask(name)
@service_instance.route('/estado') def verificar_estado(): # Retornamos JSON en lugar de texto plano return jsonify({ 'servicio': 'activo', 'version': '1.0.0' })
No ejecutamos app.run() directamente ya que lo gestionará uWSGI
if name == 'main': service_instance.run(port=5000)
</div>### Gestión de Entornos Virtuales
Es recomendable aislar las dependencias del proyecto utilizando herramientas de gestión de entornos.
Instalación de utilidades:
pip3 install virtualenv virtualenvwrapper
Configuración del shell para persistir la ruta del entorno:
export WORKON_HOME=$HOME/.virtualenvs/flask_envs source /usr/local/bin/virtualenvwrapper.sh
Comandos esenciales de operación:
- Crear entorno: `mkvirtualenv -p python3 backend_env`
- Activar entorno: `workon backend_env`
- Desactivar entorno: `deactivate`
### Configuración del Servidor uWSGI
Dentro del directorio del proyecto, generamos un archivo de configuración `prod_uwsgi.ini` para definir cómo se levantará el proceso.
<div class="code-block">```
<code>
[uwsgi]
# Conexión TCP local
socket=127.0.0.1:9000
# Ruta base del proyecto
chdir=/var/www/html/my_flask_app
# Ubicación del entorno virtual
home=/home/user/.virtualenvs/backend_env
# Importación del módulo WSGI
module=main_service
# Variable a llamar dentro del módulo
callable=service_instance
# Cantidad de procesos workers
processes=4
# Hilos por proceso
threads=2
# Archivo PID para control
pidfile=/tmp/my_project.pid
# Redirección de registros
logto=/var/log/uwsgi/req.log
</code&>
- Opción 1:
wsgi-file=main_service.pyycallable=service_instance - Opción 2:
module=main_service:service_instance
Automatización con Supervisor
Utilizamos Supervisor para asegurar que el servicio de uWSGI se reinicie automáticamente ante fallos.
Instalación:
sudo apt-get install supervisor
Definimos la configuración de monitoreo en /etc/supervisor/conf.d/uwsgi_web.conf:
supervisorctl reread && supervisorctl update: Recargar cambiossupervisorctl status: Verificar estadosupervisorctl restart flask_production: Reiniciar servicio específico
Configuración del Proxy Inverso (Nginx)
El servidor Nginx debe escuchar en el puerto público y transmitir las peticiones dinámicas a uWSGI.
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:9000;
# Cabeceras adicionales para seguridad
uwsgi_param Host $host;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $scheme;
}
} </code&>
</div>Verificación de la configuración Nginx:
nginx -t && sudo systemctl reload nginx
### Balanceo de Carga Distribuido
Para escalar horizontalmente, definimos múltiples instancias de uWSGI escuchando puertos distintos y configuramos un bloque `upstream` en Nginx.
<div class="code-block">```
<code>
http {
upstream cluster_flask {
server 127.0.0.1:9000 weight=3;
server 127.0.0.1:9001 weight=3;
}
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass cluster_flask;
}
}
}
</code&>
Alternativa: Uso de Gunicorn
Como alternativa ligera a uWSGI, Gunicorn ofrece compatibilidad directa con servidores WSGI sin necesidad de archivos INI complejos si se prefieren argumentos de línea de comandos.
Instalación:
pip install gunicorn
Ejecución directa con demonio:
gunicorn -w 3 -b 127.0.0.1:8000 --daemon main_service:service_instance
Uso de archivo de configuración gunicorn_conf.py:
gunicorn -c gunicorn_conf.py main_service:service_instance