Módulo 1 · Fundamentos que sostienen todo

Lección 02 — Redes básicas

DNS, TCP, latencia, balanceadores de carga y Nginx delante de tu Django.

Publicada
En esta lección
  1. Ejercicio 1 — DNS con
  2. Ejercicio 2 — El desglose de fases con
  3. Ejercicio 3 — Simula el 502 y arregla el Nginx
  4. Ejercicio 4 — Balanceo entre dos workers
  5. Ejercicio 5 — Cabeceras de proxy y un 404 que muerde
  6. Ejercicio 6 — Health check de balanceador (diseño)
  7. Ejercicio 7 — Latencia de la reserva (discusión senior)
  8. Ejercicio 8 — Trazado de ruta (opcional, teórico)
  9. Entrega

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):

bash
cd ~/dev/ticketflow && source .venv/bin/activate
python manage.py runserver 8000   # terminal 1

Ejercicio 1 — DNS con dig (calentamiento)

  1. Ejecuta dig +short python.org y anota qué tipo de registro te devuelve.
  2. Ejecuta dig python.org y localiza en la sección ANSWER el TTL. Repite 10 segundos después: ¿baja el TTL? ¿Por qué?
  3. dig +trace python.org 2>/dev/null | tail -20: enumera la cadena (root → TLD → autoritativo) que has visto.
  4. Compara dig @1.1.1.1 python.org con dig @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:

text
            dns:  %{time_namelookup}s
            tcp:  %{time_connect}s
            tls:  %{time_appconnect}s
          ttfb:  %{time_starttransfer}s
         total:  %{time_total}s
     remote_ip:  %{remote_ip}
  1. 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é?
  2. Repite contra https://django.com y contra https://www.python.org. ¿Qué fase acumula más? ¿Coincide con la distancia física?
  3. 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:

  1. Instala Gunicorn: pip install gunicorn y arráncalo: gunicorn config.wsgi --bind 127.0.0.1:8000.
  2. En otro terminal: curl -i http://127.0.0.1:8000/api/health/. Funciona.
  3. 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.
  4. Nombra 2 cosas que mirarías en un Nginx real (error.log) ante ese 502.

Ejercicio 4 — Balanceo entre dos workers

  1. Levanta Gunicorn con dos workers y logs verbosos: gunicorn config.wsgi --bind 127.0.0.1:8000 --workers 2 --log-level debug.
  2. Lanza 6 peticiones seguidas: for i in $(seq 6); do curl -s -o /dev/null http://127.0.0.1:8000/api/health/; done.
  3. Observa los logs: ¿dos PIDs atienden las peticiones? ¿Qué algoritmo está usando Gunicorn por defecto? (pista: --worker-class sync reparte aceptando conexiones, algo distinto al round robin de un balanceador HTTP; explica la diferencia con tus palabras).
  4. ¿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:

python
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
  1. 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).
  2. Quita la línea. Ahora: ¿qué IP del cliente vería Django si llega vía Nginx sin X-Forwarded-For configurado? ¿Y qué esquema (request.scheme)?
  3. Escribe en 2 líneas qué configuración de proxy_set_header hace falta para que Django vea IP real y https.

Ejercicio 6 — Health check de balanceador (diseño)

Diseña (en papel, 5 líneas) el endpoint /api/health/ versión balanceador:

  1. ¿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?
  2. ¿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).
  3. ¿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).

  1. 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).
  2. 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)

  1. traceroute -n ticketflow.app (o tracepath): ¿cuántos saltos hasta el destino? ¿Qué significan los * en algunos saltos?
  2. ¿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).