Architettura a bassa latenza
Perché un'architettura a bassa latenza
La latenza bassa non è solo «media veloce», ma le code stabili (p95/p99) a carico reale. La strada per questo è il budget del ritardo, la disciplina delle code/retrai, la vicinanza dei dati e della cache, i protocolli/connettori corretti e il funzionamento rigoroso (limiti, osservabilità, degrado).
Obiettivi e budget di ritardo
1. Definisci SLO: «p95» 120 ms, p99 250 mc, errore 0. 3%».
2. Raccogliete il budget, il cliente edge la regione, i servizi di dello store, la risposta.
- Client-edge: 15 ms
- Regione Edge: 15 ms
- Gateway/L7: 10 mc
- Servizio aziendale: 40 ms
- Storage/cache: 25 ms
- Riserva/jitter: 15 ms
Metriche e code
Misura p50/p90/p95/p99, passante e su ogni hop.
Dividere la regione, il metodo, la versione del client, il tipo di rete (mobile/broadband), la dimensione di payload.
Differenziare tra la coda e l'ora di esecuzione (vedere Little's Law: L = ©· W).
Tecniche sensibili a tail: hedged sollests (raramente e con protezione), divieto di retrai a cascata.
Rete e protocolli
QUIC/HTTP/3: meno perdita mobile/roaming, multiplexing senza head-of-line.
TLS 1. 3 e 0-RTT (solo per richieste idempotate sicure).
DNS: TTL breve per percorsi dinamici, Anycast per POP.
TCP: 'TCP _ NODELAY' (cauto), disattivare gli extra «Nagle »/« Delayed ACK» dove giustificato; keep-alive e ripristino rapido delle connessioni.
gRPC/HTTP/2: multiplex, flow-control e impostazioni delle finestre evitare la compressione eccessiva sui piccoli payload.
Connessioni e pool
Separare i pool per dominio/destinazione (in modo che i vicini lenti non portino via le slot).
Warm-up/Keep-alive - Mantenere un numero costante di connettori caldi.
Connection coalescing (HTTP/2/3) и reuse.
Timeout: «connect», «TLS handshake», «sollest», «idle». Valori diversi su diversi hop.
Localizzazione dei dati e dei calcoli
Edge/Regione - Attenersi ai calcoli leggeri e leggeri all'utente (vedere «Edge-nodi e logica regionale»).
Read-locale/Write-global - Repliche di lettura, verità globale da scrivere.
Gerarchia cache: CDN/edge-cache, KV/Redis regionale, cache di servizio, locale in-pric.
Riscaldamento (warming) - Carica delle chiavi hot durante il lancio/ridimensionamento.
Stale-while-revalidate per i dati a basso contenuto.
Archivi e indici
Selezionare gli schemi di accesso O (1 )/O (logN); tenete gli indici stretti sotto frequenti richieste.
Hot-keys - Scendi per «hash (id)» o aggiungi «sale» per uniformità.
Batching in uscita in database/cash (fino a dimensioni ragionevoli) invece di decine di chiamate singole.
Per OLTP: transazioni più brevi possibile read-committed/snapshot invece di blocchi seriali.
Concorrenza e tecniche senza blocco
Prima eliminate le aspettative sulle code, poi ottimizzate la CPU.
Async I/O e driver non bloccanti; strutture lock-free, se del caso.
Evitare i mutex globali; granulari, CAS/versioning.
Pool di flusso - Fissa le quote per evitare di entrare in un contesto-maglie.
NUMA-consapevolezza - Allinea i flussi ai socket, allocatori locali.
JVM/GC e running (se applicabile)
Generazione di codice e allocazione: meno effetti laterali, meno pause GC.
Raccoglitori moderni (G1/ZGC/Shenandoah) con pause di destinazione; escapes e bail-in buffer.
Class/Data sharing, JIT warming, AOT/native-immagine per le funzioni di avvio-dipendenti.
Gli istogrammi di pausa GC sono inclusi nel budget complessivo di ritardo.
Code, backpressure, protezione da sovraccarico
Dimensioni delle code = piccole: lunghe code danno «bella p50» e uccidono p99.
Backpressure esplicita: rispondi più lentamente di quanto non risponda.
Adattative concertency: riduce la parallelità con l'aumento degli errori/latitanza (algoritmi VEGAS/gradiente, AIMD).
Circuito breaker: guasti rapidi per il degrado dell'upstream, bullkhead (aziende) per pool e risorse.
Rate limit: finestra scorrevole/token, priorità (user tier/critical-path).
Retrai, hejing e idempotenza
I retrai sono solo per gli errori transitori, con il jitter e il massimo dei tentativi.
Le operazioni Idempotent e Idempotency-Key sono obbligatorie per le ripetizioni.
Hedged sollests - Invia le riprese dopo la soglia (ad esempio p95 + 10 ms) e annulla sempre l'extra.
Non ritrarre mai all'interno di ogni strato senza coordinarsi.
Cache e riscaldamento
Il percorso caldo deve essere privo di rete in caso di carico standard (in-proc/LRU).
Negative cache a 10-60 s per non fottere le chiavi mancanti.
Riscaldamento di massa durante il lancio/skateboard: elenchi chiavi calde, read-ahead, background refresh.
Degrado e follback
Graceful Degradation: taglia i fili secondari mentre aumenta la latitanza (risposta meno dettagliata, disattivazione degli arricchimenti).
Soft timeouts: restituisci la risposta di base/kash invece di 5xx.
Fail-open/Fail-closed - Documentare chiaramente per ogni chiamata.
Osservabilità e profilassi
Tracking di distribuzione: span su ogni hop, sampling di coda (tail-based).
RED/USE метрики: Rate, Errors, Duration / Utilization, Saturation, Errors.
Top-N «lenti» ogni giorno.
Profilatori (alloc/cpu/lock) in vendita con overhead basso (eBPF/async-profiler/Flight Recorder).
Sintetica da diverse reti ASN e canali mobili.
Test delle prestazioni
Test Latency-SLO (p95/p99) con payload reali e variabilità.
Script Chaos: degrado DNS, aumento della perdita di pacchetti, ritardi TLS, store «lento».
Cold-start/scale-up - Misurare i primi minuti dopo il lancio quando la cache è vuota.
I pool di carico vengono suddivisi in script (non interferire con i test read/write).
Mini modelli
Criteri timeout/retrai (pseudo)
yaml timeouts:
connect: 100ms tls_handshake: 150ms request_p95_budget: 80ms retries:
max_attempts: 2 backoff: exp_jitter(10ms..60ms)
retry_on: [CONNECT_ERROR, TIMEOUT, 502, 503, 504]
hedging:
enabled: true threshold: p95 + 10ms cancel_extra_on_first_success: true circuit_breaker:
error_rate_threshold: 5%
p95_threshold_increase: 30%
half_open_after: 10s
Pool e bullhead's
yaml pools:
checkout:
max_conns: 256 per_host: 64 queue: 8 # small analytics queue:
max_conns: 64 queue: 4
Risposta con degrado
json
{
"status": "ok",
"profile": { "id": "u123", "name": "…"},
"recommendations": "degraded, "//disabled the heavy part
"served_from": "edge-cache",
"trace_id": "…"
}
Valigette di applicazione
iGaming/Finanza: autorizzazioni di pagamento <200 ms p95, limiti/bilanci - lettura da proiezioni regionali, voci idipotenti con versione.
Marketing/raccomandazioni: risposte <100 ms p95, cache flag su edge, modelli di precompilamento + regole veloci a caldo.
Client mobili: HTTP/3, reuse aggressive dei connettori, payload ridotti (Protobuf), timeout di protezione e cache offline.
Anti-pattern
Lunghe code davanti ai worker, «bella media» e p99.
Retrai a cascata su ogni strato senza coordinazione.
Mega cache globale senza disabilità o riscaldamento.
Timeout impari (ovunque «predefinito») - Code non controllate.
Un pool comune di connettori per tutto il traffico è un blocco head-of-line.
Logica pesante su edge con gli effetti stateful.
Telemetria di coda disattivata - «non vedete» p99.
Foglio di assegno di produzione
- C'è un bilancio di ritardo per gli hop e i timeout sotto.
- Sono abilitati HTTP/2/3, TLS 1. 3, pool di connettori e warm-up.
- La gerarchia della cache, l'elenco delle chiavi calde e le strategie di riscaldamento.
- Read-locale/Write-global e charding chiavi hot.
- Backpressure esplicito, piccole code, circuiti-breakers e bullkhead '.
- Retrai con jitter, idampotenza, hejing limitato.
- Tracking con etichette di regione/versione/client; monitoraggio p95/p99.
- Test perf con sintetica ASN/mobile, script cold-start e chaos.
- Procedure di degrado e folleback documentate.
- p95/p99 corrispondono a SLO a carico reale.
FAQ
Perché il p99 è più importante della media?
Perché gli utenti affrontano le code, non la media. Il p99 dice «quanto fa male».
Dovremmo accendere l'hedging ovunque?
No, no. È utile per le code rare nei percorsi critici e solo con limiti/idampotenza rigorosi.
Come ridurre la partenza fredda?
Riscaldamento della cache/connessioni, pre-compilazione/riscaldamento JIT, minimizzazione delle inizializzazioni lazy, pool warm.
Possiamo sconfiggere la rete?
Parte: HTTP/3, edge-POP, Anycast, payload compatti, connection reuse e timeout ragionevoli.
Totale
L'architettura a bassa latenza è un sistema di accordi e disciplina: budget dei ritardi, vicinanza dei dati, piccole code, prevedibili retrai, gerarchie della cache, protocolli corretti e spietata osservabilità delle code. Seguendo questi principi, si tiene p95/p99 a nastro senza sacrifici di stabilità e portafoglio.