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. Objetivos
  2. 1. El viaje de una petición (en 6 saltos)
  3. 2. DNS: la agenda de Internet
  4. 3. TCP: fiabilidad antes que velocidad
  5. 4. Latencia: de qué se compone y cómo se mide
  6. 5. Balanceadores de carga: repartir el trabajo
  7. 6. Nginx como proxy inverso (tu caso concreto)
  8. 7. Diagnóstico: la pila de herramientas
  9. Autoevaluación (respóndeme en el chat)

Stack: Django + DRF · Proyecto: TicketFlow Estado: Publicada — impartición cuando entregues los ejercicios de la 00b y la 01 Prerrequisito: Lección 01 — HTTP a fondo


Objetivos

Al terminar esta lección podrás:

  1. Explicar el viaje completo de una petición: DNS → TCP → TLS → HTTP → respuesta.
  2. Razonar sobre latencia: qué la compone, cómo se mide y por qué el ancho de banda casi nunca es el problema.
  3. Decidir dónde va un balanceador de carga y qué tipo de algoritmo conviene a cada caso.
  4. Configurar Nginx como proxy inverso delante de Gunicorn, con TLS y cabeceras correctas.
  5. Diagnosticar problemas de red con dig, curl, ping, traceroute y ss.

1. El viaje de una petición (en 6 saltos)

Cuando el navegador pide https://ticketflow.app/api/events/, ocurre esto:

1. DNS        "¿Quién es ticketflow.app?"  → 203.0.113.42
2. TCP        3-way handshake (SYN, SYN-ACK, ACK)
3. TLS        handshake (1-RTT en TLS 1.3)
4. HTTP       petición → Nginx (proxy inverso) → Gunicorn → Django
5. Render     Django consulta PostgreSQL, Redis y monta el JSON
6. Vuelta     respuesta al revés, con keep-alive la conexión queda reutilizable

Cada salto añade latencia. Un senior no memoriza la lista: sabe cuánto cuesta cada salto y por eso coloca las cosas donde las coloca.

Clave: la Lección 01 estudió el salto 4 a fondo (HTTP). Esta lección estudia los saltos 1-3 y el "dónde" físico: quién recibe la conexión y cómo se reparte entre máquinas.

2. DNS: la agenda de Internet

DNS traduce nombres a direcciones. La cadena completa:

Cache del navegador → Cache del SO → Resolver del ISP (recursivo)
  → Root (.) → TLD (.app) → Autoritativo (ns.ticketflow.app) → A/AAAA

Tipos de registro que usarás de verdad:

RegistroQué respondeUso en TicketFlow
A / AAAAIPv4 / IPv6ticketflow.app → 203.0.113.42
CNAMEalias a otro nombrewww → ticketflow.app
ALIAS/ANAMEalias en el apexticketflow.app → balanceador
MXservidores de correolos correos de confirmación no reboten
TXTtexto arbitrarioverificación de dominio y SPF

Dos propiedades que importan en producción:

  • TTL: cuánto tiempo una respuesta vive en caché. Bajar el TTL (por ejemplo a 60 s) antes de una migración de IP te permite volver atrás rápido; con TTL de 86400 s estás atado un día entero a tu error.
  • Propagación: no es que "la red se actualice"; es que cada caché respeta su copia hasta que vence su TTL. Por eso los cambios de DNS son de "unos minutos a 48 horas".

Nota: DNS es UDP 53 normalmente (rápido, sin estado); TCP 53 para respuestas grandes o transferencias de zona. Si "el dominio resuelve en tu máquina pero no en producción", lo primero es preguntar a qué resolver le preguntaste.

3. TCP: fiabilidad antes que velocidad

HTTP vive sobre TCP (o QUIC sobre UDP en HTTP/3). Lo que TCP te da:

  • Handshake de 3 vías (SYN → SYN-ACK → ACK): una RTT antes de enviar un solo byte de aplicación.
  • Entrega fiable y ordenada: retransmite lo perdido, reordena lo desordenado.
  • Control de congestión (slow start): arranca lento y acelera mientras no pierde paquetes. Una conexión recién abierta va más despacio que una establecida: otra razón para el keep-alive.

Coste total de abrir una conexión nueva contra ticketflow.app desde Europa a un servidor en Virginia:

SaltoCoste típico
DNS (en caché / sin caché)~0 ms / 20-150 ms
TCP handshake1 RTT (~90 ms)
TLS 1.3 handshake1 RTT (~90 ms)
Primera respuesta HTTP1 RTT + tiempo del servidor

Latencia total de la primera petición: ~270 ms + procesamiento. Con keep-alive y TLS reutilizado, las siguientes peticiones se quedan en ~RTT + servidor. Esto es la Lección 01 (keep-alive) vista desde el cable.

Clave: el ancho de banda importa para respuestas grandes (ficheros, vídeos). Para APIs JSON pequeñas, casi todo es latencia y número de peticiones. Optimizar la compresión de un JSON de 2 KB rinde menos que quitar una petición de la cadena.

4. Latencia: de qué se compone y cómo se mide

Latencia de una petición = DNS + conexión + TLS + transmisión + procesamiento del servidor + vuelta. Herramientas:

bash
ping ticketflow.app            # RTT a la máquina (ICMP; ignorado a veces)
curl -w '...' -o /dev/null URL # desglose por fases (lo haremos en ejercicios)
traceroute ticketflow.app      # saltos de red hasta el destino

La descomposición de curl que usarás siempre:

text
time_namelookup:  DNS
time_connect:     TCP (acumulado)
time_appconnect:  TLS (acumulado)
time_starttransfer: primer byte (TTFB, acumulado)
time_total:       fin de la respuesta (acumulado)

Reglas de bolsillo:

  • Luz en fibra: ~1 ms por cada 100 km de ida y vuelta aproxima bien entre regiones. Madrid-Virginia ~90 ms no es "tu código lento": es física.
  • TTFB alto con DNS/TCP/TLS bajos = el servidor tarda: mira tu app (queries N+1, cola llena, GC).
  • DNS lento = caché o resolver: no lo arregles optimizando Python.

5. Balanceadores de carga: repartir el trabajo

Con un solo servidor tienes un único punto de fallo y techo de capacidad. El balanceador recibe el tráfico y lo reparte entre varias instancias idénticas (¡tu app debe ser sin estado! Lección 27).

Algoritmos que debes saber nombrar:

AlgoritmoCómo reparteCuándo usarlo
Round robinturno rotatorioinstancias iguales, casos generales
Least connectionsal que menos conexiones activas tengapeticiones de duración variable (tu caso: pagos largos)
IP hash / stickymisma IP siempre al mismo backendsesiones en memoria (a evitar: sesiones externas)
Weightedpor peso (máquina mayor pesa más)despliegues canary o hardware mixto

En el stack del curso: Nginx delante de 2+ workers de Gunicorn ya es un balanceador local; en producción, el balanceador lo pone la nube (ALB en AWS, Cloud Load Balancing en GCP) o Nginx/HAProxy en tu VM.

Dos decisiones de balanceador que la gente olvida:

  1. Terminación TLS: el certificado vive en el balanceador y descifra; hacia la app viaja plano en red privada (o mTLS si el compliance lo exige). Lo viste en la Lección 01, Ejercicio 8.
  2. Health checks: el balanceador pregunta GET /api/health/ a cada backend y saca del pool al que falla. Por eso el primer endpoint de la Lección 00 no era capricho.

6. Nginx como proxy inverso (tu caso concreto)

Arquitectura de TicketFlow en una VM:

Internet → Nginx (:80/:443) ─┬→ /api/  → Gunicorn (:8000) → Django
                             ├→ /admin/→ Gunicorn
                             └→ /static/ → ficheros servidos por Nginx

Configuración mínima (comentada en los ejercicios):

nginx
server {
    listen 443 ssl;
    server_name ticketflow.app;

    ssl_certificate     /etc/letsencrypt/live/ticketflow.app/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ticketflow.app/privkey.pem;

    # Estáticos: Nginx es rápido sirviendo ficheros; Django ni los ve.
    location /static/ {
        alias /srv/ticketflow/static/;
        expires 30d;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 60s;
    }
}

Por qué cada cabecera X-Forwarded-* existe: tu Django, detrás del proxy, vería como IP del cliente la del propio Nginx y como esquema http si no se lo dices. Con USE_X_FORWARDED_HOST y el middleware apropiado, Django reconstruye la verdad. Sin esto: paginación con URLs malas, CSRF gritando y logs de auditoría inútiles.

Nota fina: proxy_read_timeout por defecto (60 s) mata respuestas largas. Una exportación de informe que tarda 3 minutos morirá con 504 aunque Django siga trabajando. La respuesta correcta es devolver 202 y procesar en cola (Lección 06), no subir el timeout a 10 minutos.

7. Diagnóstico: la pila de herramientas

SíntomaHerramientaQué mirar
"No resuelve"dig +short dominioregistro, TTL, resolver usado
"No conecta"curl -ven qué fase se queda (DNS/TCP/TLS/HTTP)
"Va lento"curl -w por fasesqué fase acumula el tiempo
"502 Bad Gateway"Nginx error.logGunicorn caído o puerto equivocado
"504 Gateway Timeout"proxy_read_timeoutpetición más lenta que el timeout
"Conexiones colgadas"ss -tanestados CLOSE_WAIT/ESTAB anómalos

La regla del oficio: localiza la fase antes de tocar nada. Cambiar código Python porque DNS tarda 300 ms es cómo no se arregla nada.


Autoevaluación (respóndeme en el chat)

  1. ¿Por qué bajar el TTL de DNS es el primer paso antes de una migración de IP y no después?
  2. Una petición tarda 400 ms; DNS 5 ms, TCP 90 ms, TLS 90 ms, TTFB 210 ms. ¿Dónde está el problema y qué mirarías?
  3. ¿Por qué "least connections" es mejor que "round robin" para TicketFlow, donde el POST de pago es más lento que un GET?
  4. ¿Qué rompe en Django si Nginx no envía X-Forwarded-Proto https? Nombra dos síntomas.
  5. ¿Qué endpoint de tu API es el health check del balanceador y por qué debe ser barato?

Continúa con los ejercicios. Las soluciones solo tras intentarlo.