Vantaggi per le prestazioni

Introduzione: cause e mitigazioni della latenza DNS

Man mano che le pagine web diventano più complesse, facendo riferimento a risorse di numerosi domini, le ricerche DNS possono diventare un collo di bottiglia significativo nell'esperienza di navigazione. Ogni volta che un client deve eseguire una query su un resolver DNS sulla rete, la latenza introdotta può essere significativa, a seconda della vicinanza e del numero di server dei nomi che il resolver deve eseguire (più di due sono rari, ma possono capitare). Ad esempio, il seguente screenshot mostra i tempi riportati dallo strumento di misurazione delle prestazioni web Page Speed. Ogni barra rappresenta una risorsa a cui si fa riferimento nella pagina; i segmenti neri indicano le ricerche DNS. In questa pagina vengono effettuate 13 ricerche nei primi 11 secondi in cui la pagina viene caricata. Anche se molte ricerche vengono eseguite in parallelo, lo screenshot mostra che sono richiesti 5 tempi di ricerca seriale, che rappresentano diversi secondi del tempo di caricamento della pagina totale di 11 secondi.

La latenza DNS ha due componenti:

  • Latenza tra il client (utente) e il server di risoluzione DNS. Nella maggior parte dei casi ciò è in gran parte dovuto ai soliti vincoli in termini di tempo di round trip (RTT) nei sistemi in rete: distanza geografica tra le macchine client e server, congestione della rete, perdita di pacchetti e lunghi ritardi di ritrasmissione (in media un secondo), server sovraccaricati, attacchi denial of service e così via.
  • Latenza tra la risoluzione dei server e altri server dei nomi. Questa fonte di latenza è causata principalmente dai seguenti fattori:
    • Errori della cache. Se una risposta non può essere fornita dalla cache di un resolver, ma richiede l'esecuzione di query ricorsive su altri server dei nomi, la latenza di rete aggiunta è considerevole, soprattutto se i server autorevoli sono geograficamente remoti.
    • Provisioning insufficiente. Se i resolver DNS sono sovraccaricati, devono mettere in coda le richieste e le risposte di risoluzione DNS e potrebbero iniziare a eliminare e ritrasmettere i pacchetti.
    • Traffico dannoso. Anche se un servizio DNS è sottoposto a overprovisioning, il traffico DoS può sovraccaricare i server. Analogamente, gli attacchi in stile Kaminsky possono comportare l'inondazione di resolver, con query che garantiscono il bypass della cache e richiedono richieste di risoluzione in uscita.

Riteniamo che il fattore di fallimento della cache sia la causa principale della latenza DNS e ne parliamo più nel dettaglio di seguito.

Fallimenti della cache

Anche se un resolver dispone di abbondanti risorse locali, i ritardi fondamentali associati alla comunicazione con server dei nomi remoti sono difficili da evitare. In altre parole, supponendo che il provisioning del resolver sia sufficientemente valido in modo che gli hit della cache richiedano zero tempo sul lato server, i fallimenti della cache rimangono molto costosi in termini di latenza. Per gestire un errore, un resolver deve comunicare con almeno uno, ma spesso con due o più server dei nomi esterni. Utilizzando il web crawler Googlebot, abbiamo osservato un tempo di risoluzione medio di 130 ms per i server dei nomi che rispondono. Tuttavia, un 4-6% delle richieste si verifica semplicemente in timeout a causa della perdita di pacchetti UDP e dell'impossibilità di raggiungere i server. Se prendiamo in considerazione errori come perdita di pacchetti, server dei nomi non recapitabili, errori di configurazione DNS e così via, il tempo medio di risoluzione end-to-end effettivo è di 300-400 ms. Tuttavia, c'è una varianza elevata e una long tail.

Sebbene la percentuale di fallimenti della cache possa variare tra i server DNS, i fallimenti della cache sono fondamentalmente difficili da evitare per i seguenti motivi:

  • Dimensioni e crescita di internet. Molto semplicemente, con la crescita di internet, sia con l'aggiunta di nuovi utenti che di nuovi siti, la maggior parte dei contenuti è di interesse marginale. Sebbene alcuni siti (e di conseguenza i nomi DNS) siano molto popolari, la maggior parte interessa solo pochi utenti e gli accessi vengono eseguiti raramente; per questo motivo, la maggior parte delle richieste comporta fallimenti della cache.
  • Valori di durata (TTL) bassi. La tendenza verso valori TTL DNS più bassi significa che le risoluzioni richiedono ricerche più frequenti.
  • Isolamento della cache. Il deployment dei server DNS avviene in genere dietro bilanciatori del carico, che assegnano query a macchine diverse in modo casuale. In questo modo ogni singolo server mantiene una cache separata anziché poter riutilizzare le risoluzioni memorizzate nella cache da un pool condiviso.

Mitigazioni

In Google Public DNS, abbiamo implementato diversi approcci per accelerare i tempi di ricerca DNS. Alcuni di questi approcci sono abbastanza standard, altri sono sperimentali:

Eseguire il provisioning adeguato dei cluster di gestione

I resolver DNS nella cache devono eseguire operazioni più costose rispetto ai server dei nomi autorevoli, poiché molte risposte non possono essere fornite dalla memoria; richiedono invece la comunicazione con altri server dei nomi e richiedono quindi un notevole input/output di rete. Inoltre, i resolver aperti sono estremamente vulnerabili ai tentativi di avvelenamento della cache, che aumentano la percentuale di fallimenti della cache (in modo specifico, gli attacchi inviano richieste di nomi falsi che non possono essere risolti dalla cache) e agli attacchi DoS, che aumentano il carico del traffico. Se il provisioning dei resolver non è stato adeguato e non è in grado di tenere il passo con il carico, questo può avere un impatto molto negativo sulle prestazioni. I pacchetti vengono ignorati e devono essere ritrasmessi, le richieste del server dei nomi devono essere messe in coda e così via. Tutti questi fattori contribuiscono a causare ritardi.

Pertanto, è importante che i resolver DNS eseguano il provisioning per input/output di volumi elevati. Ciò include la gestione di possibili attacchi DDoS, per i quali l'unica soluzione efficace è l'overprovisioning con molte macchine. Allo stesso tempo, tuttavia, è importante non ridurre la percentuale di successo della cache quando aggiungi macchine; ciò richiede l'implementazione di un criterio di bilanciamento del carico efficace, di cui parleremo di seguito.

Bilanciamento del carico per la memorizzazione nella cache condivisa

La scalabilità dell'infrastruttura del resolver mediante l'aggiunta di macchine può causare un effetto contrario e ridurre la percentuale di successo della cache se il bilanciamento del carico non viene eseguito correttamente. In un deployment tipico, più macchine si trovano dietro un bilanciatore del carico che distribuisce equamente il traffico a ogni macchina, utilizzando un algoritmo semplice come round robin. Il risultato è che ogni macchina mantiene la propria cache indipendente in modo che i contenuti memorizzati nella cache siano isolati tra le varie macchine. Se ogni query in entrata viene distribuita su una macchina casuale, a seconda della natura del traffico, la percentuale di fallimento della cache effettivo può essere aumentata proporzionalmente. Ad esempio, per i nomi con TTL lunghi che vengono interrogati ripetutamente, la percentuale di errori della cache può essere aumentata del numero di macchine nel cluster. (Per i nomi con TTL molto brevi, per cui viene eseguita una query molto raramente o che generano risposte non memorizzabili nella cache (0 TTL ed errori), la percentuale di fallimento della cache non viene influenzata dall'aggiunta di macchine.

Per aumentare la percentuale di successo per i nomi memorizzabili nella cache, è importante bilanciare il carico dei server in modo che la cache non sia frammentata. In Google Public DNS, abbiamo due livelli di memorizzazione nella cache. In un pool di macchine, molto vicino all'utente, una piccola cache per macchina contiene i nomi più noti. Se non è possibile soddisfare una query da questa cache, viene inviata a un altro pool di macchine che partizionano la cache in base ai nomi. Per questa cache di secondo livello, tutte le query con lo stesso nome vengono inviate alla stessa macchina, dove il nome è memorizzato nella cache o non lo è.

Distribuzione di cluster di servizio per un'ampia copertura geografica

Per i resolver chiusi, questo non è davvero un problema. Per i resolver aperti, quanto più vicini sono i server agli utenti, minore sarà la latenza che vedranno sul lato client. Inoltre, avere una copertura geografica sufficiente può migliorare indirettamente la latenza end-to-end, poiché i server dei nomi in genere restituiscono risultati ottimizzati per la località del resolver DNS. Ciò significa che se un fornitore di contenuti ospita siti con mirroring in tutto il mondo, i server dei nomi di quel provider restituiranno l'indirizzo IP più vicino al resolver DNS.

Il DNS pubblico di Google è ospitato nei data center di tutto il mondo e utilizza il routing anycast per indirizzare gli utenti al data center geograficamente più vicino.

Inoltre, il DNS pubblico di Google supporta la subnet client EDNS (ECS), un'estensione di protocollo DNS che consente ai resolver di inoltrare la posizione del client ai server dei nomi, in grado di restituire risposte sensibili alla località ottimizzate in base all'indirizzo IP client effettivo, anziché all'indirizzo IP del resolver. Per informazioni dettagliate, leggi queste domande frequenti. Il DNS pubblico di Google rileva automaticamente i server dei nomi che supportano la subnet client EDNS.