SenseiTeoría desde cero0/27

4 · La red y la webLección 1 de 6

Cómo viaja un mensaje: IP, puertos y DNS

How a message travels: IP, ports and DNS

Qué pasa entre el «publicar» de Ana y el gateway de C01: la foto partida en paquetes, la dirección de cada máquina, el puerto de cada programa, la conexión que no pierde nada, el tiempo que cobra la luz y el directorio que convierte nombres en direcciones.

⏱ 60 min lo esencial · 76 min todo15 conceptos nuevos2 calculadoras10 ejerciciosAPI y Orquestación
Secciones14
  1. 01Protocolos y paquetes: la foto viaja en pedazos
  2. 02Direcciones IP: a qué máquina va
  3. 03Puertos y sockets: a qué programa va
  4. 04TCP y UDP: con conexión o sin ella
  5. 05RTT: lo que tarda la ida y vuelta
  6. 06DNS: del nombre a la dirección
  7. 07Las capas y el viaje completo de la foto
  8. 08Dentro de TCP: pérdidas, arranque lento y conexiones caras extra
  9. 09Errores comunes
  10. 10En la vida real extra
  11. 11Ejercicios
  12. 12Lo que sigue
  13. 13Palabras que vas a oír
  14. 14Chequeo
La pregunta

Cuando Ana toca «publicar», ¿cómo llega su foto del celular al gateway de C01, y cómo sabe la red a qué máquina y a qué programa ir?

Ana está en la Ciudad de México y toca «publicar». La foto de sus tenis pesa ≈ 3 MB en su celular; la app la achica a ≈ 200 KB, la manda y, poco después, le sugiere «Tenis». En medio, la foto cruzó unos 3,000 km hasta el norte de Virginia, en Estados Unidos, donde viven las máquinas del marketplace y las de C01.

En «El camino completo» seguiste ese viaje desde arriba: la request entra, el modelo responde. Aquí vas a abrir la parte que se dio por hecha: la red. Tres preguntas guían la lección:

  • ¿A qué máquina va? Hay miles de millones de aparatos conectados. ¿Cómo encuentra la foto el correcto?
  • ¿A qué programa? En una máquina corren muchos procesos. ¿Cómo llega la foto al gateway y no a otro?
  • ¿Cómo no se pierde nada? La red pierde y desordena pedazos. ¿Cómo llega la foto completa y en orden?

Al final vas a poder seguir la foto salto por salto, con los números que la Ronda usa en M02, M06 y M13, y vas a entender por qué un servidor que «corre bien» en un contenedor a veces no contesta.

01

Protocolos y paquetes: la foto viaja en pedazos

Esencial

Protocols and packets: the photo travels in pieces

Un protocolo es un acuerdo

Para que dos computadoras se entiendan, las dos tienen que seguir las mismas reglas: qué se manda primero, cómo se escribe cada dato, qué se contesta y qué se hace si algo falla. Ese acuerdo se llama protocolo (protocol).

Es como una llamada por teléfono. Quien contesta dice «¿bueno?», quien llamó dice quién es, hablan por turnos y se despiden antes de colgar. Nadie lo escribió en un contrato, pero si alguien no lo sigue, la llamada se vuelve confusa. La analogía se rompe en un punto: las personas improvisan y aun así se entienden. En la red el acuerdo está escrito, en documentos públicos que se llaman RFC (Request for Comments), y cada programa lo sigue al pie de la letra: un byte fuera de lugar y el otro lado ya no entiende.

En esta lección vas a conocer cuatro protocolos: IP, que lleva cada pedazo a la máquina correcta; TCP y UDP, que lo llevan al programa correcto; y el DNS, que traduce nombres en direcciones. Arriba de ellos va HTTP, el protocolo de las páginas web y de las APIs, que es el tema de la siguiente lección.

Un paquete: encabezado y carga

La red no manda la foto de una sola pieza. La parte en pedazos, y cada pedazo viaja por su cuenta dentro de un paquete (packet). Un paquete tiene dos partes:

  • El encabezado (header): unos bytes al principio con los datos del viaje. De dónde viene, a dónde va, qué número de pedazo es.
  • La carga (payload): el pedazo de foto.

¿Por qué en pedazos? Por tres razones. Una foto de 3 MB ocuparía el cable un buen rato y nadie más podría usarlo; en pedazos, los paquetes de muchas personas se turnan. Si se daña un pedazo, se reenvía solo ese, no la foto completa. Y cada pedazo puede tomar el camino que esté libre.

¿De qué tamaño? En casi todas las redes, un paquete lleva como máximo 1,500 bytes. Ese tope se llama MTU (maximum transmission unit). Del total, 40 bytes son encabezados (20 del protocolo IP y 20 del protocolo TCP, que vas a conocer en las siguientes secciones), así que de foto caben 1,460 bytes por paquete.

Haz la cuenta con el original de la foto de Ana, los 3 MB que guarda su celular. Así llegan las fotos que los vendedores suben desde la computadora, sin achicar:

La foto original de Ana, en paquetesLa cuenta
Foto original del celular
—
3,000,000 bytes
Foto por paquete1,500 de tope menos 40 de encabezados
1,500 − 40
1,460 bytes
Paquetes
3,000,000 ÷ 1,460 = 2,054.8 → hacia arriba
2,055
El último paquetelo que sobra después de 2,054 llenos
3,000,000 − 2,054 × 1,460
1,160 bytes
Encabezados en total
2,055 × 40
82,200 bytes
Resultado
Una sola foto original son 2,055 paquetes, y ≈ 2.7 % de lo que viaja son encabezados. El JPEG de ≈ 200 KB que de verdad manda la app de Ana, ya achicado, son 137.
El original de la foto de Ana, de 3,000,000 de bytes, se parte en 2,055 pedazos de hasta 1,460 bytes. Cada pedazo viaja en un paquete con dos partes: un encabezado, que dice su número y de dónde viene y a dónde va, del celular al servidor, y la carga, que es el pedazo de la foto. El paquete 1 y el 2 llevan 1,460 bytes cada uno; el último, el 2,055, lleva los 1,160 bytes que sobran. Abajo, el camino: del celular a un router, a otro router y al servidor. Cada router lee solo el encabezado y pasa el paquete al siguiente. UNA FOTO, MILES DE PAQUETES la foto original: 3,000,000 bytes se parte en 2,055 pedazos de hasta 1,460 bytes encabezado · n.º 1 celular → servidor carga: 1,460 bytes de la foto encabezado · n.º 2 celular → servidor carga: 1,460 bytes los que siguen ⋮ ⋮ encabezado · n.º 2,055 celular → servidor carga: 1,160 bytes lo que sobra EL CAMINO celular router router servidor Cada router lee solo el encabezado y lo reenvía.
La foto original partida en paquetes. Cada uno lleva su encabezado, con su número y su destino, y un pedazo de foto. En el camino, cada router lee solo el encabezado.

Los routers: reenviar sin abrir

Entre el celular de Ana y Virginia hay una o dos decenas de aparatos que se pasan los paquetes de mano en mano. Cada uno es un router (enrutador): una computadora especializada que recibe un paquete, lee a dónde va y lo manda al siguiente aparato que lo acerca a su destino. A cada paso de un router al siguiente se le dice salto (hop).

El router no abre la carga ni le importa que sea una foto. Lee el destino en el encabezado, lo busca en su tabla y lo reenvía, en millonésimas de segundo. Por eso internet aguanta tanto tráfico: nadie en el camino entiende el mensaje completo; solo los dos extremos.

Esto tiene una consecuencia que vas a ver toda la lección. Como cada paquete viaja solo, pueden llegar en otro orden, llegar repetidos o no llegar: un router saturado tira los que no le caben. Alguien tiene que juntarlos, ordenarlos y pedir los que faltan. Eso lo hace TCP, más abajo.

02

Direcciones IP: a qué máquina va

Esencial

IP addresses: which machine it goes to

Una dirección de 32 bits

Para que el router sepa a dónde mandar un paquete, cada aparato conectado tiene un número que lo identifica en la red: su dirección IP (IP address). IP es el Internet Protocol, el protocolo que lleva cada paquete de máquina en máquina.

En la versión 4 del protocolo, IPv4, la dirección es un número de 32 bits: 4 bytes. Para que las personas la lean, se escribe cada byte en decimal, del 0 al 255, separado por puntos: 192.168.1.20. Son los mismos 4 bytes de la lección «Cómo guarda números una computadora», escritos de otra manera.

Con 32 bits hay 2³² = 4,294,967,296 direcciones: unos 4.3 mil millones. Parecían muchísimas en 1981, cuando se diseñó IPv4. Hoy hay más personas que eso en el mundo, y cada una trae celular, computadora y tele. Las direcciones libres se acabaron: el organismo que las reparte entregó sus últimos bloques en 2011.

La salida de fondo es IPv6, con direcciones de 128 bits: 2¹²⁸ ≈ 3.4 × 10³⁸, suficientes para no acabarse nunca. Las dos versiones conviven, y en esta lección usamos IPv4, que es la que vas a ver en casi todos los ejemplos.

Para ir más hondoCómo se ve una dirección IPv6

Las direcciones IPv6 se escriben en hexadecimal (con los símbolos del 0 al 9 y de la a a la f, como viste en «El sistema operativo»), en 8 grupos de 4 símbolos, y los ceros se pueden abreviar: 2001:db8::1. Casi todo internet habla IPv4, y cada vez más también IPv6. En 2026, según las mediciones de Google, cerca de la mitad de sus usuarios ya llega por IPv6.

Una dirección también dice en qué red está

Una dirección IP tiene dos partes, como un número de teléfono con su lada: los primeros bits dicen en qué red está la máquina y los últimos, qué máquina es dentro de esa red. Una red se escribe con su primera dirección y, después de una diagonal, cuántos bits quedan fijos: 10.0.0.0/8 son todas las direcciones que empiezan con el byte 10. Quedan 24 bits libres: 2²⁴ = 16,777,216 direcciones. 192.168.1.0/24 deja fijos 3 bytes y libre el último: 256 direcciones. A diferencia de la lada, el corte entre red y máquina no se adivina viendo el número: lo dice la diagonal.

A los routers les sirve muchísimo: no guardan una fila por cada máquina del mundo, sino una por red. «Todo lo que empiece con 10.0 va por la puerta 2».

IP privada y pública

No todas las direcciones salen a internet. Tres rangos están apartados para redes internas, y cualquiera puede usarlos adentro sin pedirle permiso a nadie:

RangoVa deDirecciones
10.0.0.0/810.0.0.0 a 10.255.255.25516,777,216
172.16.0.0/12172.16.0.0 a 172.31.255.2551,048,576
192.168.0.0/16192.168.0.0 a 192.168.255.25565,536

Una dirección de esos rangos es una IP privada: vale solo dentro de su red, y la misma 192.168.1.20 existe en millones de casas a la vez. Todas las demás son IP públicas: únicas en el mundo y alcanzables desde internet.

Tu casa es el ejemplo. Tu router le da a cada aparato una IP privada, 192.168.1.x, y él tiene una sola IP pública que le dio tu proveedor. Cuando tu celular sale a internet, el router cambia en cada paquete la dirección privada por la pública y anota el cambio, para saber a quién devolver la respuesta. Esa traducción se llama NAT (network address translation). Así, una IP pública alcanza para toda la casa. Las compañías de celulares hacen lo mismo en grande: en IPv4, el celular de Ana casi seguro tiene una IP privada, y miles de celulares salen por la misma pública.

En la nube pasa igual. Las máquinas de C01 viven en una red privada de AWS (Amazon Web Services, la nube de Amazon) con direcciones como 10.0.3.15, y desde internet no se pueden alcanzar: solo la puerta de entrada tiene IP pública. Esa red privada en la nube se llama VPC, y la vas a armar en la fase 8. En Kubernetes, además, cada pod (cada copia de un programa) recibe su propia IP privada al nacer y la pierde al morir: la siguiente copia tendrá otra.

Para ir más hondoLas direcciones, en Python

El módulo ipaddress de la biblioteca estándar lee direcciones, las muestra en binario y dice de qué tipo son:

python
import ipaddress

for texto in ("192.168.1.20", "10.0.3.15", "172.20.0.7", "8.8.8.8", "127.0.0.1"):
    ip = ipaddress.ip_address(texto)
    bits = ".".join(f"{b:08b}" for b in ip.packed)        # los 4 bytes, en binario
    tipo = "loopback" if ip.is_loopback else "privada" if ip.is_private else "pública"
    print(f"{texto:>12} → {bits}  {tipo}")

print("direcciones IPv4:", f"{2**32:,}")
print("direcciones IPv6:", f"{2**128:.2e}")
red = ipaddress.ip_network("10.0.0.0/8")
print("en 10.0.0.0/8 caben", f"{red.num_addresses:,}")
print("¿10.0.3.15 está en 10.0.0.0/8?", ipaddress.ip_address("10.0.3.15") in red)
Salida
192.168.1.20 → 11000000.10101000.00000001.00010100  privada
   10.0.3.15 → 00001010.00000000.00000011.00001111  privada
  172.20.0.7 → 10101100.00010100.00000000.00000111  privada
     8.8.8.8 → 00001000.00001000.00001000.00001000  pública
   127.0.0.1 → 01111111.00000000.00000000.00000001  loopback
direcciones IPv4: 4,294,967,296
direcciones IPv6: 3.40e+38
en 10.0.0.0/8 caben 16,777,216
¿10.0.3.15 está en 10.0.0.0/8? True

El 8.8.8.8 es un servidor público de DNS de Google, que verás más adelante. El 127.0.0.1 es especial: no es ni de tu casa ni de internet, es la máquina misma. (El is_private de Python cuenta como privados otros rangos reservados además de los tres de la tabla; por eso el código pregunta primero por loopback.)

03

Puertos y sockets: a qué programa va

Esencial

Ports and sockets: which program it goes to

El puerto: un número para cada programa

La IP lleva el paquete a la máquina. Pero en la máquina de un pod del gateway corren varios procesos, y en la de Triton, el servidor que corre el modelo, también. ¿Cuál recibe el paquete?

Lo dice el puerto (port): un número de 16 bits, del 0 al 65,535, que va en el encabezado junto a la IP. Cada programa que quiere recibir conexiones se apunta en un puerto, y el kernel le entrega lo que llegue a ese número. Si la IP es la dirección de un edificio, el puerto es el número del departamento.

Algunos puertos son famosos, porque cada protocolo tiene uno acordado:

PuertoQuién lo usa
22SSH, para entrar a otra máquina a escribir comandos
53DNS
80HTTP, la web sin cifrar
443HTTPS, la web cifrada: casi todo internet
8000uvicorn, si no le dices otro; y el HTTP de Triton
8001 · 8002Triton: gRPC (otra manera de pedirle predicciones, que verás en la lección de APIs) y métricas
8080El gateway de C01

Los puertos del 0 al 1023 están reservados para los protocolos más conocidos, y en Linux solo root puede apuntarse en ellos, como viste en «El sistema operativo». (Docker y containerd 2.0, dos de los programas que arrancan contenedores, quitan esa regla dentro de ellos, pero la costumbre se quedó.) Por eso los programas propios, como el gateway con su 8080, usan puertos altos. Triton escucha en tres a la vez (el 8002 es para que Prometheus, el programa que junta las métricas de todos, las lea), así que un programa puede tener varios puertos; lo que no puede pasar, salvo con opciones especiales que aquí no hacen falta, es que dos programas de la misma máquina se apunten en el mismo puerto de la misma IP.

El socket: la puerta que abre un proceso

Para hablar por la red, un proceso le pide al kernel un socket: un objeto del sistema operativo por donde entran y salen los bytes, igual que un archivo abierto. Se pide con syscalls, las peticiones de un programa al kernel: socket para crearlo, bind para apuntarlo en una IP y un puerto, listen para esperar conexiones, accept para aceptar una y connect para conectarse a otro.

Con esas syscalls se ven los dos papeles de cualquier conversación por la red:

  • El servidor llega primero y espera: hace bind en su puerto, listen y se queda en accept.
  • El cliente (client) es quien abre la conexión: hace connect a la IP y al puerto del servidor.

Ser cliente o servidor no es un tipo de máquina: es un papel en una conexión. El gateway de C01 es servidor cuando le llega la foto y cliente cuando le habla a Triton.

El cliente también necesita un puerto, para que la respuesta tenga a dónde volver. No lo elige: el kernel le presta uno libre de un rango alto, un puerto efímero (ephemeral port), que dura lo que dure la conexión. En Linux, por omisión, sale del 32,768 al 60,999. (El organismo que reparte los números, la IANA, recomienda otro rango, del 49,152 al 65,535, y Windows usa ese.)

Así, una conexión queda identificada por cuatro números: IP y puerto del cliente, IP y puerto del servidor. Por eso un solo puerto 8080 atiende miles de conexiones a la vez: todas llegan al mismo puerto del servidor, pero cada una viene de una IP o de un puerto de cliente distinto.

Para ir más hondoUn servidor y un cliente en Python

Así se ve con el módulo socket, con un servidor y un cliente en la misma máquina. El cliente se conecta, manda unos bytes y recibe la respuesta:

python
import socket, threading

servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   # IPv4 y TCP
servidor.bind(("127.0.0.1", 0))      # 0: que el sistema elija un puerto libre
servidor.listen()                    # ya es un servidor: espera conexiones
ip, puerto = servidor.getsockname()

def atender():
    conexion, (ip_cliente, puerto_cliente) = servidor.accept()
    with conexion:
        pedido = conexion.recv(1024)                  # lee lo que llegó
        print("servidor: recibí", pedido, "desde", ip_cliente)
        print("servidor: el cliente usa otro puerto:", puerto_cliente != puerto)
        conexion.sendall(b"categoria=tenis")

hilo = threading.Thread(target=atender)
hilo.start()

with socket.create_connection((ip, puerto)) as cliente:   # el handshake pasa aquí
    cliente.sendall(b"foto de Ana")
    print("cliente: me respondieron", cliente.recv(1024))
hilo.join()
servidor.close()
Salida
servidor: recibí b'foto de Ana' desde 127.0.0.1
servidor: el cliente usa otro puerto: True
cliente: me respondieron b'categoria=tenis'

El servidor corre en un hilo aparte para que el mismo programa pueda hacer de los dos lados. No imprimimos los puertos porque el kernel elige otros en cada corrida; lo que siempre se cumple es que el del cliente es distinto del del servidor. Así trabajan uvicorn y Triton por dentro, con muchas conexiones a la vez.

localhost y 0.0.0.0: dónde escucha un servidor

Cada máquina tiene una dirección para hablar consigo misma: 127.0.0.1, que se llama localhost. Lo que se manda ahí no sale de la máquina: el kernel lo devuelve por dentro, por una puerta de red de mentiras que se llama loopback. En IPv6 es ::1.

Una máquina tiene varias puertas de red, que se llaman interfaces: la de loopback, la del Wi-Fi o el cable, a veces más. Cada una tiene su IP. Por eso, al hacer bind, el servidor dice en cuál escucha:

  • 127.0.0.1: solo en loopback. Solo le pueden hablar los programas de la misma máquina.
  • 0.0.0.0: en todas las interfaces de la máquina. Le puede hablar quien llegue por cualquiera.

uvicorn, si no le dices otra cosa, escucha en 127.0.0.1:8000. En tu laptop está bien, y es a propósito: si escuchara en todas, cualquiera en la red del café podría hablarle a tu programa a medio hacer.

Dentro de un contenedor es una trampa. En «El sistema operativo» viste que un contenedor tiene su propio namespace de red: sus propias interfaces y su propio localhost. El 127.0.0.1 de adentro no es el de la máquina. Cuando Docker o Kubernetes mandan una request al contenedor, llega por su interfaz de red (en un pod, la de su IP privada, como 10.0.3.15), no por loopback. Si uvicorn escucha en 127.0.0.1, nadie escucha en esa interfaz, y la conexión se rechaza.

Un contenedor tiene dos puertas de red: la de la red, con la dirección 10.0.3.15, por donde llega lo de afuera, y la de loopback, 127.0.0.1, que solo se alcanza desde adentro. Arriba, uvicorn escucha en 127.0.0.1, puerto 8080: queda conectado solo a la puerta de adentro, y la request que llega de afuera por 10.0.3.15 no encuentra a nadie escuchando y se rechaza. Abajo, uvicorn escucha en 0.0.0.0, puerto 8080, que quiere decir todas las puertas: queda conectado a las dos y la request de afuera llega. ESCUCHA EN 127.0.0.1:8080 CONTENEDOR request de afuera 10.0.3.15 127.0.0.1 uvicorn :8080 Nadie escucha en 10.0.3.15: se rechaza. ESCUCHA EN 0.0.0.0:8080 · TODAS CONTENEDOR request de afuera 10.0.3.15 127.0.0.1 uvicorn :8080 Escucha en las dos: la request llega.
Las dos puertas de un contenedor. Escuchando en 127.0.0.1, uvicorn solo atiende la de adentro y la request de afuera se rechaza. Escuchando en 0.0.0.0, atiende las dos.

Es el error clásico de «el contenedor corre, los logs dicen que todo está bien y no contesta». Por eso el gateway de C01 arranca con uvicorn ... --host 0.0.0.0 --port 8080. Lo vas a vivir en la estación 7 del Dojo.

Para ir más hondoCuando localhost sí sirve entre contenedores

Un pod de Kubernetes puede tener varios contenedores, y esos sí comparten el mismo namespace de red: entre ellos, localhost funciona. La Ronda lo menciona como una opción para C01: si el gateway y Triton vivieran en el mismo pod, se hablarían por localhost, sin red de por medio.

04

TCP y UDP: con conexión o sin ella

Esencial

TCP and UDP: with or without a connection

La IP lleva paquetes sueltos a una máquina, sin prometer nada: pueden perderse, llegar repetidos o desordenados. Sobre ella van dos protocolos que se encargan de llevarlos al programa, y que resuelven el problema de manera opuesta.

TCP: una conexión confiable

TCP (Transmission Control Protocol) convierte esos paquetes sueltos en una conexión: una tubería entre dos programas por la que los bytes llegan completos, sin repetirse y en el orden en que salieron. Para lograrlo usa tres ideas:

  1. 1

    Numerar

    Cada paquete lleva el número de su primer byte dentro de la conversación: el número de secuencia. Del otro lado, TCP los acomoda por número, aunque lleguen desordenados, y tira los repetidos.

  2. 2

    Acusar recibo

    El que recibe contesta con un acuse (acknowledgment, ACK): «ya tengo todo hasta el byte 43,800». Un solo acuse confirma muchos paquetes.

  3. 3

    Reenviar

    Si un acuse no llega a tiempo, el que manda supone que el paquete se perdió y lo reenvía. El programa nunca se entera: solo ve los bytes llegar en orden, a veces un poco tarde.

TCP también cuida no ahogar a nadie: si el que recibe va lento, le pide que espere, y si la red empieza a perder paquetes, manda menos. Esa parte está en la sección extra «Dentro de TCP».

El handshake: tres pasos antes del primer byte

Antes de mandar datos, los dos lados tienen que ponerse de acuerdo: que los dos existen, que los dos escuchan y desde qué número empieza cada uno a contar. Eso se hace con un saludo de tres pasos, el handshake (three-way handshake):

  1. 1

    SYN

    El cliente manda un paquete sin datos con la marca SYN (de synchronize) y su número inicial: «¿hablamos? Yo empiezo a contar en tal número».

  2. 2

    SYN-ACK

    El servidor contesta con SYN y ACK a la vez: «recibí tu número; yo empiezo en este otro».

  3. 3

    ACK

    El cliente acusa recibo. La conexión está abierta, y en ese mismo momento el cliente ya puede mandar su request.

Una conexión TCP nueva entre un cliente y un servidor a 30 milisegundos de distancia, con un RTT de 60 milisegundos. El tiempo corre hacia abajo. A los 0 milisegundos, el cliente manda SYN. A los 30 llega al servidor, que contesta SYN-ACK. A los 60 llega al cliente, que manda el ACK y, en seguida, la request. A los 90 la request llega al servidor, que contesta. A los 120 la respuesta llega al cliente. El primer RTT, de 0 a 60, es el handshake, y en él no viaja ningún dato; el segundo, de 60 a 120, es la request y su respuesta. UNA CONEXIÓN NUEVA · RTT DE 60 MS cliente servidor 0 ms 30 60 90 120 SYN SYN-ACK ACK + request respuesta 1 RTT sin datos 1 RTT la request Conexión nueva: 2 RTT = 120 ms. Conexión ya abierta: 1 RTT = 60 ms. Con TLS encima, un RTT más (otra lección).
Una conexión nueva, contada en el tiempo, con una ida y vuelta (un RTT) de 60 ms, un valor de ejemplo. Mira la columna de la izquierda: el primer RTT se va en el handshake, sin datos; la request sale en el segundo.

Fíjate en el costo. Del SYN a recibir el SYN-ACK pasa una ida y vuelta completa, y en ella no viaja ni un byte de la foto. Esa ida y vuelta tiene nombre, RTT, y es el tema de la siguiente sección. Una conexión nueva cuesta 1 RTT antes del primer byte. Por eso los programas serios abren una conexión y la reusan para muchas requests.

Para ir más hondoCerrar una conexión, y el «connection refused»

Para cerrar, cada lado manda un paquete con la marca FIN («ya no voy a mandar más») y el otro lo acusa. Si un programa se muere sin cerrar, el kernel cierra sus conexiones por él: con FIN, o con un RST (reset) si le quedaban datos sin leer. Un RST quiere decir «esta conexión no existe»: es lo que contesta una máquina a un paquete de una conexión que no conoce (por ejemplo, después de reiniciarse) y también lo que recibes cuando nadie escucha en un puerto: el «connection refused» de la figura del contenedor.

UDP: mandar y olvidar

UDP (User Datagram Protocol) hace lo mínimo. Agrega a cada paquete el puerto de origen y el de destino, en un encabezado de 8 bytes, y lo manda. No hay handshake, no hay acuses, no hay reenvíos ni orden. Si un paquete se pierde, se perdió.

¿Para qué querría alguien algo así? Para cuando llegar tarde es peor que no llegar:

  • Voz y videollamadas. Si se pierde un pedazo de voz, reenviarlo no sirve: cuando llegue, la conversación ya va más adelante. Es mejor un microcorte que una pausa. Por eso las llamadas por internet usan UDP siempre que pueden.
  • Juegos en línea. La posición de un jugador de hace 200 ms ya no importa; importa la de ahora.
  • El DNS. Una pregunta y su respuesta caben en un paquete cada una. Hacer un handshake para eso costaría más que la pregunta. Si no llega respuesta, se vuelve a preguntar.
  • QUIC. Un protocolo nuevo que va encima de UDP y hace él mismo lo que hacía TCP: numera, acusa y reenvía, pero a su manera. Es la base de HTTP/3. Por qué alguien reconstruiría TCP sobre UDP lo ves en la sección extra.
TCPUDP
ConexiónSí: handshake de 1 RTTNo
Llega todoSí: reenvía lo perdidoNo: lo perdido se pierde
En ordenSíNo
Encabezado20 bytes o más8 bytes
Lo usanHTTP/1.1 y HTTP/2, la foto de Ana, el tensor de C01, las bases de datosVoz, video en vivo, juegos, DNS, QUIC (y con él, HTTP/3)

Todo lo que viaja en C01, de la foto al tensor y a la respuesta, va por TCP: una categoría equivocada por un pedazo perdido sería mucho peor que unos milisegundos de espera.

05

RTT: lo que tarda la ida y vuelta

Esencial

RTT: the round trip time

Ida y vuelta

El RTT (round-trip time, tiempo de ida y vuelta) es lo que tarda un paquete en llegar del cliente al servidor más lo que tarda la respuesta en volver. Es la unidad con la que se mide cuánto le cuesta la red a cualquier conversación: el handshake es 1 RTT, una request con su respuesta es otro.

Si juegas en línea, ya lo conoces: el «ping» que muestra el juego, «32 ms», es el RTT entre tu consola y el servidor del juego. El nombre viene de ping, un programa que manda un paquete chiquito y mide cuánto tarda en volver.

El límite de la luz

El RTT tiene un piso que ninguna tecnología puede bajar: la velocidad de la luz. En el vacío, la luz recorre ≈ 300,000 km por segundo; dentro de la fibra óptica, el vidrio la frena a ≈ 200,000 km por segundo: 200 km por milisegundo. En la lección de unidades viste la regla que usa la Ronda, ≥ 1 ms de ida y vuelta por cada 100 km. Sale de aquí: 100 km de ida y 100 de vuelta son 200 km, un milisegundo.

El piso físico entre Ana y VirginiaLa cuenta
Distancia en línea rectade la Ciudad de México a Ashburn, en el norte de Virginia
—
≈ 3,012 km
Solo la idaa 200 km por milisegundo
3,012 ÷ 200
≈ 15 ms
Ida y vuelta: el RTT mínimo
2 × 15
≈ 30 ms
Una ruta realla fibra no va en línea recta y cada router suma un poco; suele salir del orden de 1.5 veces
30 × 1.5
≈ 45 ms
Resultado
Ninguna request de Ana a Virginia puede contestarse en menos de ≈ 30 ms, aunque el servidor responda al instante. Y por 4G, el tramo de radio del celular suma todavía más.

Más ancho de banda no baja el RTT. El ancho de banda dice cuántos bits caben por segundo en el tubo; el RTT dice cuánto tarda un bit en ir y volver. Una carretera de diez carriles deja pasar más coches, pero no hace más corto el viaje de cada uno. Para bajar el RTT solo hay dos caminos: acercarse o hacer menos idas y vueltas.

La tabla usa dos palabras de la nube. Una región es un lugar del mundo donde un proveedor de nube tiene sus centros de datos: la de AWS en el norte de Virginia se llama us-east-1, y ahí vive C01. Una zona es uno o varios centros de datos dentro de una región, separados de los demás para que no fallen juntos; C01 usa dos. Las dos tienen su propia lección más adelante.

EntreRTT típico
Dos programas de la misma máquina, por localhostDecenas de microsegundos
Dos máquinas en la misma zona de la nubeMenos de 1 ms
Dos zonas de la misma región de la nube≈ 1 a 2 ms
Centro de México y Virginia, por cable≈ 50 ms (el mínimo físico es 30)
El celular y la antena, por 4GUnas decenas de ms, solo ese tramo

Son órdenes de magnitud, no promesas: cada red mide distinto, y lo que importa es medir la tuya.

Para ir más hondoDe dónde salen los números de la tabla

Dos referencias públicas: AWS dice que las zonas de una región están a menos de 100 km entre sí, que a la velocidad de la luz en fibra es ≈ 1 ms de ida y vuelta, y Azure publica la mediana entre sus regiones: de Querétaro a las de Virginia, 48 a 53 ms (en julio de 2026).

Cuántas idas y vueltas paga una request

Ahora junta las piezas. Una request por una conexión nueva paga 1 RTT de handshake y 1 RTT de la request y su respuesta: 2 RTT. Si además va cifrada, como casi todo en internet, con TLS (el protocolo que cifra la conexión para que nadie en el camino pueda leerla), el saludo del cifrado suma, en su versión actual (TLS 1.3), otro RTT: 3 en total. La versión anterior, TLS 1.2, que todavía se usa, cobraba 2 de saludo: 4 en total. Por una conexión que ya estaba abierta: 1.

Con un RTT de 60 ms, un número redondo cerca del de Ana a Virginia (≈ 45 ms de la ruta más lo que sume el 4G), la diferencia se ve así:

Conexión nueva contra conexión abierta, a 60 ms de RTTLa cuenta
Por una conexión ya abiertasolo la request y su respuesta
1 × 60 ms
60 ms
Por una conexión nuevahandshake de TCP + request
2 × 60 ms
120 ms
Nueva y con TLShandshake de TCP + saludo de TLS + request
3 × 60 ms
180 ms
Resultado
Abrir la conexión triplica lo que la red le cobra a la request. Contra una promesa de 200 ms, como el SLO de C01, la diferencia entre 60 y 180 ms es casi todo el presupuesto.

Por eso existe keep-alive: dejar la conexión abierta después de una request para mandar la siguiente por ahí. Y por eso los programas que hacen muchas requests guardan varias conexiones abiertas listas para usarse, un pool de conexiones. Las dos ideas son de la lección de HTTP.

Lo que la distancia le cobra a una requestCalculadora

La luz en la fibra recorre ≈ 200 km por milisegundo. Elige la distancia y cuántas idas y vueltas (RTT) pide cada request. Arranca con la Ciudad de México y el norte de Virginia, donde vive C01, en línea recta y con una conexión nueva.

RTT por la distanciaida y vuelta, solo lo que tarda la luz en la fibra por esa ruta30.1 ms
Idas y vueltas que pagan las requests1 por request, más 1 por TCP y 1 por TLS si la conexión es nueva2
Tiempo de red, como mínimo60.2 ms
Parte de una promesa de 200 msmás de 100 %: la luz sola ya no cabe30.1 %

Prueba Madrid con conexión nueva y TLS: 3 idas y vueltas de ≈ 91 ms ya pasan de 270 ms antes de que el servidor haga nada. Luego pon la conexión en 0: reusarla ahorra 2 de cada 3.

Pon 184 km, Querétaro, con conexión nueva y TLS: ≈ 5.5 ms. Acercarse vale más que cualquier optimización del código.

En C01, la regla se cumple en cada salto. El backend del marketplace está en la misma región que C01 y llama con conexiones abiertas. El gateway y Triton están en la misma zona y también reusan conexiones: su RTT es una fracción de milisegundo. Lo que no se controla es el tramo de Ana: por eso el SLO de 200 ms se mide del lado del servidor, desde que la request completa llega.

06

DNS: del nombre a la dirección

Esencial

DNS: from name to address

Las personas usan nombres; la red, números

Nadie escribe 203.0.113.10 en el navegador: escribe api.example.com. Y aunque lo escribiera, las IP cambian: una empresa muda su servicio a otra máquina y la IP vieja deja de servir. Hace falta un directorio que traduzca nombres a direcciones, que cualquiera pueda consultar y que se pueda actualizar. Ese directorio es el DNS (Domain Name System, sistema de nombres de dominio).

Usar el DNS se llama resolver un nombre. Antes de abrir cualquier conexión, el programa lo resuelve: le pregunta al DNS «¿qué IP tiene api.example.com?» y recibe «203.0.113.10». (El rango 203.0.113.x está reservado para ejemplos, como example.com: no es de nadie.)

Un árbol de nombres

Un nombre se lee de derecha a izquierda, como una dirección postal que empieza por el país: api.example.com es «la máquina api, de example, dentro de .com». Y la información también está repartida así, en un árbol: nadie tiene la lista completa de todos los nombres del mundo.

  • Los servidores raíz (root) saben quién lleva cada terminación: .com, .mx, .org.
  • Los servidores de cada terminación (top-level domain, TLD) saben quién lleva cada nombre: quién manda en example.com.
  • El servidor autoritativo de example.com tiene la respuesta oficial: api.example.com es 203.0.113.10.

Tu programa no recorre el árbol. Le pregunta a un resolver (así, en inglés: «el que resuelve»), un servidor de DNS que hace el recorrido por él: el de tu proveedor de internet, el de la red de la nube o uno público, como el 8.8.8.8.

Cómo se resuelve un nombre: la primera vez y las siguientes · Toca cada caja para ver qué sabe, o usa «Recorrer» para seguir una búsqueda la primera vez y las siguientes.
  • Tu programa · pide api.example.com
    Un programa casi nunca sabe IPs: sabe nombres. Le pide al sistema operativo la IP de un nombre (en Python, socket.getaddrinfo) y el sistema le pregunta a su resolver.
  • Resolver · con caché
    El servidor de DNS que hace el trabajo por ti: el de tu proveedor de internet, el de la nube o uno público. Pregunta de servidor en servidor y guarda cada respuesta en su caché lo que diga su TTL.
  • Raíz · ¿quién lleva .com?
    La punta del árbol de nombres. No sabe la IP de api.example.com, pero sabe qué servidores llevan cada terminación: .com, .mx, .org. Hay 13 nombres de servidores raíz, cada uno con muchas copias por el mundo.
  • Servidor de .com · ¿quién lleva example?
    El servidor de la terminación (top-level domain, TLD). Tampoco sabe la IP final: sabe qué servidor es el autoritativo de example.com, el que tiene la respuesta oficial.
  • Autoritativo · de example.com
    El que manda en ese nombre: aquí la empresa escribió que api.example.com es 203.0.113.10, con un TTL de 300 s. Si cambia de máquina, cambia este registro.

La caché y el TTL

Recorrer el árbol cuesta varias idas y vueltas. Si se hiciera en cada request, el DNS sería lentísimo y los servidores raíz recibirían cada búsqueda del mundo. La solución es guardar las respuestas: una caché.

Pero una respuesta guardada puede quedar vieja. Por eso cada respuesta trae su TTL (time to live, tiempo de vida): cuántos segundos se puede guardar antes de volver a preguntar. Lo decide el dueño del nombre. Un TTL de 300 s quiere decir «guárdala hasta 5 minutos».

El TTL es un trato. Uno corto cuesta más consultas pero los cambios se notan rápido; uno largo ahorra consultas pero un cambio tarda en llegar a todos. Un ejemplo con números: el TTL es de 300 s, tu programa preguntó en t = 0 y la empresa cambia de máquina en t = 150. Tu programa sigue usando la IP vieja hasta t = 300, cuando vence su caché. Si la máquina vieja ya estaba apagada, son 150 segundos de errores. Por eso, antes de mudar un servicio, se baja el TTL con días de anticipación.

Para ir más hondoLa caché del DNS, en Python

Esta simulación, con un reloj de mentiras, hace justo eso: la empresa cambia de máquina a los 150 s y nadie se entera hasta que vence la caché.

python
registro = {"api.example.com": "203.0.113.10"}   # lo que dice el servidor autoritativo
TTL = 300                                        # segundos que se puede guardar la respuesta
cache = {}                                       # nombre → (ip, hasta cuándo vale)
consultas = 0

def resolver(nombre, ahora):
    global consultas
    if nombre in cache and ahora < cache[nombre][1]:
        return cache[nombre][0], "de la caché"
    consultas += 1                               # pregunta de verdad, por la red
    cache[nombre] = (registro[nombre], ahora + TTL)
    return registro[nombre], "preguntó"

for t in (0, 10, 120):
    print(f"t = {t:>3} s:", *resolver("api.example.com", t))
registro["api.example.com"] = "203.0.113.99"     # a los 150 s, la empresa cambia de máquina
for t in (200, 299, 300, 310):
    print(f"t = {t:>3} s:", *resolver("api.example.com", t))
print("consultas de verdad:", consultas, "de 7 búsquedas")
Salida
t =   0 s: 203.0.113.10 preguntó
t =  10 s: 203.0.113.10 de la caché
t = 120 s: 203.0.113.10 de la caché
t = 200 s: 203.0.113.10 de la caché
t = 299 s: 203.0.113.10 de la caché
t = 300 s: 203.0.113.99 preguntó
t = 310 s: 203.0.113.99 de la caché
consultas de verdad: 2 de 7 búsquedas

De los 150 s a los 300, el programa siguió mandando requests a la máquina vieja; de 7 búsquedas, solo 2 salieron a la red.

Nombres dentro de Kubernetes

Dentro de un clúster de Kubernetes, el grupo de máquinas que maneja los pods de C01, hay un DNS propio. El problema que resuelve es el de las IP de los pods: cambian cada vez que un pod se reinicia. Así que el gateway no apunta a la IP de un pod de Triton; apunta a un nombre:

triton.classifier.svc.cluster.local

Se lee igual, de derecha a izquierda: el dominio del clúster (cluster.local), los Services (svc), el namespace classifier y el Service triton. Ojo: un namespace de Kubernetes no es el namespace de red de Linux que viste arriba; es solo una carpeta para agrupar los objetos de un equipo, y classifier es la de C01. Un Service es un objeto de Kubernetes que pone un nombre y una IP fijos delante de los pods que hacen el mismo trabajo, y reparte entre ellos. El gateway lee ese nombre de una variable de su configuración, TRITON_URL=triton.classifier.svc.cluster.local:8000: el nombre y, después de los dos puntos, el puerto.

Para ir más hondoPor qué un nombre corto cuesta varias consultas en un pod

Dentro de un pod, el archivo /etc/resolv.conf le dice al sistema a qué DNS preguntar y qué terminaciones probar. En el namespace classifier, la lista de terminaciones (search) es classifier.svc.cluster.local, svc.cluster.local y cluster.local, y Kubernetes pone ndots:5: si un nombre tiene menos de 5 puntos, se prueba primero con cada terminación. Por eso triton a secas funciona dentro del namespace: se vuelve triton.classifier.svc.cluster.local al primer intento.

El efecto raro es con nombres de afuera. api.example.com tiene 2 puntos, así que el pod pregunta primero por api.example.com.classifier.svc.cluster.local, luego por las otras dos terminaciones, y solo al final por el nombre real; y cada intento va dos veces, una por la dirección IPv4 y otra por la IPv6. Son 8 consultas para una respuesta, y más si el nodo agrega sus propias terminaciones a la lista, como hace EKS, el Kubernetes de AWS. Hasta el nombre completo de Triton tiene solo 4 puntos y pasa por lo mismo antes de encontrarse. Se evita con un punto al final del nombre (api.example.com.), que quiere decir «este nombre ya está completo», o bajando ndots.

07

Las capas y el viaje completo de la foto

Esencial

Layers and the full trip of the photo

Cada capa responde una pregunta

Ya tienes todas las piezas. Fíjate en que cada protocolo resuelve una sola pregunta y deja las demás a otro:

  • Enlace (Wi-Fi, o Ethernet, la red por cable): ¿cómo llego al siguiente aparato, el que tengo enfrente? Solo un salto.
  • IP: ¿a qué máquina va, a través de todos los saltos?
  • TCP o UDP: ¿a qué programa de esa máquina, y llega completo y en orden?
  • HTTP (y el resto de los protocolos de los programas): ¿qué se pide y qué se contesta?

A esa pila se le dice capas de red (network layers). Cada capa usa la de abajo sin saber cómo funciona: HTTP no sabe de routers, e IP no sabe que lleva una foto. Por eso se puede cambiar una sin tocar las demás: la misma request de HTTP viaja igual por Wi-Fi, por 4G o por fibra.

En el trabajo se nombran con números, que vienen de un modelo de siete capas, el modelo OSI: el enlace es la capa 2 (L2), IP es la capa 3 (L3), TCP y UDP son la capa 4 (L4) y HTTP es la capa 7 (L7). Las otras casi no se mencionan. Internet, en realidad, se diseñó con un modelo de cuatro capas, el de TCP/IP (enlace, internet, transporte y aplicación), que son justo las cuatro de arriba; los números se tomaron prestados del OSI. En los dos, el DNS es de la capa de aplicación, como HTTP.

Sobres dentro de sobres

Al salir, cada capa envuelve lo que le dio la de arriba en su propio sobre: su encabezado. Al llegar, cada capa quita el suyo y le pasa el resto a la de arriba.

Lo que manda el gateway a Triton, como sobres dentro de sobres. Por dentro van los datos: el tensor de la foto, de 602,112 bytes. Los envuelve HTTP, la capa 7, que dice qué se pide: POST a /v2/models/classifier/infer. Lo envuelve TCP, la capa 4, que dice a qué programa va: del puerto 51234 al 8000, en orden. Lo envuelve IP, la capa 3, que dice a qué máquina: de 10.0.3.15 a 10.0.3.27. Y por fuera va la capa de enlace, la capa 2, Ethernet o Wi-Fi, que lo lleva solo hasta el siguiente aparato del camino. Cada capa agrega su sobre al salir y lo quita al llegar. SOBRES DENTRO DE SOBRES ENLACE · CAPA 2 · ¿AL SIGUIENTE APARATO? Ethernet o Wi-Fi: solo hasta el siguiente salto IP · CAPA 3 · ¿A QUÉ MÁQUINA? de 10.0.3.15 a 10.0.3.27 TCP · CAPA 4 · ¿A QUÉ PROGRAMA? del puerto 51234 al 8000, en orden HTTP · CAPA 7 · ¿QUÉ SE PIDE? POST /v2/models/classifier/infer los datos: el tensor de la foto 602,112 bytes Cada capa agrega su sobre al salir y lo quita al llegar, de afuera hacia adentro.
Lo que el gateway le manda a Triton. El tensor va adentro; lo envuelven HTTP, TCP, IP y el enlace, y cada sobre responde su propia pregunta.
Para ir más hondoLo que pesan los sobres

Cada sobre ocupa bytes que no son datos. En un paquete de TCP sobre IPv4, la cuenta es esta:

Lo que pesan los sobres de un paquete de 1,500 bytesLa cuenta
Encabezado de IPIPv4, el tamaño más común
—
20 bytes
Encabezado de TCPsin opciones extra
—
20 bytes
Lo que queda para datos
1,500 − 20 − 20
1,460 bytes
Parte que son sobres
40 ÷ 1,500
≈ 2.7 %
Con UDP en vez de TCP8 bytes de encabezado
1,500 − 20 − 8
1,472 bytes
Resultado
Por eso 1,460 es el número de la primera sección. El enlace agrega su sobre aparte, por fuera de los 1,500, y el de HTTP va solo en el primer paquete de la request.

En la práctica caben un poco menos. Linux le pone a cada paquete de TCP, por omisión, 12 bytes de opciones con la hora de envío (timestamps), que le sirven para medir el RTT: quedan 1,448 bytes de datos. La lección redondea con 1,460, la cuenta clásica.

Las capas importan para la Ronda por una razón práctica: lo que ve una máquina depende de la capa en la que trabaja. Un router solo lee la capa 3: IP de origen y de destino. Un balanceador (un programa que reparte las requests entre varias copias de un mismo servidor) que trabaja en la capa 4 ve también los puertos, y nada más: reparte conexiones, sin saber qué requests van adentro. Uno de capa 7 abre HTTP y ve cada request: su ruta, sus encabezados. La Ronda (M06) dice que el Service de Kubernetes «balancea por conexión (L4)», y en la lección Balanceadores, proxies y gateways vas a ver por qué eso le complica la vida a un servidor de modelos.

El viaje completo

Ahora sí, la respuesta a la pregunta de la lección. Recorre el diagrama paso a paso:

El viaje de la foto de Ana: qué nombre, qué IP y qué puerto en cada salto · Usa «Recorrer» para seguir la foto de Ana salto por salto, o el recorrido de quién es cliente y quién servidor en cada conexión.
  • Celular de Ana · 4G · IP privada
    La app es el cliente: abre la conexión. El celular tiene una IP privada del operador, que NAT traduce a una pública al salir a internet. Su RTT por 4G suma decenas de milisegundos que nadie en C01 controla.
  • DNS · nombre → IP
    Antes de conectarse, la app pregunta al DNS la IP del backend del marketplace. Si la respuesta está en caché y su TTL no ha vencido, no hay ni que preguntar.
  • Backend · del marketplace
    El programa del marketplace que guarda la foto para la publicación. Recibe el JPEG de ≈ 200 KB (la app ya achicó la foto de 3 MB) por TCP en el puerto 443 y después se lo manda a C01 de servidor a servidor, en la misma región.
  • ALB · puerto 443 · TLS
    El ALB (Application Load Balancer) es el balanceador de AWS: la puerta de entrada de C01. Escucha en el 443, quita el cifrado (TLS, el protocolo que impide que alguien lea la request en el camino) y reparte las requests entre los pods del gateway. Lo verás en la lección de balanceadores.
  • Gateway · pod · puerto 8080
    uvicorn escucha en 0.0.0.0:8080 dentro de su contenedor. Para el ALB es servidor; para Triton es cliente: abre conexiones hacia él y las reusa.
  • DNS del clúster · CoreDNS
    El gateway no sabe la IP de Triton: sabe el nombre triton.classifier.svc.cluster.local. El DNS de Kubernetes (el programa que lo atiende se llama CoreDNS) lo traduce a la IP estable del Service, que no cambia aunque los pods de Triton se reinicien.
  • Triton · puerto 8000 · T4
    Escucha HTTP en el 8000, gRPC en el 8001 y métricas en el 8002. Recibe el tensor de 602 KB (≈ 413 paquetes), corre la ResNet-50 en la GPU (una T4) y contesta con las categorías.

En una frase: la app resuelve un nombre con el DNS, abre una conexión TCP a la IP y al puerto 443 del backend, y manda la foto en paquetes que los routers reenvían. El backend hace lo mismo hacia C01. El ALB (Application Load Balancer), el balanceador de AWS que es la puerta de entrada de C01, pasa la request a la IP privada de un pod del gateway, en el puerto 8080, donde uvicorn escucha en 0.0.0.0. Y el gateway, ahora como cliente, resuelve triton.classifier.svc.cluster.local y manda el tensor al puerto 8000 de Triton. Cada salto es una conexión distinta, y en cada una se repite lo mismo: nombre → IP, IP → máquina, puerto → programa, TCP → completo y en orden.

08

Dentro de TCP: pérdidas, arranque lento y conexiones caras

Extra

Inside TCP: losses, slow start and expensive connections

En la sección de TCP viste lo que promete. Aquí va cómo lo cumple sin ahogar a la red, y tres costos que aparecen en producción: el arranque lento, la espera de un paquete perdido y los puertos que se quedan ocupados.

El arranque lento

TCP no sabe qué tan ancho es el camino. Si mandara todo de golpe, podría saturar un router y perder la mitad. Así que empieza con poco y va subiendo: manda un puñado de paquetes, espera sus acuses y, si llegaron bien, en la siguiente vuelta manda el doble. Esa cantidad que se permite mandar sin acuse es la ventana de congestión (congestion window), y la fase en la que se duplica en cada RTT se llama arranque lento (slow start). Hoy casi todos los sistemas empiezan con una ventana de 10 paquetes, ≈ 14.6 KB: la recomendación del RFC 6928, de 2013, que Linux ya usaba desde 2011.

El JPEG de 200 KB, en una conexión recién abiertaLa cuenta
Paquetes que hay que mandar
200,000 ÷ 1,460 → hacia arriba
137
Primera vueltala ventana inicial
10
llevan 10
Segunda vueltael doble
20
llevan 30
Tercera vuelta
40
llevan 70
Cuarta vuelta
80
llevan 150: ya pasaron de 137
Resultado
Son 4 RTT solo para mandar 200 KB, aunque el tubo fuera enorme. Por 4G, con 50 ms de RTT, son ≈ 200 ms. Una foto de 3 MB necesita 8.

Con un ancho de banda chico pasa al revés: el que manda es el tubo, no el RTT. 3 MB a 10 Mb/s son 2.4 s, se abra la ventana tan rápido como se abra. La calculadora te deja ver cuál de los dos limita.

El arranque lento de una conexión nuevaCalculadora

Una conexión TCP nueva empieza mandando unos pocos paquetes por cada ida y vuelta y duplica la cantidad en cada RTT. Arranca con el JPEG de ≈ 200 KB que la app de Ana sube por 4G, con una conexión recién abierta.

Paquetes de 1,460 bytes137
Idas y vueltas del arranque lentocada una manda el doble que la anterior4
Lo que pide el arranque lentoidas y vueltas × RTT200.0 ms
Lo que pide el ancho de bandabits ÷ bits por segundo160.0 ms
Piso aproximado del envíomanda el más lento de los dos; sin contar el handshake200.0 ms

Sube el ancho de banda a 1000 Mb/s: el envío no baja de 200 ms, porque lo que manda es el RTT. Ahora, con esos 1000 Mb/s, baja el RTT a 0.5, como dentro de una zona de la nube: el mismo envío cae a 2 ms.

Pon 602 KB, el tensor de C01, con 0.5 ms de RTT y 5000 Mb/s, como dentro de una zona: 6 vueltas, ≈ 3 ms. Y el tensor ya viaja por conexiones abiertas, con la ventana grande.

Una conexión que ya estaba abierta tiene la ventana grande: la siguiente request no vuelve a arrancar desde 10. Es otra razón para reusar conexiones, además del handshake. (Si la conexión pasa un rato sin usarse, Linux, por omisión, vuelve a empezar con la ventana chica.)

Cuando se pierde un paquete

Si un acuse no llega, TCP espera un tiempo, el tiempo de reenvío (retransmission timeout), y reenvía. Ese tiempo se calcula con los RTT medidos y tiene un mínimo: en Linux, 200 ms. Si los acuses que sí llegan muestran un hueco (tres acuses repetidos que dicen «tengo hasta el byte tal», porque los paquetes de después llegaron y el que falta no), reenvía sin esperar. En los dos casos, además, achica la ventana: interpreta la pérdida como señal de que la red está saturada.

El peor caso es perder el SYN, el primer paquete del handshake. Todavía no hay RTT medido, así que el cliente espera 1 segundo antes de reenviarlo, y si se vuelve a perder, 2 más. Por eso en las gráficas de latencia a veces aparecen requests de ≈ 1 s y ≈ 3 s que no tienen nada que ver con tu código: son SYN perdidos. Con un SLO de 200 ms, un solo SYN perdido ya rompe la request.

Un paquete perdido detiene a todos

TCP entrega en orden. Si se pierde el paquete 5 y llegan del 6 al 40, el programa no recibe ninguno hasta que llegue el 5 reenviado: todos esperan detrás del perdido. Es el bloqueo por cabeza de fila (head-of-line blocking). Si por esa conexión viajaban varias requests a la vez, una pérdida frena a todas, aunque sus pedazos ya hubieran llegado.

Esto explica QUIC. Para arreglarlo había que cambiar TCP, pero TCP vive dentro del kernel de miles de millones de aparatos, y muchos aparatos del camino que revisan el tráfico, como los firewalls, tiran lo que no reconocen: cambiarlo tarda décadas. Así que QUIC se construyó encima de UDP, que cualquier programa puede usar, y hace sus propios números, acuses y reenvíos, con varias conversaciones independientes dentro de la misma conexión: una pérdida frena solo a la suya. Además junta el handshake de transporte y el de cifrado en 1 RTT. HTTP/3 es HTTP sobre QUIC, y lo usan muchos navegadores y sitios grandes.

Los puertos que se quedan ocupados

Al cerrar una conexión, el lado que cierra primero no libera de inmediato sus cuatro números: los deja apartados un rato por si llega tarde algún paquete viejo. Ese estado se llama TIME_WAIT, y en Linux dura 60 s. Si el que cierra primero es el cliente, el puerto apartado es uno de sus efímeros, y esos se pueden acabar.

Un cliente que abre y cierra una conexión por requestLa cuenta
Puertos efímeros de Linuxdel 32,768 al 60,999
60,999 − 32,768 + 1
28,232
Lo que dura cada uno apartado al cerrar
—
60 s
Conexiones nuevas por segundo, como máximohacia la misma IP y el mismo puerto
28,232 ÷ 60
≈ 470
Resultado
Un cliente que abre y cierra una conexión por request no pasa de ≈ 470 requests por segundo hacia el mismo destino. Al pico de diseño de C01, 500 por segundo, ya no alcanzaría.

C01 no tiene ese problema, porque reparte las 500 requests por segundo entre 5 pods y, sobre todo, porque reusa conexiones. Pero un job de prueba que lanza miles de requests con un cliente que abre una conexión cada vez se topa con ese techo y empieza a fallar con «cannot assign requested address». La salida no es tocar el kernel: es un pool de conexiones.

09

Errores comunes

Esencial

Common mistakes

1. Escuchar en 127.0.0.1 dentro de un contenedor

El servidor arranca, los logs dicen «running on http://127.0.0.1:8000» y nadie de afuera puede hablarle. Dentro del contenedor, 127.0.0.1 es su propio localhost, y lo de afuera llega por otra interfaz. El síntoma cambia según por dónde llegues: desde otra máquina, «connection refused»; desde tu laptop, con -p (la opción de Docker que conecta un puerto de tu laptop con uno del contenedor; la ves en el error siguiente), a veces Docker acepta la conexión y luego la corta, y curl dice «Empty reply from server» o «Connection reset by peer». Es el mismo error.

Cómo evitarlo: en un contenedor, escuchar en 0.0.0.0 (uvicorn --host 0.0.0.0). En tu laptop, fuera de un contenedor, deja 127.0.0.1: así nadie de tu red le habla a tu programa a medio hacer.

2. Confundir el puerto del contenedor con el de la máquina

docker run -p 8080:8000 quiere decir «el puerto 8080 de la máquina lleva al 8000 del contenedor»: primero el de afuera, después el de adentro. Si uvicorn escucha en el 8080 dentro del contenedor, ese -p apunta a un puerto donde nadie escucha.

Cómo evitarlo: decide el puerto en un solo lugar (una variable de configuración) y revisa que coincidan el --port del programa, el -p de Docker o el containerPort de Kubernetes (el campo de su configuración que dice en qué puerto escucha el contenedor), y el puerto que piden sus clientes.

3. Abrir una conexión nueva en cada request

Cada conexión nueva paga 1 RTT de handshake (2 con TLS), empieza mandando poco a poco (el arranque lento de la sección extra «Dentro de TCP») y, al cerrarse, deja su puerto apartado un rato. A 60 ms de RTT y con TLS, una request que costaría 60 ms cuesta 180.

Cómo evitarlo: crear el cliente HTTP una vez, al arrancar el programa, y reusarlo: con keep-alive y un pool de conexiones. Nunca crear un cliente nuevo dentro de la función que atiende cada request.

4. Apuntar a la IP de un pod

Funciona hasta que el pod se reinicia y nace con otra IP. O hasta que Kubernetes agrega un pod nuevo que nadie conoce.

Cómo evitarlo: hablarle a un nombre, el del Service (triton.classifier.svc.cluster.local), que tiene una IP fija y siempre apunta a los pods vivos. En la nube, lo mismo: nombres de DNS, no IPs escritas en la configuración.

5. Olvidar el TTL al mover un servicio

Cambias la IP en el DNS y apagas la máquina vieja de inmediato. Durante lo que dure el TTL, todos los que tenían la respuesta guardada siguen llamando a la vieja. Con un TTL de un día, son hasta 24 horas de errores.

Cómo evitarlo: días antes del cambio, bajar el TTL (a 60 s, por ejemplo), esperar a que venza el viejo, cambiar la IP y dejar la máquina vieja viva hasta que se apague el tráfico. Después, volver a subir el TTL.

6. Creer que más ancho de banda arregla la latencia

Si el RTT a otro continente es de 100 ms, ningún plan de internet más rápido lo baja: más Gb/s sirve para mandar más cosas a la vez, no para que cada una llegue antes.

Cómo evitarlo: contar idas y vueltas, no solo megas. Acercar las máquinas, reusar conexiones y hacer menos viajes por request.

10

En la vida real

Extra

In real life

C01: cada salto, con sus números

Este es el viaje de la foto de Ana con lo que la Ronda deja escrito para C01:

SaltoCliente → servidorPuertoLo que viaja
Celular → backendLa app de Ana, por 4G e internet443El JPEG de ≈ 200 KB, ya achicado: 137 paquetes
Backend → ALBEl backend, de servidor a servidor (server-to-server), en us-east-1443El mismo JPEG: 137 paquetes
ALB → gatewayEl ALB, a la IP privada de un pod8080La misma foto, ya sin cifrar
Gateway → TritonEl gateway, por el nombre del Service8000El tensor de 602 KB: 413 paquetes
Prometheus → TritonEl que vigila las métricas8002Las métricas, cada 15 a 60 s, según se configure

Tres decisiones de C01 salen directo de esta lección.

Triton no tiene IP pública ni puerta de entrada. Solo se alcanza desde adentro, y una regla de red de Kubernetes (una NetworkPolicy) deja que le hablen únicamente los pods del gateway, y al 8002 solo Prometheus. Si nadie de afuera puede llegar al puerto, nadie de afuera puede abusar de él.

El gateway habla con el Triton de su misma zona. Al pico de diseño, el gateway manda 500 tensores de 602 KB por segundo: ≈ 301 MB/s, ≈ 2.4 Gb/s, ≈ 206,500 paquetes por segundo. Dentro de una zona, el RTT es una fracción de milisegundo y el tráfico no se cobra. Entre zonas, el RTT sube un poco y AWS cobra US$0.01 por GB en cada sentido (su precio de 2026 en us-east-1). Si el Service repartiera al azar, la mitad de los tensores cruzaría de zona. En un mes promedio, con ≈ 10 millones de fotos al día, los tensores suman 10,000,000 × 602 KB × 30 días ≈ 180 TB; la mitad son ≈ 90 TB, y a US$0.02 por GB (0.01 de cada lado), ≈ US$1,800 al mes: más de lo que cuestan las dos GPUs. La Ronda (M06) lo arregla con una línea en el Service de Triton, trafficDistribution: PreferSameZone (existe desde Kubernetes 1.34 y es estable desde 1.35): cada gateway prefiere el Triton de su zona y solo cruza si el suyo no está listo.

Las conexiones se reusan en todo el camino. El ALB mantiene conexiones abiertas con los pods del gateway, y la Ronda le da a su tramo ≈ 1 a 3 ms; el gateway reusa las suyas con Triton, y el tramo completo del tensor, con la conversión a bytes y la red dentro de la nube, se estima en ≈ 2 a 4 ms la mediana y ≈ 5 a 10 ms el p99. Con una conexión nueva por request, cada tramo pagaría el handshake, el arranque lento y un puerto en TIME_WAIT.

Dentro de una red de AWS, además, las máquinas pueden usar paquetes de hasta 9,001 bytes (jumbo frames): ahí el tensor de 602 KB son ≈ 68 paquetes en vez de 413. Al salir a internet, el tope vuelve a 1,500.

Y un detalle de M13: en AWS, cada IP pública cuesta US$0.005 por hora desde 2024, ≈ US$3.65 al mes. Darle IP pública a cada máquina «por comodidad» es pagar por exponerlas. Las de C01 viven en subredes privadas.

M07 y C10: las conexiones largas y el pod que nadie usa

Kubernetes reparte en la capa 4: conexiones, no requests. C10 sirve un LLM propio, y cada respuesta llega token por token durante varios segundos por la misma conexión. Un cliente que abre pocas conexiones y las mantiene vivas queda pegado a los mismos pods. Cuando el sistema agrega un pod nuevo porque hay mucha carga, el pod nace, está listo… y no recibe nada hasta que las conexiones viejas se cierran. La Ronda (M07) da las salidas: un balanceador de capa 7, que reparte requests; que el cliente conozca todas las IPs de los pods y reparta él mismo; o un tiempo de vida máximo para cada conexión. Lo vas a ver completo en la lección de balanceo.

Voz y videollamadas: UDP a propósito

En una videollamada, la voz y el video viajan casi siempre por UDP. Si se pierde un pedazo, el programa lo tapa como puede (repite el anterior, suaviza) y sigue: reenviarlo llegaría cuando ya no sirve. Lo que sí va por TCP es lo que no puede perderse, como el texto del chat. Un sistema de voz con ML, como el de transcripción de la Ronda, tiene el mismo dilema: para subtítulos en vivo, a veces conviene perder 20 ms de audio antes que atrasarse medio segundo.

Cuando falla el DNS, falla todo

El 4 de octubre de 2021, Facebook, Instagram y WhatsApp desaparecieron de internet durante unas 6 horas. Una orden de mantenimiento desconectó por error la red que une sus centros de datos, y sus servidores autoritativos de DNS, al quedarse aislados, dejaron de anunciarse a internet: nadie podía resolver facebook.com, así que nadie podía conectarse, aunque los servidores de la aplicación estuvieran encendidos. Hasta los empleados tuvieron problemas para entrar a los edificios, porque sus sistemas también dependían de esa red.

El 20 de octubre de 2025, en la región us-east-1 de AWS, la misma de C01, un error en el sistema que actualiza los registros de DNS de DynamoDB (una base de datos de AWS) dejó su nombre sin ninguna IP. Los programas que la usaban no podían encontrarla. AWS arregló el registro en menos de 3 horas, y aun así cada cliente tardó en recuperarse lo que tardó en vencer la respuesta vacía que tenía en caché: el TTL otra vez. Como muchos otros servicios de AWS dependen de DynamoDB, la falla siguió rebotando entre ellos hasta la tarde: unas 14 horas en total. Entre los ingenieros hay un dicho: «siempre es el DNS». Un sistema puede tener dos zonas, dos GPUs y su plan B; si nadie puede resolver su nombre, nadie llega.

11

Ejercicios

Esencial

Exercises

Resuélvelos con lápiz antes de abrir la solución. Los de distancia y de arranque lento se pueden comprobar con las calculadoras.

  1. 1Fácil

    Un vendedor sube desde la web el original de una foto de 10 MB. ¿Cuántos paquetes de 1,460 bytes de datos son? ¿Cuántos bytes de encabezados de IP y TCP viajan con ellos?

    Ver la solución paso a paso
    • Paquetes: 10,000,000 ÷ 1,460 = 6,849.3 → hacia arriba, 6,850.
    • Encabezados: 6,850 × 40 bytes = 274,000 bytes, ≈ 274 KB: el 2.7 % de lo que viaja.
  2. 2Fácil

    ¿Cuáles de estas direcciones son privadas? 10.2.3.4, 172.15.0.1, 172.31.255.1, 192.169.0.1 y 127.0.0.1.

    Ver la solución paso a paso
    • 10.2.3.4: privada. Empieza con 10: está en 10.0.0.0/8.
    • 172.15.0.1: pública. El rango privado de 172 va del 172.16 al 172.31; el 15 queda afuera.
    • 172.31.255.1: privada. Es la última parte del rango 172.16.0.0/12.
    • 192.169.0.1: pública. El rango privado es 192.168.x.x; 169 no entra.
    • 127.0.0.1: ninguna de las dos. Es loopback, la máquina misma: no sale ni a la red de la casa.
  3. 3Fácil

    Corres docker run -p 8080:8000 mi-api. Adentro, uvicorn arranca sin --host y en su puerto por omisión. Desde tu laptop, curl localhost:8080 falla. ¿Por qué, y qué cambias?

    Ver la solución paso a paso
    • El -p lleva el 8080 de tu laptop al 8000 del contenedor: el puerto coincide con el de uvicorn, eso está bien.
    • El problema es la dirección: sin --host, uvicorn escucha en 127.0.0.1, el localhost del contenedor. Lo que llega por -p entra por la interfaz de red del contenedor, donde nadie escucha.
    • Arreglo: uvicorn app:app --host 0.0.0.0 --port 8000.
  4. 4Fácil

    Un juego promete un RTT de 40 ms. Si todo fuera fibra en línea recta, ¿a cuántos km puede estar el servidor, como máximo?

    Ver la solución paso a paso
    • 40 ms de ida y vuelta son 20 ms de ida.
    • A 200 km por milisegundo: 20 × 200 = 4,000 km, como máximo. En la práctica, menos, porque la ruta no es recta y cada router suma.
  5. 5Medio

    Un programa hace 3 requests seguidas, cada una esperando a la anterior, a un servidor con 45 ms de RTT y TLS. ¿Cuánto tarda la red si abre una conexión nueva para cada una? ¿Y si abre una y la reusa?

    Ver la solución paso a paso
    • Conexión nueva para cada una: 3 RTT por request (TCP, TLS y la request) × 3 requests = 9 RTT = 9 × 45 = 405 ms.
    • Una sola conexión: 2 RTT para abrirla (TCP y TLS) + 3 RTT de las requests = 5 RTT = 225 ms.
    • Reusar ahorra 180 ms. Si la conexión ya estaba abierta de antes, quedan 3 × 45 = 135 ms.
  6. 6Medio

    El nombre de un servicio tiene un TTL de 86,400 s. El lunes a las 10:00 cambias su IP y apagas la máquina vieja. ¿Hasta cuándo puede haber clientes llamando a la vieja? ¿Cómo lo harías mejor?

    Ver la solución paso a paso
    • 86,400 s ÷ 3,600 = 24 horas. Un cliente que guardó la respuesta el lunes a las 9:59 la usa hasta el martes a las 9:59: casi un día de errores para él.
    • Mejor: el viernes anterior, bajar el TTL a 60 s. Esperar al menos 24 horas, para que venza todo lo guardado con el TTL viejo. El lunes, cambiar la IP; a los pocos minutos, casi todos usan la nueva. Dejar la vieja encendida hasta que deje de recibir tráfico y luego subir el TTL otra vez.
  7. 7Medio

    Escribe 10.0.3.15 en binario, byte por byte. ¿Está en la red 10.0.0.0/8? ¿Y en 10.0.2.0/24?

    Ver la solución paso a paso
    • 10 = 0000 1010; 0 = 0000 0000; 3 = 0000 0011; 15 = 0000 1111. Juntos: 00001010.00000000.00000011.00001111.
    • /8 deja fijos los primeros 8 bits, que en 10.0.0.0 son 00001010. Coinciden: sí está.
    • /24 deja fijos los primeros 3 bytes: 10, 0 y 2. El tercer byte de la dirección es 3, no 2: no está. Estaría en 10.0.3.0/24.
  8. 8Medio

    Por una conexión TCP nueva hay que mandar 1 MB, con 50 ms de RTT y 10 Mb/s de ancho de banda. ¿Cuántas vueltas pide el arranque lento, con ventana inicial de 10? ¿Qué limita más, el RTT o el ancho de banda?

    Ver la solución paso a paso
    • Paquetes: 1,000,000 ÷ 1,460 → 685.
    • Vueltas: 10, 20, 40, 80, 160, 320 suman 630; falta una más: 7 vueltas, 7 × 50 = 350 ms.
    • Por ancho de banda: 1,000,000 × 8 = 8,000,000 bits ÷ 10,000,000 bits por segundo = 0.8 s.
    • Limita el ancho de banda: el envío tarda ≈ 800 ms aunque la ventana se abra en 350. Con 100 Mb/s, mandaría el RTT.
  9. 9Reto

    Un job de prueba manda 2,000 requests por segundo a un Triton, desde una sola máquina, y abre y cierra una conexión por request. A los pocos segundos empieza a fallar con «cannot assign requested address». ¿Por qué, y en cuántos segundos? ¿Qué cambias?

    Ver la solución paso a paso
    • Cada conexión cerrada deja su puerto efímero en TIME_WAIT 60 s. Para sostener 2,000 por segundo harían falta 2,000 × 60 = 120,000 puertos apartados a la vez, y Linux trae 28,232.
    • Se acaban en 28,232 ÷ 2,000 ≈ 14 segundos. Desde ahí, el kernel no tiene puerto que prestarle a la siguiente conexión.
    • El techo con conexiones nuevas es ≈ 470 por segundo hacia ese destino. Arreglo: un pool de conexiones con keep-alive. Con 20 conexiones reusadas, cada una lleva 100 requests por segundo, sin handshakes ni TIME_WAIT.
  10. 10Reto

    Ana, en la Ciudad de México, sube por 4G a Virginia el original de su foto, de 3 MB, como si la app no la achicara. Supón un RTT de 80 ms (45 de la ruta más 35 del tramo de radio), 10 Mb/s de subida, el nombre ya guardado en caché y una conexión nueva con TLS. Estima lo que tarda la red hasta que la foto llega completa. ¿Por qué el SLO de C01 no mide esto?

    Ver la solución paso a paso
    • DNS: en caché, 0 ms.
    • Handshake de TCP y saludo de TLS: 2 RTT = 160 ms.
    • La foto: el arranque lento pediría 8 vueltas × 80 = 640 ms, pero el ancho de banda pide 3,000,000 × 8 ÷ 10,000,000 = 2.4 s. Manda el ancho de banda.
    • Total: ≈ 160 + 2,400 ≈ 2.6 s, más lo que tarde en volver la respuesta.
    • El SLO de C01 (p99 ≤ 200 ms) se mide del lado del servidor, desde que la request completa llega. Estos 2.6 s dependen de la señal de Ana y de su compañía de celular, que nadie en C01 controla. Por eso, además, la app achica la foto antes de subirla: con ≈ 200 KB son 137 paquetes, 4 vueltas de arranque lento × 80 = 320 ms (el ancho de banda pediría solo 160), y con el handshake, ≈ 480 ms en vez de 2.6 s.
12

Lo que sigue

Esencial

What comes next

En la Ronda:

  • M02 · Patrones de inferencia, para decidir si el modelo corre en la nube o junto a las cámaras, pregunta si cabe una ida y vuelta por una red que no controlas y cuántos Mb/s tiene el sitio: RTT y ancho de banda.
  • M06 · Orquestación y escalado usa los Services de Kubernetes como «un nombre DNS estable delante de los pods sanos», pone triton.classifier.svc.cluster.local:8000 en la configuración del gateway, advierte que el Service balancea por conexión (L4) y manda el tráfico a la misma zona con PreferSameZone.
  • M13 · Nube recorre cada byte: IP públicas que se cobran, subredes privadas, el NAT de la salida a internet y lo que cuesta cruzar de zona o de región.
  • También: M07 usa los puertos de Triton (8000 HTTP, 8001 gRPC, 8002 métricas) y el caso del pod nuevo que no recibe tráfico por las conexiones persistentes.

En el Dojo: la estación 7, «Empaquetado (Docker)», ya está abierta: ahí publicas puertos con -p y te topas con el «escuchar en 0.0.0.0». La estación 9, «Kubernetes», todavía no abre; cuando abra, el gateway encontrará a Triton por el nombre de su Service.

En Sensei: la siguiente lección, «HTTP: requests, respuestas y códigos», abre lo que viaja dentro de la conexión TCP: el método, la URL, los encabezados, los códigos como 200 o 503, el keep-alive y el pool de conexiones. Después vienen las APIs, los balanceadores (capa 4 contra capa 7), los timeouts y reintentos, y la latencia de punta a punta. En la fase 8, «Redes en la nube» arma la VPC, el NAT y la salida a internet de C01, y otra lección explica el cifrado con TLS.

13

Palabras que vas a oír

Esencial

Words you will hear

Estos son los conceptos que presentó esta lección. Cada uno tiene su tarjeta con la definición completa.

ProtocoloprotocolEl acuerdo de cómo hablan dos programas por la red: qué se manda primero, cómo se escribe cada dato, qué se contesta y qué se hace si algo falla. Los dos lados tienen que seguir el mismo.Más

En la red cada protocolo resuelve una pregunta y se apoya en el de abajo: IP lleva cada paquete a la máquina, TCP o UDP lo llevan al programa, y HTTP dice qué se pide y qué se contesta; el DNS traduce nombres en direcciones. Esa pila son las capas de red. Los protocolos de internet están escritos en documentos públicos, los RFC, y cualquier programa que los siga se entiende con cualquier otro, aunque estén escritos en lenguajes distintos.

Analogía. Una llamada por teléfono: quien contesta dice «¿bueno?», quien llama dice quién es, hablan por turnos y se despiden antes de colgar. Se rompe en que la gente improvisa y se entiende igual; un programa que se sale del protocolo en un solo byte ya no se entiende con nadie.

Ejemplo. El gateway de C01 le habla a Triton con HTTP, que va sobre TCP, que va sobre IP: tres protocolos a la vez en la misma request.

Ver en el glosario →

Paquete de redpacketUn pedazo de un mensaje que viaja solo por la red, con un encabezado que dice de dónde viene y a dónde va, y su carga: el pedazo de datos. En casi todas las redes mide como máximo ≈ 1,500 bytes.Más

La red parte cada mensaje en paquetes para que muchos aparatos se turnen el mismo cable, para reenviar solo lo que se daña y para que cada pedazo tome el camino libre. El tope de un paquete se llama MTU; en internet suele ser de 1,500 bytes, de los que 40 son los encabezados de IP y TCP, así que quedan 1,460 para datos. Los routers leen solo el encabezado y lo reenvían. Como cada paquete viaja por su cuenta, pueden llegar desordenados, repetidos o perderse: TCP los junta y pide los que faltan.

Ejemplo. El original de la foto de Ana, de 3 MB, serían 3,000,000 ÷ 1,460 → 2,055 paquetes; el JPEG de ≈ 200 KB que de verdad manda la app, 137. El tensor de 602 KB que el gateway le manda a Triton son 413; al pico de diseño, ≈ 206,500 paquetes por segundo.

Ver en el glosario →

Dirección IPIP addressEl número que identifica a un aparato en la red, para que los paquetes lleguen a él. En IPv4 son 32 bits escritos como cuatro números del 0 al 255 (192.168.1.20); en IPv6, 128 bits.Más

IP (Internet Protocol) es el protocolo que lleva cada paquete de máquina en máquina. IPv4 tiene 2³² ≈ 4.3 mil millones de direcciones, y se acabaron; IPv6 tiene 2¹²⁸ ≈ 3.4 × 10³⁸ y se escribe en hexadecimal (2001:db8::1). Una dirección tiene una parte que dice en qué red está y otra que dice qué máquina es: 10.0.0.0/8 son todas las que empiezan con el byte 10. Hay direcciones públicas, únicas en internet, y privadas, que valen solo dentro de una red. La IP dice a qué máquina va un paquete; el puerto, a qué programa.

Ejemplo. Un pod del gateway de C01 tiene una IP privada como 10.0.3.15 = 00001010.00000000.00000011.00001111 en binario. Si el pod se reinicia, el nuevo nace con otra: por eso se le habla por nombre, con el DNS.

Ver en el glosario →

IP privadaprivate IP addressUna dirección IP de los rangos apartados para redes internas (10.x.x.x, 172.16 a 172.31.x.x y 192.168.x.x). Vale solo dentro de su red y no se puede alcanzar desde internet.Más

Los tres rangos privados son 10.0.0.0/8 (16,777,216 direcciones), 172.16.0.0/12 (1,048,576) y 192.168.0.0/16 (65,536). Cualquiera puede usarlos adentro sin pedir permiso, así que la misma dirección existe en millones de redes a la vez. Para salir a internet, un aparato con IP privada pasa por NAT, que cambia su dirección por una pública y recuerda a quién devolver la respuesta. En la nube, las máquinas viven en una red privada, la VPC, y solo la puerta de entrada tiene IP pública. Distinto de 127.0.0.1, que es localhost: la máquina misma.

Analogía. Las extensiones de una oficina: la 102 existe en muchas oficinas a la vez y solo funciona adentro; para que te llamen de afuera, se marca el número del conmutador. Se rompe en que el conmutador no cambia nada en tu llamada, y NAT sí reescribe cada paquete.

Ejemplo. En tu casa, tu celular es 192.168.1.20 y el router tiene una sola IP pública para todos. En C01, Triton solo tiene IP privada: desde internet no hay manera de llegarle.

Ver en el glosario →

PuertoportUn número de 16 bits, del 0 al 65,535, que dice a qué programa de una máquina va un paquete. La IP lleva a la máquina; el puerto, al programa que se apuntó en ese número.Más

Un servidor se apunta en un puerto con la syscall bind y el kernel le entrega lo que llegue ahí. Cada protocolo tiene uno acordado: 22 para SSH, 53 para DNS, 80 para HTTP y 443 para HTTPS. Los menores que 1024, en Linux, solo los abre root. Un programa puede escuchar en varios puertos, pero dos programas de la misma máquina no pueden compartir uno en la misma IP (salvo con opciones especiales). El cliente también usa un puerto, uno efímero que le presta el kernel (en Linux, del 32,768 al 60,999). Una conexión queda identificada por cuatro números: IP y puerto de cada lado.

Analogía. Si la IP es la dirección de un edificio, el puerto es el número del departamento. Se rompe en que un mismo programa puede vivir en varios departamentos a la vez, como Triton.

Ejemplo. El gateway de C01 escucha en el 8080; Triton, en el 8000 (HTTP), el 8001 (gRPC) y el 8002 (métricas). uvicorn, si no le dices otro, usa el 8000.

Ver en el glosario →

SocketsocketLo que un proceso le pide al sistema operativo para hablar por la red: una puerta por donde entran y salen bytes, que el programa usa como un archivo abierto.Más

Se crea y se usa con syscalls: socket lo crea, bind lo apunta en una IP y un puerto, listen lo pone a esperar, accept acepta una conexión y connect se conecta a otro. El servidor hace bind, listen y accept; el cliente, connect. Cada conexión aceptada es otro socket. El kernel lo maneja igual que a un archivo abierto del proceso, así que cuenta en el límite de archivos abiertos. En Python está en el módulo socket; uvicorn y Triton los usan por dentro.

Ejemplo. socket.socket(socket.AF_INET, socket.SOCK_STREAM) pide un socket de IPv4 y TCP. bind(("0.0.0.0", 8080)) lo apunta en el puerto del gateway, en todas las interfaces.

Ver en el glosario →

localhostlocalhost · loopbackEl nombre de la máquina misma: 127.0.0.1 en IPv4 y ::1 en IPv6. Lo que se manda ahí no sale a la red; el sistema lo devuelve por dentro.Más

Viaja por una interfaz de mentiras, la de loopback, que solo alcanzan los programas de la misma máquina. Un servidor que escucha en 127.0.0.1 solo atiende a esos programas; uno que escucha en 0.0.0.0 atiende en todas las interfaces. Un contenedor tiene su propio namespace de red y, con él, su propio localhost: si un servidor escucha en 127.0.0.1 dentro del contenedor, lo que llega de afuera por su interfaz de red no encuentra a nadie y se rechaza. Los contenedores de un mismo pod de Kubernetes sí comparten localhost.

Analogía. Dejarte una nota a ti mismo en el refri: no pasa por el correo. Se rompe con los contenedores, donde cada uno tiene su propio refri.

Ejemplo. uvicorn arranca por omisión en 127.0.0.1:8000. En tu laptop está bien; dentro de un contenedor nadie de afuera le llega. Por eso el gateway de C01 arranca con --host 0.0.0.0 --port 8080.

Ver en el glosario →

ClienteclientEn una conexión por la red, el programa que la abre y pide algo. El otro lado, el que estaba esperando, es el servidor.Más

El cliente hace connect a la IP y al puerto de un servidor; el kernel le presta un puerto efímero para que la respuesta tenga a dónde volver. Ser cliente o servidor es un papel en cada conexión, no un tipo de máquina: el mismo programa puede ser las dos cosas en conexiones distintas. Como el cliente abre la conexión, es él quien paga el handshake, y por eso le conviene reusar conexiones.

Ejemplo. En C01, la app de Ana es cliente del backend; el backend, cliente del ALB; el gateway es servidor para el ALB y cliente de Triton.

Ver en el glosario →

TCPTransmission Control ProtocolEl protocolo que convierte los paquetes sueltos de la red en una conexión confiable entre dos programas: los bytes llegan completos, sin repetirse y en orden. Lo usan HTTP y casi todo lo que no puede perderse.Más

Numera cada byte (número de secuencia), el que recibe acusa recibo (ACK) y lo que no se acusa a tiempo se reenvía. Antes de mandar datos hace un handshake de tres pasos que cuesta 1 RTT. Además cuida no saturar la red: empieza mandando poco (arranque lento, con una ventana de ≈ 10 paquetes) y duplica en cada RTT, y si se pierde un paquete, baja. Como entrega en orden, un paquete perdido detiene a los que vienen detrás. Su contraparte sin conexión es UDP.

Analogía. Mandar un libro por correo en hojas sueltas numeradas, y que el que lo recibe te avise qué hojas ya tiene: las que no confirma, las vuelves a mandar. Se rompe en que el correo no se pone más lento cuando hay tráfico; TCP sí frena a propósito.

Ejemplo. El JPEG de Ana, del celular al backend y del backend a C01, y el tensor de 602 KB hacia Triton viajan por TCP. Una conexión nueva a 60 ms de RTT tarda 120 ms en traer la primera respuesta; una ya abierta, 60.

Ver en el glosario →

UDPUser Datagram ProtocolEl protocolo que lleva cada paquete al programa correcto, con su puerto, y nada más: sin conexión, sin acuses, sin reenvíos y sin orden. Lo que se pierde, se pierde. Sirve cuando llegar tarde es peor que no llegar.Más

Su encabezado mide 8 bytes, contra 20 o más de TCP, y no hace handshake. Lo usan la voz y las videollamadas (un pedazo reenviado llegaría cuando ya no sirve), los juegos en línea, el DNS (una pregunta y su respuesta caben en un paquete) y QUIC, el protocolo de HTTP/3, que hace sus propios acuses y reenvíos encima de UDP para evitar los problemas de TCP.

Ejemplo. En una videollamada, un pedazo de voz perdido se tapa y la llamada sigue; con TCP, toda la voz esperaría a que llegara el reenvío.

Ver en el glosario →

Handshakethree-way handshakeEl saludo de tres mensajes con el que TCP abre una conexión: SYN, SYN-ACK y ACK, que equivalen a «¿hablamos?», «sí, ¿y tú?» y «sí». Cuesta una ida y vuelta completa (1 RTT) antes de que viaje el primer byte de datos.Más

El cliente manda SYN con su número inicial; el servidor contesta SYN-ACK con el suyo; el cliente acusa con ACK y, en ese momento, ya puede mandar la request. Por eso una request por una conexión nueva paga 2 RTT en vez de 1, y 3 si además lleva TLS, que tiene su propio saludo. Si el primer SYN se pierde, el cliente espera ≈ 1 s antes de reenviarlo. Para no pagarlo en cada request, las conexiones se reusan (keep-alive, pool de conexiones).

Analogía. «¿Me oyes?» — «Sí, ¿y tú a mí?» — «Sí.» Hasta ahí no se ha dicho nada, pero los dos saben que el otro escucha. Se rompe en que dos personas pueden hablar encimadas desde el principio; TCP no manda datos hasta terminar el saludo.

Ejemplo. A 60 ms de RTT: por una conexión nueva, la respuesta llega a los 120 ms; con TLS, a los 180; por una ya abierta, a los 60.

Ver en el glosario →

RTTround-trip timeLo que tarda un paquete en ir de una máquina a otra más lo que tarda la respuesta en volver. Es la unidad con la que se cuenta lo que la red le cobra a una conversación.Más

Tiene un piso físico: la luz en la fibra recorre ≈ 200 km por milisegundo, así que cada 100 km de distancia suman ≥ 1 ms de RTT. Las rutas reales son más largas que la línea recta y cada router suma un poco. Órdenes de magnitud: decenas de microsegundos por localhost, menos de 1 ms dentro de una zona de la nube, ≈ 1 a 2 ms entre zonas, ≈ 50 ms de la Ciudad de México a Virginia. Más ancho de banda no lo baja: solo acercarse o hacer menos idas y vueltas. El handshake cuesta 1 RTT y cada request otro.

Analogía. El tiempo entre que gritas en un cañón y oyes el eco. Se rompe en que el eco solo depende de la distancia; el RTT también de los routers y de las filas en el camino.

Ejemplo. De la Ciudad de México a Virginia hay ≈ 3,012 km: 2 × 3,012 ÷ 200 ≈ 30 ms de RTT como mínimo. El «ping» de un videojuego es su RTT.

Ver en el glosario →

DNSDomain Name SystemEl directorio de internet que traduce nombres en direcciones IP: le preguntas por api.example.com y te contesta 203.0.113.10. Cada respuesta trae su TTL, el tiempo que se puede guardar.Más

La información está repartida en un árbol: los servidores raíz saben quién lleva cada terminación (.com, .mx), los de cada terminación saben quién manda en cada nombre, y el servidor autoritativo tiene la respuesta oficial. Tu programa le pregunta a un resolver, que hace el recorrido y guarda las respuestas en caché lo que diga su TTL. Las preguntas suelen ir por UDP al puerto 53. Kubernetes tiene su propio DNS, que da nombres fijos a los Services: el de Triton en C01 es triton.classifier.svc.cluster.local. Si el DNS falla, nadie encuentra a nadie, aunque las máquinas estén encendidas.

Analogía. Los contactos de tu celular: buscas «Mamá» y el teléfono marca el número. Se rompe en que tus contactos los cambias tú al instante; en el DNS, quien guardó el número viejo lo sigue usando hasta que venza su TTL.

Ejemplo. El gateway de C01 tiene en su configuración TRITON_URL=triton.classifier.svc.cluster.local:8000: un nombre y un puerto, nunca la IP de un pod, que cambia con cada reinicio.

Ver en el glosario →

TTLtime to liveEn el DNS, los segundos que una respuesta se puede guardar en caché antes de volver a preguntar. Uno corto hace que los cambios se noten rápido; uno largo ahorra consultas.Más

Lo decide el dueño del nombre, en su servidor autoritativo, y viaja con cada respuesta del DNS. Valores comunes van de 60 s a un día. Mientras no venza, quien guardó la respuesta no se entera de cambios: si un servicio cambia de IP, sus clientes siguen llamando a la vieja hasta que venza el TTL. Por eso, antes de mudar un servicio, se baja con días de anticipación. (En los paquetes de IP existe otro TTL, con el mismo nombre: un contador de saltos que evita que un paquete dé vueltas para siempre.)

Ejemplo. Con un TTL de 300 s, un cambio de IP tarda hasta 5 minutos en llegar a todos; con 86,400 s, hasta 24 horas.

Ver en el glosario →

Capas de rednetwork layers · L2, L3, L4, L7La manera de repartir el trabajo de la red en pisos, donde cada protocolo responde una sola pregunta: el enlace llega al siguiente aparato (L2), IP a la máquina (L3), TCP o UDP al programa (L4) y HTTP dice qué se pide (L7).Más

Cada capa usa la de abajo sin saber cómo funciona, y envuelve lo que le da la de arriba en su propio encabezado, como sobres dentro de sobres: HTTP dentro de TCP, dentro de IP, dentro de Ethernet o Wi-Fi. Los números vienen de un modelo de siete capas, el OSI (internet se diseñó con uno de cuatro, el de TCP/IP, con las mismas capas de arriba); en el trabajo se usan sobre todo L3, L4 y L7. Importan porque lo que ve un aparato depende de su capa: un router lee IPs; un balanceador de capa 4 ve IPs y puertos y reparte conexiones; uno de capa 7 abre HTTP y reparte requests.

Ejemplo. Un paquete de 1,500 bytes del gateway a Triton lleva 20 bytes de IP, 20 de TCP y 1,460 de datos; el primero, además, el encabezado de HTTP con POST /v2/models/classifier/infer. El Service de Kubernetes reparte en L4: ve conexiones, no requests.

Ver en el glosario →

14

Chequeo

Esencial

Check

Intenta responder en tu cabeza antes de abrir cada respuesta.

  1. 1¿Qué decide la IP y qué decide el puerto?Ver respuesta

    La IP, a qué máquina va el paquete; el puerto, a qué programa de esa máquina. El gateway de C01 escucha en el 8080 de la IP de su pod.

  2. 2¿Por qué el original de la foto de Ana, de 3 MB, viajaría en ≈ 2,055 paquetes y no de una pieza?Ver respuesta

    Un paquete lleva como máximo 1,500 bytes, 1,460 de datos. En pedazos, el cable se comparte y lo dañado se reenvía solo.

  3. 3¿Por qué un servidor que escucha en 127.0.0.1 dentro de un contenedor no recibe nada de afuera?Ver respuesta

    Porque 127.0.0.1 es el localhost del propio contenedor. Lo de afuera llega por otra interfaz, y ahí nadie escucha. Hay que escuchar en 0.0.0.0, todas las interfaces.

  4. 4¿Cuántas idas y vueltas paga una request por una conexión nueva con TLS, y por una ya abierta?Ver respuesta

    Tres: el handshake de TCP, el saludo de TLS y la request con su respuesta. Por una ya abierta, una. A 60 ms de RTT, 180 ms contra 60.

  5. 5¿Cuándo conviene UDP en vez de TCP?Ver respuesta

    Cuando llegar tarde es peor que no llegar (voz, video en vivo, juegos) o cuando el mensaje cabe en un paquete y se puede volver a preguntar (DNS). QUIC usa UDP y hace él mismo lo que hacía TCP.

  6. 6¿Para qué sirve el TTL de una respuesta de DNS, y qué pasa si es muy largo?Ver respuesta

    Dice cuántos segundos se puede guardar la respuesta. Si el nombre cambia de IP, quien la guardó sigue usando la vieja hasta que venza: con un TTL de un día, hasta 24 horas.

  7. 7Un balanceador de capa 4 y uno de capa 7, ¿qué ve cada uno?Ver respuesta

    El de capa 4 ve IPs y puertos: reparte conexiones. El de capa 7 abre HTTP y ve cada request, con su ruta y sus encabezados. El Service de Kubernetes reparte en capa 4.

Sigue · 22HTTP: requests, respuestas y códigosLa red y la web Léelo en la RondaM02 · Patrones de inferenciaLo que acabas de leer, con el ojo del entrevistador. ← 20 · Hacer varias cosas a la vez: async, event loop y GIL