Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni

È molto interessante osservare il protocollo QUIC, quindi ci piace scrivere su di esso. Se le pubblicazioni precedenti su QUIC avevano un carattere più storico (locale, se vuoi) e una dimensione tecnica, oggi siamo felici di pubblicare una traduzione di altro tipo: parleremo dell'applicazione reale del protocollo nel 2019. E non stiamo parlando di una piccola infrastruttura, basata in un garage convenzionale, ma di Uber, che opera in quasi tutto il mondo. Come gli ingegneri dell'azienda hanno deciso di utilizzare QUIC in produzione, come hanno effettuato i test e cosa hanno osservato dopo il roll-out in produzione - sotto il tag.

Le immagini sono cliccabili. Buona lettura!

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni

Uber è su scala mondiale, precisamente in 600 città, in ognuna delle quali l'applicazione si basa completamente su internet wireless fornito da oltre 4500 operatori di telefonia mobile. Gli utenti si aspettano che l'app funzioni non solo rapidamente, ma in tempo reale: per garantire ciò, l'app di Uber ha bisogno di basse latenze e di una connessione molto affidabile. Purtroppo, il stack HTTP/2 si comporta male in reti wireless dinamiche e soggette a perdite. Abbiamo capito che in questo caso le basse prestazioni sono direttamente correlate alle implementazioni di TCP nei kernel dei sistemi operativi.

Per risolvere il problema, abbiamo applicato QUIC, un protocollo moderno con multiplexing dei canali, che ci offre un maggiore controllo sulle prestazioni del protocollo di trasporto. Attualmente, il gruppo di lavoro IETF sta standardizzando QUIC come HTTP/3.

Dopo test approfonditi, siamo giunti alla conclusione che l'implementazione di QUIC nella nostra applicazione ridurrà le latenze "tail" rispetto a TCP. Abbiamo osservato una riduzione compresa tra il 10% e il 30% per il traffico HTTPS, usando come esempio le applicazioni per autisti e passeggeri. Inoltre, QUIC ci ha fornito un controllo end-to-end sui pacchetti degli utenti.

In questo articolo condividiamo l'esperienza di ottimizzazione di TCP per le applicazioni di Uber utilizzando uno stack che supporta QUIC.

L'ultima parola della tecnologia: TCP

Oggi TCP è il protocollo di trasporto più utilizzato per la consegna del traffico HTTPS su Internet. TCP garantisce un flusso di byte affidabile, gestendo così il sovraccarico di rete e le perdite a livello di collegamento. L'ampio utilizzo di TCP per il traffico HTTPS è giustificato dalla sua onnipresenza (quasi ogni sistema operativo contiene TCP), dalla disponibilità su gran parte dell'infrastruttura (ad esempio, su bilanciatori di carico, proxy HTTPS e CDN) e dalla funzionalità "out-of-the-box", che è disponibile per la maggior parte delle piattaforme e delle reti.

La maggior parte degli utenti utilizza la nostra applicazione in movimento, e i ritardi "tail" di TCP sono stati lontani dai requisiti del nostro traffico HTTPS in tempo reale. In parole semplici, gli utenti di tutto il mondo si sono trovati di fronte a questa situazione – la Figura 1 mostra i ritardi nelle grandi città:

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 1. L'entità dei ritardi "tail" varia nelle principali città in cui è presente Uber.

Nonostante i ritardi nelle reti indiane e brasiliane fossero maggiori rispetto a quelli degli Stati Uniti e del Regno Unito, i ritardi tail erano significativamente più elevati rispetto ai ritardi medi. Ed è così anche per Stati Uniti e Regno Unito.

Prestazioni di TCP su rete wireless

TCP è stato progettato per reti cablate, cioè con un focus su collegamenti facilmente prevedibili. Tuttavia, le reti wireless hanno le loro peculiarità e difficoltà. In primo luogo, le reti wireless sono sensibili alle perdite dovute a interferenze e attenuazione del segnale. Ad esempio, le reti Wi-Fi sono sensibili a microonde, Bluetooth e altre onde radio. Le reti cellulari soffrono della perdita di segnale (perdita di percorso) a causa di riflessione/assorbimento del segnale da parte di oggetti e strutture, nonché a causa di interferenze da torri di telefonia mobile . Questo porta a ritardi round-trip (RTT) più significativi (da 4 a 10 volte) e variabilità rispetto a una connessione cablata.Per combattere le fluttuazioni nella larghezza di banda e le perdite, le reti cellulari utilizzano normalmente buffer ampi per gestire i picchi di traffico. Questo può portare a eccessiva latenza, il che significa ritardi maggiori. Spesso TCP interpreta tale latenza come una perdita a causa dell'aumento del timeout, quindi TCP tende a effettuare ritrasmissioni e a riempire il buffer. Questo problema è noto come eccessivo buffering di rete, espansione del buffer ), e rappresenta un

problema molto serio. bufferbloat (Problema molto serio.Problema molto serio. Problema molto serio. internet moderno.

Infine, le prestazioni della rete mobile variano a seconda dell'operatore, della regione e dell'orario. Nella Figura 2 abbiamo raccolto i ritardi mediani del traffico HTTPS per le celle in un raggio di 2 chilometri. I dati sono stati raccolti per i due principali operatori di telecomunicazioni a Delhi, India. Come si può notare, le prestazioni variano da una cella all'altra. Inoltre, le prestazioni di un operatore differiscono da quelle di un altro. Fattori come i modelli di accesso alla rete in base a tempo e posizione, la mobilità degli utenti e l'infrastruttura di rete che tiene conto della densità delle torri e del rapporto tra i tipi di rete (LTE, 3G, ecc.) influiscono su questo.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 2. Ritardi nel contesto di un raggio di 2 chilometri. Delhi, India.

Inoltre, le prestazioni delle reti mobili cambiano nel tempo. Nella Figura 3 è mostrato il ritardo mediano nei giorni della settimana. Abbiamo anche osservato differenze in una scala più ridotta – in un singolo giorno e ora.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 3. I ritardi di coda possono variare significativamente in giorni diversi, ma per lo stesso operatore.

Tutto quanto sopra porta alla conclusione che le prestazioni di TCP sono inefficaci nelle reti wireless. Tuttavia, prima di cercare alternative a TCP, volevamo sviluppare una comprensione accurata sui seguenti punti:

  • TCP è il principale colpevole dei ritardi di coda nelle nostre applicazioni?
  • Le reti moderne presentano ritardi circolari significativi e variabili (RTT)?
  • Qual è l'impatto di RTT e delle perdite sulle prestazioni di TCP?

Analisi delle prestazioni di TCP

Per capire come abbiamo analizzato le prestazioni di TCP, diamo un rapido sguardo a come TCP trasmette i dati dal mittente al destinatario. All'inizio, il mittente stabilisce una connessione TCP eseguendo un 'handshake' a tre vie. handshake: il mittente invia un pacchetto SYN, attende un pacchetto SYN-ACK dal destinatario e poi invia un pacchetto ACK. Due passaggi supplementari sono necessari per stabilire la connessione TCP. Il destinatario conferma la ricezione di ciascun pacchetto (ACK) per garantire una consegna affidabile.

Se un pacchetto o un ACK viene perso, il mittente effettua una ritrasmissione dopo un timeout (RTO, retransmission timeout). L'RTO viene calcolato dinamicamente sulla base di vari fattori, ad esempio, sul ritardo RTT previsto tra il mittente e il destinatario.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 4. Lo scambio di pacchetti tramite TCP/TLS include meccanismi di ritrasmissione.

Per determinare come TCP funzionasse nelle nostre applicazioni, abbiamo monitorato i pacchetti TCP con tcpdump per una settimana sul traffico in produzione, proveniente dai server di frontiera indiani. Abbiamo poi analizzato le connessioni TCP con tcptrace. Inoltre, abbiamo creato un'app Android che invia traffico emulato a un server di test, imitandone il traffico reale il più possibile. Gli smartphone con questa app sono stati distribuiti a diversi dipendenti, che hanno raccolto i log per diversi giorni.

I risultati di entrambi gli esperimenti sono stati coerenti tra loro. Abbiamo osservato ritardi RTT elevati; i valori di coda erano quasi 6 volte superiori alla mediana; la media dei ritardi – oltre 1 secondo. Molte connessioni avevano perdite, costringendo TCP a ritrasmettere il 3,5% di tutti i pacchetti. Nelle aree sovraccariche, come aeroporti e stazioni, abbiamo registrato perdite del 7%. Questi risultati mettono in discussione l'opinione comune che gli schemi di ritrasmissione avanzati riducano significativamente le perdite a livello di trasporto. Di seguito sono riportati i risultati dei test dall'app "simulatore":

Metriche di rete
Valori

RTT, millisecondi [50%, 75%, 95%, 99%]
[350, 425, 725, 2300]

Deviazione RTT, secondi
In media ~1,2 s

Perdita dei pacchetti in connessioni instabili
In media ~3,5% (7% in aree sovraccariche)

In quasi la metà di queste connessioni c'era almeno una perdita di pacchetti, principalmente si trattava di pacchetti SYN e SYN-ACK. La maggior parte delle implementazioni TCP utilizza un valore RTO di 1 secondo per i pacchetti SYN, che aumenta esponenzialmente in caso di ulteriori perdite. I tempi di caricamento delle applicazioni possono aumentare perché TCP richiede più tempo per stabilire le connessioni.

Per quanto riguarda i pacchetti di dati, i valori elevati di RTO riducono notevolmente l'utilizzo utile della rete in presenza di perdite temporanee nelle reti wireless. Abbiamo scoperto che il tempo medio di ritrasmissione è di circa 1 secondo, con un ritardo di coda di quasi 30 secondi. Questi elevati ritardi a livello di TCP causavano timeout HTTPS e richieste ripetute, aumentando ulteriormente il ritardo e l'inefficienza della rete.

Mentre il 75° percentile dei RTT misurati era intorno ai 425 ms, il 75° percentile per TCP era quasi di 3 secondi. Questo suggerisce che le perdite costringevano TCP a effettuare da 7 a 10 passaggi per trasmettere con successo i dati. Ciò potrebbe essere il risultato di un calcolo inefficace dell'RTO, dell'incapacità di TCP di rispondere rapidamente alle perdite. degli ultimi pacchetti nella finestra e dell'inefficienza dell'algoritmo di controllo della congestione che non distingue tra perdite wireless e perdite dovute a congestione di rete. Di seguito sono riportati i risultati dei test di perdita TCP:

Statistiche sulle perdite di pacchetti TCP
Valore

Percentuale di connessioni con almeno 1 perdita di pacchetto
45%

Percentuale di connessioni con perdite durante l'instaurazione della connessione
30%

Percentuale di connessioni con perdite durante lo scambio di dati
76%

Distribuzione dei ritardi nella ritrasmissione, secondi [50%, 75%, 95%, 99%]
[1, 2.8, 15, 28]

Distribuzione del numero di ritrasmissioni per un pacchetto o segmento TCP
[1,3,6,7]

Applicazione di QUIC

Originariamente progettato da Google, QUIC è un protocollo di trasporto moderno e multi-thread che funziona sopra UDP. Attualmente, QUIC è in fase di standardizzazione (abbiamo già accennato che esistono fondamentalmente due versioni di QUIC, i curiosi possono seguire il link – nota del traduttore). Come mostrato nella Figura 5, QUIC si colloca sotto HTTP/3 (in effetti, HTTP/2 su QUIC è ciò che è HTTP/3, attualmente in fase di intensa standardizzazione). Sostituisce parzialmente i livelli di HTTPS e TCP, utilizzando UDP per la formazione dei pacchetti. QUIC supporta solo la trasmissione sicura dei dati, poiché TLS è completamente integrato in QUIC.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 5: QUIC funziona sotto HTTP/3, sostituendo TLS, che precedentemente funzionava sotto HTTP/2.

Di seguito riportiamo i motivi che ci hanno convinto a utilizzare QUIC per potenziare TCP:

  • Connessione 0-RTT. QUIC consente il riutilizzo delle autorizzazioni da connessioni precedenti, riducendo il numero di handshake di sicurezza. In futuro, TLS1.3 supporterà 0-RTT, tuttavia, l'handshake TCP a tre vie sarà comunque obbligatorio.
  • superamento del blocco HoL. HTTP/2 utilizza una singola connessione TCP per ogni client per migliorare le prestazioni, ma questo può portare al blocco HoL (head-of-line). QUIC semplifica il multiplexing e consegna le richieste all'applicazione in modo indipendente l'una dall'altra.
  • gestione della congestione. QUIC si trova a livello applicativo, consentendo di aggiornare più facilmente l'algoritmo di trasporto principale che gestisce l'invio in base ai parametri di rete (quantità di perdite o RTT). La maggior parte delle implementazioni TCP utilizza l'algoritmo CUBIC, che non è ottimale per il traffico sensibile ai ritardi. Algoritmi recentemente sviluppati come BBRmodellano con maggiore precisione la rete e ottimizzano i ritardi. QUIC consente l'uso di BBR e l'aggiornamento di questo algoritmo man mano che si perfeziona.
  • il recupero delle perdite. QUIC provoca due TLP (tail loss probe) prima che si attivi il RTO – anche quando le perdite sono molto evidenti. Questo differisce dalle implementazioni TCP. TLP ritrasmette principalmente l'ultimo pacchetto (o uno nuovo, se disponibile), per avviare un rapido recupero. La gestione dei ritardi finali è particolarmente utile per come Uber interagisce con la rete, specialmente per trasferimenti di dati brevi, sporadici e sensibili ai ritardi.
  • ACK ottimizzato. Poiché ogni pacchetto ha un numero di sequenza unico, non si pone il problema della differenziazione dei pacchetti durante la loro ritrasmissione. I pacchetti ACK contengono anche il tempo necessario per elaborare il pacchetto e generare l'ACK dal lato client. Queste caratteristiche garantiscono che QUIC calcoli con maggiore precisione il RTT. L'ACK in QUIC supporta fino a 256 intervalli NACK, aiutando il mittente a essere più resistente alla riorganizzazione dei pacchetti e a utilizzare meno byte nel processo. L'ACK selettivo (SACK) in TCP non risolve questo problema in tutti i casi.
  • migrazione della connessione. Le connessioni QUIC vengono identificate mediante un ID a 64 bit, quindi se il client cambia indirizzi IP, è possibile continuare a utilizzare l'ID della vecchia connessione sul nuovo indirizzo IP, senza interruzioni. Questa è una pratica molto comune per le applicazioni mobili quando l'utente passa tra connessioni Wi-Fi e cellulari.

Alternative a QUIC

Abbiamo esaminato approcci alternativi per affrontare il problema prima di scegliere QUIC.

Per prima cosa abbiamo provato a implementare i TPC PoPs (Points of Presence) per terminare le connessioni TCP più vicino agli utenti. Fondamentalmente, i PoPs terminano la connessione TCP con il dispositivo mobile più vicino alla rete cellulare e fanno da proxy per il traffico verso l'infrastruttura originale. Terminando il TCP più vicino, possiamo potenzialmente ridurre il RTT e assicurarci che il TCP risponda in modo più attivo al dinamico ambiente wireless. Tuttavia, i nostri esperimenti hanno mostrato che, per la maggior parte, il RTT e le perdite provengono dalle reti cellulari e l'uso dei PoPs non offre un miglioramento significativo delle prestazioni.

Abbiamo anche esaminato la regolazione dei parametri TCP. L'ottimizzazione dello stack TCP sui nostri server di confine eterogenei è stata difficile, poiché il TCP ha implementazioni incompatibili tra le diverse versioni dei sistemi operativi. È stata complicata sia la sua implementazione che la verifica di diverse configurazioni di rete. Regolare il TCP direttamente sui dispositivi mobili era impossibile a causa della mancanza di autorizzazioni. Ciò che è ancora più importante, caratteristiche come le connessioni 0-RTT e il miglioramento della previsione RTT sono cruciali per l'architettura del protocollo e quindi non è possibile ottenere un vantaggio significativo solo regolando il TCP.

Infine abbiamo valutato diversi protocolli basati su UDP che risolvono i problemi di streaming video - volevamo vedere se questi protocolli avrebbero potuto aiutarci nel nostro caso. Sfortunatamente, mancavano di molte impostazioni di sicurezza e richiedevano una connessione TCP aggiuntiva per i metadati e le informazioni di controllo.

Le nostre ricerche hanno dimostrato che QUIC è quasi l'unico protocollo in grado di affrontare il problema del traffico Internet, considerando sia la sicurezza che le prestazioni.

Integrazione di QUIC nella piattaforma

Per integrare con successo QUIC e migliorare le prestazioni dell'app in condizioni di scarsa connettività, abbiamo sostituito il vecchio stack (HTTP/2 sopra TLS/TCP) con il protocollo QUIC. Abbiamo utilizzato la libreria di rete Cronet da Progetti Chromium, che contiene la versione originale e di Google del protocollo – gQUIC. Questa implementazione è inoltre costantemente migliorata per seguire le ultime specifiche dell'IETF.

Per prima cosa abbiamo integrato Cronet nelle nostre applicazioni Android per aggiungere supporto a QUIC. L'integrazione è stata realizzata in modo da ridurre al minimo i costi di migrazione. Invece di sostituire completamente il vecchio stack di rete, che utilizzava la libreria OkHttp, abbiamo integrato Cronet ALL'INTERNO del framework OkHttp API. Rendendo l'integrazione in questo modo, abbiamo evitato modifiche alle nostre chiamate di rete (che utilizzano Retrofit) a livello di API.

Simile all'approccio per i dispositivi Android, abbiamo implementato Cronet nelle app Uber su iOS, intercettando il traffico HTTP dalle reti API, utilizzando NSURLProtocol. Questa astrazione fornita da iOS Foundation gestisce dati URL specifici del protocollo e garantisce che possiamo integrare Cronet nelle nostre app iOS senza costi significativi di migrazione.

Terminazione di QUIC sui bilanciatori di carico di Google Cloud

Sul lato backend, la terminazione di QUIC è garantita dall'infrastruttura di bilanciamento del carico di Google Cloud, che utilizza alt-svc Le intestazioni nelle risposte per supportare QUIC. In generale, il bilanciatore di carico aggiunge l'intestazione alt-svc a ogni richiesta HTTP e già essa valida il supporto di QUIC per il dominio. Quando il client Cronet riceve una risposta HTTP con tale intestazione, utilizza QUIC per le successive richieste HTTP a quel dominio. Non appena il bilanciatore termina QUIC, la nostra infrastruttura invia chiaramente questa azione tramite HTTP2/TCP ai nostri data center.

Prestazioni: risultati

Le prestazioni fornite sono la principale ragione della nostra ricerca del miglior protocollo. Per iniziare, abbiamo creato un banco di prova con un'emulazione di rete, per capire come si comporterà QUIC con diversi profili di rete. Per verificare il funzionamento di QUIC in reti reali, abbiamo condotto esperimenti viaggiando per Nuova Delhi, utilizzando traffico di rete emulato molto simile alle chiamate HTTP in un'app passeggero.

Esperimento 1

Inventario per l'esperimento:

  • dispositivi di test Android con stack OkHttp e Cronet, per assicurarci di inviare traffico HTTPS tramite TCP e QUIC rispettivamente;
  • server di emulazione basato su Java, che invia intestazioni HTTPS simili nelle risposte e sovraccarica i dispositivi client per ricevere richieste da essi;
  • proxy cloud fisicamente situati vicino all'India, per completare le connessioni TCP e QUIC. Mentre per completare TCP abbiamo utilizzato un proxy inverso su NGINX, è stato difficile trovare un proxy inverso open-source per QUIC. Abbiamo creato un proxy inverso per QUIC noi stessi, utilizzando lo stack QUIC di base da Chromium e hanno pubblicato lo abbiamo reso open-source nel Chromium.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioniIl protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 6. Il set di attrezzature per i test TCP vs QUIC consisteva in dispositivi Android con OkHttp e Cronet, proxy cloud per completare le connessioni e un server di emulazione.

Esperimento 2

Quando Google ha reso QUIC disponibile tramite Google Cloud Load Balancing, abbiamo utilizzato lo stesso inventario, ma con una modifica: invece di NGINX, abbiamo utilizzato i bilanciatori di carico di Google per completare le connessioni TCP e QUIC dai dispositivi, nonché per dirigere il traffico HTTPS verso il server di emulazione. I bilanciatori sono distribuiti in tutto il mondo, ma utilizzano il server PoP più vicino al dispositivo (grazie alla geolocalizzazione).

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 7. Nel secondo esperimento abbiamo voluto confrontare la latenza di completamento di TCP e QUIC: utilizzando Google Cloud e il nostro proxy cloud.

In conclusione, abbiamo fatto alcune rivelazioni:

  • La chiusura tramite PoP ha migliorato le prestazioni di TCP. Poiché i bilanciatori chiudono la connessione TCP più vicino agli utenti ed sono ottimizzati, ciò comporta RTT più brevi, migliorando le prestazioni di TCP. Anche se QUIC ne risente meno, ha comunque superato TCP in termini di riduzione delle latenze finali (del 10-30 percento).
  • le latenze finali sono influenzate da transiti di rete (hops). Sebbene il nostro proxy QUIC fosse più lontano dai dispositivi (con un ritardo di circa 50 ms in più) rispetto ai bilanciatori di Google, ha mostrato prestazioni simili: una riduzione delle latenze del 15% contro una riduzione del 20% nel 99° percentile per TCP. Questo indica che il passaggio nell'ultimo miglio è un collo di bottiglia nella rete.

Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioniIl protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 8. I risultati di due esperimenti mostrano che QUIC supera significativamente TCP.

Traffico di produzione

Ispirati dagli esperimenti, abbiamo implementato il supporto per QUIC nelle nostre applicazioni Android e iOS. Abbiamo condotto un test A/B per determinare l'impatto di QUIC nelle città in cui è presente Uber. In generale, abbiamo osservato una significativa riduzione delle latenze finali sia a livello regionale che tra gli operatori di rete e i tipi di rete.

Nei grafici sottostanti sono mostrai i miglioramenti percentuali delle latenze finali (95° e 99° percentili) per macroregioni e diversi tipi di rete – LTE, 3G, 2G.
Il protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioniIl protocollo QUIC in azione: comeUber lo ha implementato per ottimizzare le prestazioni
Figura 9. Nei test di produzione, QUIC ha superato TCP in termini di latenze.

Solo avanti

Probabilmente si tratta solo dell'inizio: il rilascio di QUIC in produzione ha offerto incredibili opportunità di migliorare le prestazioni delle applicazioni sia in reti stabili che instabili, inclusi:

Aumento della copertura

Analizzando le prestazioni del protocollo su traffico reale, abbiamo visto che circa l'80% delle sessioni ha utilizzato con successo QUIC per tutti richieste, mentre il 15% delle sessioni ha usato una combinazione di QUIC e TCP. Riteniamo che tale combinazione sia emersa perché la libreria Cronet torna a utilizzare TCP a causa di timeout, poiché non può distinguere tra reali fallimenti di UDP e cattive condizioni di rete. Attualmente stiamo cercando una soluzione a questo problema mentre lavoriamo all'implementazione successiva di QUIC.

Ottimizzazione di QUIC

Il traffico dalle applicazioni mobili è sensibile ai ritardi, ma non alla larghezza di banda. Inoltre, le nostre applicazioni vengono utilizzate principalmente nelle reti cellulari. Basandoci su esperimenti, i ritardi tail sono ancora elevati, anche nonostante l'uso di proxy per terminare TCP e QUIC vicino agli utenti. Stiamo attivamente cercando modi per migliorare la gestione del sovraccarico e aumentare l'efficienza degli algoritmi di recupero perdite QUIC.

Con questi e altri miglioramenti, pianifichiamo di migliorare l'esperienza dell'utente indipendentemente dalla rete e dalla regione, rendendo il trasporto dei pacchetti conveniente e fluido più accessibile in tutto il mondo.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster