🧠FFVAcademy
🔄

HTTP/1.1, /2, /3: multiplexing, HPACK, server push

15 min de leitura·+75 XP

Cada versão do HTTP foi criada para resolver gargalos específicos da anterior. HTTP/1.1 adicionou keep-alive mas serializou requests. HTTP/2 trouxe multiplexing real mas herdou o HoL blocking do TCP. HTTP/3 resolveu isso mudando o protocolo de transporte.

Evolução do HTTP: o que mudou em cada versão

CaracterísticaHTTP/1.0HTTP/1.1HTTP/2HTTP/3
Conexões por origem1 por request6 (keep-alive)1 (mux)1 (QUIC)
MultiplexingNãoPipelining (defeituoso)Sim (streams)Sim (QUIC streams)
Header compressionNãoNãoHPACKQPACK
HoL blockingSeveroModeradoParcial (TCP)Não
TransporteTCPTCPTCP+TLSQUIC (UDP+TLS)
Server pushNãoNãoSim (deprecado)Não
FormatoTextoTextoBinárioBinário

HTTP/1.1: keep-alive e pipelining

import socket

# HTTP/1.0: uma conexão TCP por request
# HTTP/1.1: Connection: keep-alive por padrão

# Request/Response HTTP/1.1 (formato texto):
request = (
    "GET / HTTP/1.1\r\n"
    "Host: example.com\r\n"
    "Connection: keep-alive\r\n"
    "Accept: text/html\r\n"
    "\r\n"
)

# Problema: requests serializados em uma conexão
# Request 1 → Response 1 → Request 2 → Response 2
# Latência: N_requests × RTT (sequencial)

# Workarounds da era HTTP/1.1:
# 1. Domain sharding: img1.example.com, img2.example.com
#    → cada domínio = 6 conexões paralelas
#    → overhead: múltiplos DNS lookups + TLS handshakes

# 2. Resource bundling (anti-pattern moderno):
#    concat all CSS → 1 request (mas invalida cache de tudo se 1 linha muda)
#    sprite images → 1 request para ícones
#    → HTTP/2 tornou isso desnecessário

# 3. Inline crítico: CSS/JS inline no HTML para recursos acima da dobra

# Pipelining: envia múltiplos requests sem esperar resposta
# Problema: responses DEVEM voltar em ordem (head-of-line blocking)
# Se request 1 demora 500ms e request 2 demora 10ms:
# request 2 aguarda request 1 terminar
# Bugs em proxies intermediários → browsers desabilitaram

# Verificar versão HTTP:
# curl -I --http1.1 https://example.com | head -1
# curl -I --http2   https://example.com | head -1
# curl -I --http3   https://cloudflare.com | head -1

HTTP/2: multiplexing e HPACK

# HTTP/2: protocolo binário, não texto
# Frame types: DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS,
#              PUSH_PROMISE, PING, GOAWAY, WINDOW_UPDATE, CONTINUATION

# Streams: cada request/response é um stream com ID (cliente: ímpar, servidor: par)
# Stream multiplexing: frames de streams diferentes intercalados na conexão

# HPACK — header compression:
# Tabela estática (61 entradas padrão):
# 1: :authority
# 2: :method GET        ← índice 2 em vez de "GET" (7 bytes)
# 3: :method POST
# 7: :scheme https
# 8: :status 200        ← índice 8 em vez de "200 OK" (6 bytes)

# Tabela dinâmica (headers vistos na conexão):
# Após ver "Authorization: Bearer abc123" pela 1ª vez → entra na tabela dinâmica
# Próximas requests: referência ao índice (1-2 bytes)

# Exemplo de economia com HPACK:
# Sem compressão:
headers_sem_compressao = {
    ":method": "GET",         # 14 bytes
    ":path": "/api/users",    # 20 bytes
    "host": "api.example.com",# 24 bytes
    "user-agent": "Mozilla/5.0 (compatible)", # 45 bytes
    "cookie": "session=abc123def456; pref=dark; _ga=GA1.2.123",  # 70 bytes
    "accept": "application/json", # 27 bytes
    "authorization": "Bearer eyJhbGciOiJSUzI1NiJ9...",  # 200+ bytes
}
# Total: ~400 bytes por request × 100 requests = 40 KB só de headers

# Com HPACK (após 1ª request):
# method, path, host → índices: ~3 bytes cada
# user-agent → índice da tabela dinâmica: 2 bytes
# cookie → índice: 2 bytes
# authorization → índice: 2 bytes
# Total: ~15 bytes por request × 100 requests = 1.5 KB (96% menor)

# HTTP/2 em Python com httpx:
import httpx

async def http2_example():
    async with httpx.AsyncClient(http2=True) as client:
        # Múltiplos requests simultâneos no mesmo TCP connection:
        resps = await asyncio.gather(
            client.get("https://httpbin.org/get?n=1"),
            client.get("https://httpbin.org/get?n=2"),
            client.get("https://httpbin.org/get?n=3"),
        )
        for r in resps:
            print(r.http_version, r.status_code)

# Server Push (HTTP/2, agora deprecado):
# Link: </style.css>; rel=preload; as=style   ← alternativa moderna (funciona!)
# HTTP 103 Early Hints — ainda melhor que push

HTTP/3: sobre QUIC

# HTTP/3 (RFC 9114): HTTP/2 sobre QUIC em vez de TCP+TLS
# QUIC = UDP + TLS 1.3 + multiplexing + flow control

# Diferenças HTTP/2 → HTTP/3:
# HoL blocking: eliminado (QUIC streams independentes)
# Header compression: HPACK → QPACK (adapta para out-of-order)
# Server push: removido por design
# Handshake: TCP+TLS 1.3 (2 RTT) → QUIC (1 RTT, 0 RTT para reconexão)
# Mobilidade: muda de IP sem reconectar (Connection ID)

# QPACK vs HPACK:
# HPACK: tabela dinâmica bloqueante (stream 0 deve ordenar updates)
# QPACK: tabela dinâmica não-bloqueante (encoder/decoder streams separados)
# Por quê: QUIC entrega frames out-of-order entre streams diferentes

# Verificar adoção HTTP/3:
# curl --http3 -I https://cloudflare.com 2>/dev/null | head -1
# curl --http3 -I https://youtube.com 2>/dev/null | head -1
# curl --http3 -I https://facebook.com 2>/dev/null | head -1

# Alt-Svc header: como servidores anunciam HTTP/3:
# Alt-Svc: h3=":443"; ma=86400
# Significa: "suporto HTTP/3 na porta 443, válido por 86400s"
# Browser usa HTTP/2 na 1ª visita, HTTP/3 nas seguintes

# Performance comparada (Cloudflare measurements):
# HTTP/1.1: 100% (baseline)
# HTTP/2:   60% de requests completados em 2s (vs 45% do 1.1)
# HTTP/3:   75% de requests completados em 2s
# Ganho maior em: redes móveis, alta latência, packet loss > 0.1%

# Adoção (2025): ~30% dos sites suportam HTTP/3
# CDNs (Cloudflare, Fastly, Akamai) habilitam automaticamente
# Nginx: compilar com --with-http_v3_module (ou pacote nginx-plus)
# Caddy: HTTP/3 por padrão (zero config)

# Verificar suporte sem curl:
# Chrome DevTools → Network → Protocol column
# https://www.http3check.net/
Resumo prático: HTTP/1.1 com keep-alive ainda roda em 70%+ da web interna. HTTP/2 é obrigatório em APIs públicas de alto tráfego — HPACK comprime headers 90%, multiplexing elimina domain sharding. HTTP/3 ganha em condições de rede adversas (mobile, alta latência, pacote loss). Alt-Svc anuncia suporte HTTP/3 automaticamente — CDNs como Cloudflare o habilitam por padrão. Server push: esqueça; use Link preload ou 103 Early Hints.
💡
Próximo: TLS 1.3 — handshake, como as chaves são negociadas, certificados, SNI e ALPN.
🧩

Quiz rápido

3 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito

Continue lendo