Da oltre 20 anni visualizziamo pagine web tramite il protocollo HTTP. La maggior parte degli utenti non si chiede nemmeno cosa sia e come funzioni. Altri sanno che sotto HTTP c'è TLS, e sotto questo TCP, seguito da IP e così via. E poi ci sono i dissententi, che ritengono che TCP sia obsoleto e desiderano qualcosa di più veloce, affidabile e sicuro. Tuttavia, nei loro tentativi di inventare un nuovo protocollo perfetto, sono tornati alle tecnologie degli anni '80 e cercano di costruire su di esse il loro meraviglioso nuovo mondo.

Un po' di storia: HTTP/1.1
Nel 1997, il protocollo di scambio di informazioni testuali HTTP versione 1.1 ha ottenuto il suo RFC. A quel tempo, il protocollo era già utilizzato dai browser da diversi anni, e il nuovo standard è rimasto in vigore per altri quindici. Il protocollo funzionava solo secondo il principio richiesta-risposta ed era destinato principalmente alla trasmissione di informazioni testuali.
L'HTTP è stato progettato per funzionare sopra il protocollo TCP, che garantisce la consegna affidabile dei pacchetti al destinatario. Il funzionamento del TCP si basa sull'instaurazione e sul mantenimento di una connessione sicura tra i punti finali e sulla suddivisione del traffico in segmenti. I segmenti hanno un numero sequenziale e una somma di controllo. Se uno dei segmenti non arriva o arriva con una somma di controllo errata, la trasmissione si fermerà finché non verrà ripristinato il segmento mancante.
In HTTP/1.0 la connessione TCP veniva chiusa dopo ogni richiesta. Questo era estremamente inefficiente, poiché l'instaurazione di una connessione TCP (3-Way-Handshake) non è un processo rapido. In HTTP/1.1 è stato introdotto un meccanismo di keep-alive, che consente di riutilizzare una connessione per più richieste. Tuttavia, poiché ciò può facilmente diventare un collo di bottiglia, in diverse implementazioni di HTTP/1.1 è consentita l'apertura di più connessioni TCP a un unico host. Ad esempio, in Chrome e nelle ultime versioni di Firefox, sono consentite fino a sei connessioni.

Il protocollo di crittografia doveva essere affidato anche ad altri protocolli, e per questo motivo il protocollo TLS ha iniziato ad essere utilizzato sopra TCP, garantendo una protezione adeguata dei dati, ma aumentando ulteriormente il tempo necessario per stabilire la connessione. Alla fine, il processo di handshake è diventato simile a questo:

Illustrazione di Cloudflare
Così HTTP/1.1 presentava una serie di problemi:
- Stabilire una connessione lenta.
- I dati vengono trasmessi in formato testo, il che significa che la trasmissione di immagini, video e altre informazioni non testuali è inefficace.
- Una connessione TCP viene utilizzata per una singola richiesta, il che significa che le altre richieste devono trovare un'altra connessione o attendere che la richiesta corrente la rilasci.
- Supporta solo il modello pull. Non c'è nulla nello standard riguardo al server-push.
- Le intestazioni vengono trasmesse in testo.
Se il server-push viene implementato in modo approssimativo utilizzando il protocollo WebSocket, le altre problematiche dovevano essere affrontate in maniera più radicale.
Un po' di modernità: HTTP/2
Nel 2012, Google ha iniziato a lavorare sul protocollo SPDY (pronunciato "spidi"). Questo protocollo era progettato per risolvere le principali problematiche di HTTP/1.1, mantenendo però la compatibilità all’indietro. Nel 2015, il gruppo di lavoro IETF ha presentato la specifica di HTTP/2, basata su SPDY. Ecco quali sono state le differenze in HTTP/2:
- Serializzazione binaria.
- Multiplexing di più richieste HTTP in una sola connessione TCP.
- Server push integrato (senza WebSocket).
Il protocollo ha rappresentato un grande passo avanti. Ha notevolmente e non richiede la creazione di più connessioni TCP: tutte le richieste verso un unico host vengono multiplexate in una sola. In altre parole, in una connessione ci sono più stream, ognuno dei quali ha il proprio ID. Come bonus, c'è il server push integrato.
Tuttavia, la multiplexing porta a un altro problema cruciale. Immagina di eseguire 5 richieste a un unico server in modo asincrono. Utilizzando HTTP/2, tutte queste richieste verranno eseguite all'interno di una sola connessione TCP; significa che, se uno dei segmenti di qualsiasi richiesta si perde o arriva in modo errato, la trasmissione di tutte le richieste e le risposte si fermerà finché non sarà ripristinato il segmento mancante. È evidente che maggiore è la scadente qualità della connessione, più lento sarà HTTP/2. , in condizioni in cui i pacchetti persi rappresentano il 2% del totale, HTTP/1.1 in un browser si comporta meglio di HTTP/2 grazie al fatto che apre 6 connessioni invece di una.
Questo problema è chiamato "head-of-line blocking" e, sfortunatamente, non è possibile risolverlo utilizzando TCP.

Illustrazione di Daniel Steinberg
In conclusione, gli sviluppatori dello standard HTTP/2 hanno svolto un lavoro enorme e hanno fatto praticamente tutto ciò che era possibile a livello applicativo del modello OSI. È giunto il momento di scendere al livello di trasporto e inventare un nuovo protocollo di trasporto.
Abbiamo bisogno di un nuovo protocollo: UDP vs TCP
È diventato chiaro abbastanza rapidamente che implementare un protocollo di trasporto completamente nuovo è una sfida irrisolvibile nelle attuali realtà. Il fatto è che solo le apparecchiature di rete o i middle-box (router, firewall, server NAT…) conoscono il livello di trasporto e insegnare loro qualcosa di nuovo è un compito davvero difficile. Inoltre, il supporto per i protocolli di trasporto è integrato nel kernel dei sistemi operativi, e anche i kernel non cambiano facilmente.
A questo punto si potrebbe mollare tutto e dire «Certo, inventeremo un nuovo HTTP/3 con affetto e cortigiane, ma ci vorranno 10-15 anni prima che venga adottato (circa il tempo necessario per sostituire la maggior parte delle apparecchiature)», ma c'è un'altra opzione, non così ovvia: utilizzare il protocollo UDP. Sì, proprio quel protocollo con cui ci scambiavamo file in rete locale negli anni '90 e nei primi anni 2000. Praticamente tutte le apparecchiature di oggi possono lavorare con esso.
Quali sono i vantaggi di UDP rispetto a TCP? In primo luogo, non abbiamo una sessione a livello di trasporto riconosciuta dall'hardware. Questo ci permette di definire autonomamente le sessioni nei punti finali e di gestire i conflitti che sorgono. Non siamo quindi limitati a una o poche sessioni (come in TCP), ma possiamo crearne tante quante ne abbiamo bisogno. In secondo luogo, la trasmissione dei dati tramite UDP avviene più rapidamente rispetto a TCP. Pertanto, in teoria, possiamo superare l'attuale limite di velocità raggiunto con HTTP/2.
Tuttavia, UDP non garantisce l'affidabilità nella trasmissione dei dati. In effetti, stiamo semplicemente inviando pacchetti, sperando che dall'altra parte vengano ricevuti. Non li hanno ricevuti? Beh, non è andata bene… Questo è stato sufficiente per la trasmissione di video per adulti, ma per cose più serie è necessaria affidabilità, il che significa che dovremo sovrapporre qualcosa a UDP.
Come nel caso di HTTP/2, il lavoro per la creazione di un nuovo protocollo è iniziato in Google nel 2012, cioè più o meno contemporaneamente all'inizio dei lavori su SPDY. Nel 2013, Jim Roskind ha presentato al pubblico , e già nel 2015 è stata presentata una Internet Draft per la standardizzazione presso l'IETF. Già a quel tempo, il protocollo sviluppato da Roskind in Google differiva notevolmente dallo standard proposto, perciò la versione di Google venne chiamata gQUIC.
Che cos'è QUIC
Innanzitutto, come già detto, è un involucro sopra UDP. Sopra UDP si stabilisce una connessione QUIC, in cui, analogamente a HTTP/2, possono esistere più stream. Questi stream esistono solo sui punti finali e vengono gestiti in modo indipendente. Se si verifica una perdita di pacchetti in uno stream, gli altri non ne saranno affetti.

Illustrazione di Daniel Steinberg
In secondo luogo, la crittografia non è più implementata come un livello separato, ma è integrata nel protocollo. Questo consente di stabilire una connessione e scambiare chiavi pubbliche con un'unica operazione di handshake, oltre a permettere l'uso del meccanismo avanzato del 0-RTT handshake, eliminando così i ritardi durante l'handshake. Inoltre, ora è possibile crittografare pacchetti dati singoli. Ciò consente di avviare la decrittazione dei pacchetti ricevuti senza dover attendere il completamento della ricezione dei dati dallo stream. Questa modalità di funzionamento era completamente impossibile in TCP, poiché TLS e TCP operavano in modo indipendente, e TLS non poteva sapere come i dati sarebbero stati frammentati da TCP. Pertanto, non era in grado di preparare i propri segmenti in modo che corrispondessero ai segmenti TCP uno a uno, permettendo una decrittazione indipendente. Tutti questi miglioramenti consentono a QUIC di ridurre la latenza rispetto a TCP.

In terzo luogo, il concetto di stream leggeri consente di scollegare la connessione dall'indirizzo IP del cliente. Questo è importante, ad esempio, quando un cliente passa da un punto di accesso Wi-Fi a un altro, cambiando il proprio IP. In questo caso, l'uso di TCP comporta un lungo processo in cui le connessioni TCP esistenti scadono e nuove connessioni vengono create con il nuovo IP. Con QUIC, il cliente continua semplicemente a inviare pacchetti al server dal nuovo IP con il vecchio ID dello stream. Poiché l'ID dello stream è ora unico e non viene riutilizzato, il server comprende che il cliente ha cambiato IP, invia i pacchetti mancanti e prosegue la comunicazione all'indirizzo nuovo.
In quarto luogo, QUIC viene implementato a livello di applicazione, e non del sistema operativo. Questo, da un lato, consente di apportare modifiche più rapidamente al protocollo, poiché per ricevere un aggiornamento è sufficiente aggiornare la libreria, senza dover aspettare una nuova versione del sistema operativo. D'altra parte, ciò porta a un forte aumento del consumo della CPU.
E infine, parliamo degli header. La compressione degli header è uno degli aspetti che differisce tra QUIC e gQUIC. Non ha senso dedicare molto tempo a questo, quindi dirò solo che nella versione proposta per la standardizzazione la compressione degli header è stata resa il più simile possibile a quella di HTTP/2. Puoi leggere di più in dettaglio. .
Quanto è più veloce?
È una domanda complessa. Il fatto è che finché non abbiamo uno standard, non c'è molto da misurare. Forse, l'unico dato statistico di cui disponiamo è quello di Google, che utilizza gQUIC dal 2013 e nel 2016 , che circa il 90% del traffico verso i loro server da Chrome ora utilizza QUIC. Nella stessa presentazione affermano che con gQUIC le pagine si caricano circa il 5% più velocemente, mentre nel video in streaming si registrano il 30% in meno di buffering rispetto a TCP.
Nel 2017, un gruppo di ricercatori guidato da Arash Molavi Kakhki ha pubblicato sullo studio delle performance di gQUIC rispetto a TCP.
Lo studio ha rivelato alcune debolezze di gQUIC, come l'instabilità nella miscelazione dei pacchetti di rete, la scarsa equità nella gestione della larghezza di banda e un trasferimento più lento di oggetti di piccole dimensioni (fino a 10 KB). Tuttavia, quest'ultimo può essere compensato utilizzando il 0-RTT. In tutti gli altri casi esaminati, gQUIC ha mostrato un incremento della velocità rispetto a TCP. Le cifre specifiche sono difficili da fornire. È meglio consultare o .
Qui è importante sottolineare che questi dati riguardano specificamente gQUIC e non sono attuali per lo standard in fase di sviluppo. Cosa accadrà per QUIC: per ora è un mistero, ma c'è speranza che le debolezze emerse in gQUIC vengano considerate e risolte.
Un po' di futuro: e per HTTP/3?
Qui è tutto chiaro: l'API non cambierà affatto. Rimarrà esattamente come era in HTTP/2. E se l'API rimane invariata, la transizione a HTTP/3 dovrà avvenire tramite l'uso di una versione aggiornata della libreria sul backend, che supporta il trasporto tramite QUIC. Tuttavia, dovremo mantenere un fallback per le versioni precedenti di HTTP per un lungo periodo, poiché attualmente Internet non è pronta per una transizione totale a UDP.
Chi già supporta
Ecco le implementazioni esistenti di QUIC. Nonostante l'assenza di uno standard, la lista è piuttosto buona.
Nessun browser attualmente supporta QUIC nella versione produzione. Recentemente si è saputo che in Chrome è stata attivata la supporto per HTTP/3, ma solo nella versione Canary.
Tra i backend, solo e , ma ancora in modo sperimentale. NGINX alla fine della primavera 2019 , che stanno lavorando per supportare HTTP/3, ma non hanno ancora completato.
Quali problemi ci sono?
Viviamo in un mondo reale, dove nessuna grande tecnologia può affermarsi senza incontrare resistenza, e QUIC non fa eccezione.
La cosa più importante è che dobbiamo spiegare al browser che “https://” ora non è necessariamente collegato alla porta TCP 443. Potrebbe non esserci affatto TCP. A questo serve l'intestazione Alt-Svc. Essa consente di informare il browser che questo sito web è disponibile anche su un certo protocollo a un certo indirizzo. In teoria, dovrebbe funzionare senza intoppi, ma nella pratica ci imbatteremo nel fatto che UDP può essere, ad esempio, bloccato dal firewall per evitare attacchi DDoS.
Tuttavia, anche se UDP non è vietato, il client potrebbe trovarsi dietro un router NAT configurato per mantenere la sessione TCP tramite indirizzo IP. Poiché utilizziamo UDP, che non ha una sessione hardware, il NAT non manterrà la connessione e la sessione QUIC .
Tutti questi problemi sono legati al fatto che UDP non è stato utilizzato in passato per la trasmissione di contenuti Internet, quindi i produttori di hardware non potevano prevedere che ciò potesse accadere. Analogamente, gli amministratori delle reti non comprendono ancora bene come configurare correttamente le proprie reti per supportare QUIC. Questa situazione cambierà lentamente e, in ogni caso, tali cambiamenti richiederanno meno tempo rispetto all'implementazione di un nuovo protocollo di trasporto.
Inoltre, come già accennato, QUIC aumenta notevolmente l'uso della CPU. Daniel Stenberg un aumento dell'utilizzo della CPU fino a tre volte.
Quando arriverà HTTP/3
Standard entro maggio 2020, ma considerando che attualmente i documenti previsti per luglio 2019 non sono ancora completati, si può dire che la data verrà probabilmente posticipata.
Google utilizza la sua implementazione di gQUIC dal 2013. Se si osserva una richiesta HTTP inviata al motore di ricerca di Google, si può notare questo:

Conclusioni
QUIC appare attualmente come una tecnologia piuttosto grezza ma molto promettente. Considerando che negli ultimi 20 anni tutte le ottimizzazioni dei protocolli a livello di trasporto si sono principalmente concentrate su TCP, QUIC, che nella maggior parte dei casi offre migliori prestazioni, sembra già ora davvero interessante.
Tuttavia, rimangono ancora problemi irrisolti che dovremo affrontare nei prossimi anni. Il processo potrebbe richiedere più tempo a causa dell'hardware coinvolto, che nessuno ama aggiornare, ma tutte le problematiche sembrano comunque risolvibili e, prima o poi, tutti noi avremo HTTP/3.
Il futuro è alle porte!
Fonte: habr.com
