Hazlos en orden con tu TicketFlow local. Entrega en el chat los outputs recortados y tus respuestas. No mires solutions.md hasta entregar.
Preparación (3 min):
cd ~/dev/ticketflow && source .venv/bin/activate
python manage.py runserver 8000 # terminal 1Ejercicio 1 — DNS con dig (calentamiento)
- Ejecuta
dig +short python.orgy anota qué tipo de registro te devuelve. - Ejecuta
dig python.orgy localiza en la sección ANSWER el TTL. Repite 10 segundos después: ¿baja el TTL? ¿Por qué? dig +trace python.org 2>/dev/null | tail -20: enumera la cadena (root → TLD → autoritativo) que has visto.- Compara
dig @1.1.1.1 python.orgcondig @9.9.9.9 python.org: ¿coinciden las respuestas? ¿Qué implica para una migración de IP?
Ejercicio 2 — El desglose de fases con curl -w
Crea el fichero curl-format.txt:
dns: %{time_namelookup}s
tcp: %{time_connect}s
tls: %{time_appconnect}s
ttfb: %{time_starttransfer}s
total: %{time_total}s
remote_ip: %{remote_ip}- Mídelo contra tu API local:
curl -w @curl-format.txt -o /dev/null -s http://127.0.0.1:8000/api/health/. ¿Cuánto valen DNS y TCP contra localhost? ¿Por qué? - Repite contra
https://django.comy contrahttps://www.python.org. ¿Qué fase acumula más? ¿Coincide con la distancia física? - Repite 3 veces la misma URL externa sin pausa. ¿Bajan DNS/TCP/TLS en la 2ª y 3ª? Explica qué caché actúa en cada fase.
Entrega: las tres tablas recortadas y tu explicación de la pregunta 3.
Ejercicio 3 — Simula el 502 y arregla el Nginx
Sin instalar Nginx aún (lo haremos en el Módulo 9), demuestra el concepto con Gunicorn:
- Instala Gunicorn:
pip install gunicorny arráncalo:gunicorn config.wsgi --bind 127.0.0.1:8000. - En otro terminal:
curl -i http://127.0.0.1:8000/api/health/. Funciona. - Mata Gunicorn (Ctrl+C) y repite el curl. ¿Qué error exacto recibes del lado del cliente? Ese es, conceptualmente, el 502 Bad Gateway: el proxy no puede hablar con la app.
- Nombra 2 cosas que mirarías en un Nginx real (
error.log) ante ese 502.
Ejercicio 4 — Balanceo entre dos workers
- Levanta Gunicorn con dos workers y logs verbosos:
gunicorn config.wsgi --bind 127.0.0.1:8000 --workers 2 --log-level debug. - Lanza 6 peticiones seguidas:
for i in $(seq 6); do curl -s -o /dev/null http://127.0.0.1:8000/api/health/; done. - Observa los logs: ¿dos PIDs atienden las peticiones? ¿Qué algoritmo está usando Gunicorn por defecto? (pista:
--worker-class syncreparte aceptando conexiones, algo distinto al round robin de un balanceador HTTP; explica la diferencia con tus palabras). - ¿Qué pasa si un worker se bloquea 10 segundos en una petición lenta y llegan 3 más al mismo worker? (razona con "least connections" vs "accept-based").
Ejercicio 5 — Cabeceras de proxy y un 404 que muerde
En config/settings.py añade temporalmente:
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")curl -i http://127.0.0.1:8000/api/health/: ¿qué respuesta da y por qué? (esta cabecera hace creer a Django que el proxy ya terminó TLS).- Quita la línea. Ahora: ¿qué IP del cliente vería Django si llega vía Nginx sin
X-Forwarded-Forconfigurado? ¿Y qué esquema (request.scheme)? - Escribe en 2 líneas qué configuración de
proxy_set_headerhace falta para que Django vea IP real yhttps.
Ejercicio 6 — Health check de balanceador (diseño)
Diseña (en papel, 5 líneas) el endpoint /api/health/ versión balanceador:
- ¿Qué debe comprobar: solo "proceso vivo", o también base de datos y Redis? ¿Qué coste tiene comprobar la BD en cada check cada 5 segundos?
- ¿Qué código devuelves si la BD va lenta pero responde: 200 o 503? Justifica con el efecto sobre el balanceador (sacar del pool vs mantener).
- ¿Qué debe devolver: el nombre de la versión, la hora de arranque, el PID? ¿Por qué esas pistas ayudan a depurar?
Ejercicio 7 — Latencia de la reserva (discusión senior)
El POST /api/events/42/reserve de TicketFlow hace hoy: validar JSON, 2 SELECT, 1 INSERT de reserva, 1 INSERT de ítem, 1 COMMIT (todo local).
- Estima la latencia añadida si la BD pasa de localhost a una región distinta (~90 ms de RTT) sabiendo que son 5 idas y venidas a la BD. ¿Cómo lo resuelve una transacción única? (guárdalo: es la Lección 10).
- El listado de eventos se cachea 60 s en un CDN. Un comprador ve "disponible" un asiento que acaba de reservarse otro usuario. ¿Qué es eso a nivel de red y qué decisión de negocio propones?
Ejercicio 8 — Trazado de ruta (opcional, teórico)
traceroute -n ticketflow.app(otracepath): ¿cuántos saltos hasta el destino? ¿Qué significan los*en algunos saltos?- ¿Por qué el primer salto suele ser tu router y el último puede no responder ICMP?
Entrega
Pega en el chat outputs recortados y respuestas. Con esto cierro la 02 y la marco impartida; después: Lección 03 — Concurrencia y asincronía (la que hace posible que dos compradores no se lleven el mismo asiento sin que la BD diga nada).