🔄
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ística | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| Conexões por origem | 1 por request | 6 (keep-alive) | 1 (mux) | 1 (QUIC) |
| Multiplexing | Não | Pipelining (defeituoso) | Sim (streams) | Sim (QUIC streams) |
| Header compression | Não | Não | HPACK | QPACK |
| HoL blocking | Severo | Moderado | Parcial (TCP) | Não |
| Transporte | TCP | TCP | TCP+TLS | QUIC (UDP+TLS) |
| Server push | Não | Não | Sim (deprecado) | Não |
| Formato | Texto | Texto | Binário | Biná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 -1HTTP/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 pushHTTP/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