Da oltre 20 anni visualizziamo pagine web utilizzando il protocollo HTTP. La maggior parte degli utenti non si chiede nemmeno cosa sia e come funzioni. Altri sanno che da qualche parte sotto HTTP c'è TLS, e sotto TCP, sotto quale IP, e così via. E altri ancora - eretici - credono che TCP sia il secolo scorso, vogliono qualcosa di più veloce, affidabile e sicuro. Ma nel tentativo di inventare un nuovo protocollo ideale, sono tornati alle tecnologie degli anni '80 e stanno cercando di costruire il loro nuovo mondo su di esse.

Un po' di storia: HTTP/1.1
Nel 1997, il protocollo HTTP versione 1.1 per lo scambio di informazioni testuali ricevette la sua RFC. All'epoca, il protocollo era utilizzato dai browser da diversi anni e il nuovo standard durò altri quindici. Il protocollo funzionava esclusivamente secondo il principio richiesta-risposta ed era destinato principalmente alla trasmissione di informazioni testuali.
HTTP è stato progettato per funzionare sul protocollo TCP, che garantisce la consegna affidabile dei pacchetti al destinatario. TCP funziona stabilendo e mantenendo una connessione affidabile tra gli endpoint e suddividendo il traffico in segmenti. Ogni segmento ha un proprio numero di sequenza e un proprio checksum. Se uno qualsiasi dei segmenti non arriva o arriva con un checksum errato, la trasmissione si interromperà fino al ripristino del segmento perso.
In HTTP/1.0, la connessione TCP veniva chiusa dopo ogni richiesta. Questo era estremamente dispendioso, poiché stabilire una connessione TCP (3-Way-Handshake) è un processo lento. HTTP/1.1 ha introdotto il meccanismo keep-alive, che consente di riutilizzare una connessione per più richieste. Tuttavia, poiché può facilmente diventare un collo di bottiglia, diverse implementazioni di HTTP/1.1 consentono più connessioni TCP allo stesso host. Ad esempio, Chrome e le versioni recenti di Firefox consentono fino a sei connessioni.

Anche la crittografia avrebbe dovuto essere affidata ad altri protocolli, e a questo scopo venne utilizzato il protocollo TLS anziché TCP, che proteggeva i dati in modo piuttosto affidabile, ma aumentava ulteriormente il tempo necessario per stabilire una connessione. Di conseguenza, il processo di handshake iniziò ad apparire così:

Illustrazione di Cloudflare
Pertanto, HTTP/1.1 presentava una serie di problemi:
- Connessione lenta.
- I dati vengono trasmessi in formato testo, il che significa che la trasmissione di immagini, video e altre informazioni non testuali è inefficace.
- Per una richiesta viene utilizzata una connessione TCP, il che significa che le altre richieste devono trovare un'altra connessione o attendere che la richiesta corrente la rilasci.
- È supportato solo il modello pull. Lo standard non prevede alcuna clausola server-push.
- I titoli vengono trasmessi come testo.
Se server-push viene implementato più o meno utilizzando il protocollo WebSocket, allora i problemi rimanenti devono essere affrontati in modo più radicale.
Un po' di modernità: HTTP/2
Nel 2012, Google ha iniziato a lavorare sul protocollo SPDY (pronunciato "speedy"). Il protocollo aveva lo scopo di risolvere i principali problemi di HTTP/1.1, mantenendo al contempo la retrocompatibilità. Nel 2015, il gruppo di lavoro IETF ha presentato la specifica HTTP/2, basata sul protocollo SPDY. Ecco le differenze di HTTP/2:
- Serializzazione binaria.
- Multiplexing di più richieste HTTP in un'unica connessione TCP.
- Server-push pronto all'uso (senza WebSocket).
Il protocollo è stato un grande passo avanti. Era molto e non richiede la creazione di diverse connessioni TCP: tutte le richieste a un host vengono multiplexate in una sola. In altre parole, in una connessione ci sono diversi cosiddetti flussi, ognuno dei quali ha un proprio ID. Un server-push in box è un vantaggio.
Tuttavia, il multiplexing porta a un altro problema fondamentale. Immaginiamo di effettuare 5 richieste a un server in modo asincrono. Con HTTP/2, tutte queste richieste verranno effettuate all'interno di un'unica connessione TCP, il che significa che se un segmento di una richiesta viene perso o arriva in modo errato, tutte le richieste e le risposte si interromperanno fino al ripristino del segmento perso. Ovviamente, peggiore è la qualità della connessione, più lento sarà HTTP/2. , in condizioni in cui i pacchetti persi costituiscono il 2% del totale, HTTP/1.1 nel browser si dimostra migliore di HTTP/2 perché apre 6 connessioni invece di una.
Questo problema è chiamato "head-of-line blocking" e, sfortunatamente, non è possibile risolverlo utilizzando TCP.

Illustrazione di Daniel Steinberg
Di conseguenza, gli sviluppatori dello standard HTTP/2 hanno fatto un ottimo lavoro e hanno fatto quasi tutto ciò che era possibile fare a livello applicativo del modello OSI. È ora di passare al livello di trasporto e inventare un nuovo protocollo di trasporto.
Abbiamo bisogno di un nuovo protocollo: UDP vs TCP
È diventato subito chiaro che implementare un protocollo di livello di trasporto completamente nuovo è un compito impossibile nella realtà odierna. Il fatto è che il livello di trasporto è noto solo all'hardware o ai dispositivi intermedi (router, firewall, server NAT...), e insegnare loro qualcosa di nuovo è un compito estremamente arduo. Inoltre, il supporto per i protocolli di trasporto è integrato nel kernel dei sistemi operativi, e anche i kernel non sono molto propensi a cambiare.
E qui potremmo alzare le mani e dire: "Certo, inventeremo un nuovo HTTP/3 con preferenze e cortigiane, ma ci vorranno 10-15 anni per implementarlo (più o meno nello stesso periodo, la maggior parte dell'hardware sarà sostituito)", ma c'è un'altra opzione, meno ovvia: usare il protocollo UDP. Sì, lo stesso protocollo che usavamo per inviare file su una rete locale tra la fine degli anni Novanta e l'inizio del Duemila. Quasi tutto l'hardware odierno può supportarlo.
Quali sono i vantaggi di UDP rispetto a TCP? Innanzitutto, non abbiamo una sessione a livello di trasporto nota all'hardware. Questo ci permette di definire autonomamente la sessione sugli endpoint e di risolvere eventuali conflitti che si presentano. In altre parole, non siamo limitati a una o più sessioni (come in TCP), ma possiamo crearne quante ne vogliamo. In secondo luogo, il trasferimento dati tramite UDP è più veloce rispetto a TCP. Pertanto, in teoria, possiamo superare l'attuale limite di velocità raggiunto da HTTP/2.
Tuttavia, UDP non garantisce una trasmissione dati affidabile. In realtà, stiamo semplicemente inviando pacchetti, sperando che l'altra parte li riceva. Non li ha ricevuti? Beh, sfortuna... Questo era sufficiente per trasmettere video per adulti, ma per cose più serie è necessaria l'affidabilità, il che significa che dovrete aggiungere qualcos'altro a UDP.
Come per HTTP/2, il lavoro sul nuovo protocollo è iniziato in Google nel 2012, più o meno nello stesso periodo di SPDY. Nel 2013, Jim Roskind lo ha presentato al pubblico. e già nel 2015 l'Internet Draft fu sottoposto a standardizzazione presso l'IETF. Già allora, il protocollo sviluppato da Roskind presso Google era molto diverso da quello sottoposto allo standard, quindi la versione di Google si chiamava gQUIC.
Che cosa è QUIC
In primo luogo, come già accennato, si tratta di un wrapper su UDP. Una connessione QUIC viene attivata tramite UDP, in cui, analogamente a HTTP/2, possono coesistere diversi flussi. Questi flussi esistono solo sugli endpoint e vengono serviti in modo indipendente. Se un pacchetto viene perso in un flusso, non influenzerà gli altri.

Illustrazione di Daniel Steinberg
In secondo luogo, la crittografia ora non è implementata come un livello separato, ma è inclusa nel protocollo. Ciò consente di stabilire una connessione e scambiare chiavi pubbliche in un unico handshake, e consente inoltre di utilizzare l'intelligente meccanismo di handshake 0-RTT, evitando completamente i ritardi durante l'handshake. Inoltre, ora è possibile crittografare singoli pacchetti di dati. Ciò consente di non attendere il completamento della ricezione dei dati dal flusso, ma di decifrare i pacchetti ricevuti in modo indipendente. Questa modalità di funzionamento era generalmente impossibile in TCP, poiché TLS e TCP funzionavano indipendentemente l'uno dall'altro e TLS non poteva sapere in quali parti TCP avrebbe suddiviso i dati. Di conseguenza, non poteva preparare i suoi segmenti in modo che si adattassero ai segmenti TCP uno alla volta e potessero essere decifrati in modo indipendente. Tutti questi miglioramenti consentono a QUIC di ridurre la latenza rispetto a TCP.

In terzo luogo, il concetto di flussi leggeri consente di scollegare una connessione dall'indirizzo IP del client. Questo è importante, ad esempio, quando un client passa da un punto di accesso Wi-Fi a un altro, cambiando il proprio IP. In questo caso, utilizzando TCP, si verifica un lungo processo durante il quale le connessioni TCP esistenti vengono interrotte per timeout e vengono create nuove connessioni dal nuovo IP. Nel caso di QUIC, il client continua semplicemente a inviare pacchetti al server dal nuovo IP con il vecchio ID flusso. Poiché l'ID flusso è ora univoco e non riutilizzato, il server capisce che il client ha cambiato IP, invia nuovamente i pacchetti persi e continua la comunicazione al nuovo indirizzo.
In quarto luogo, QUIC è implementato a livello applicativo, non a livello di sistema operativo. Da un lato, questo consente modifiche più rapide al protocollo, poiché per ottenere un aggiornamento è sufficiente aggiornare la libreria, senza dover attendere una nuova versione del sistema operativo. Dall'altro, questo comporta un forte aumento del consumo di processore.
E infine, le intestazioni. La compressione delle intestazioni è una delle differenze tra QUIC e gQUIC. Non vedo il motivo di soffermarmi troppo su questo aspetto, mi limiterò a dire che nella versione presentata per la standardizzazione, la compressione delle intestazioni è stata resa il più simile possibile a quella di HTTP/2. Potete saperne di più qui. .
Quanto è più veloce?
Questa è una domanda difficile. Il fatto è che finché non avremo uno standard, non c'è molto da misurare. Forse le uniche statistiche che abbiamo sono quelle di Google, che utilizza gQUIC dal 2013 e nel 2016. , circa il 90% del traffico diretto ai loro server dal browser Chrome ora utilizza QUIC. Nella stessa presentazione, riportano che gQUIC carica le pagine circa il 5% più velocemente e trasmette i video in streaming con un ritardo del 30% inferiore rispetto a TCP.
Nel 2017, un gruppo di ricercatori guidato da Arash Molavi Kakhki ha pubblicato per studiare le prestazioni di gQUIC rispetto a TCP.
Lo studio ha rivelato diversi punti deboli di gQUIC, come l'instabilità nel mixaggio dei pacchetti di rete, l'avidità di capacità del canale e la trasmissione più lenta di oggetti di piccole dimensioni (fino a 10 kb). Quest'ultimo, tuttavia, può essere compensato utilizzando 0-RTT. In tutti gli altri casi studiati, gQUIC ha mostrato un aumento di velocità rispetto a TCP. È difficile parlare di numeri specifici in questa sede. È meglio leggere o .
Va notato che questi dati riguardano specificamente gQUIC e non sono rilevanti per lo standard in fase di sviluppo. Cosa accadrà a QUIC? È ancora un segreto gelosamente custodito, ma c'è la speranza che le debolezze identificate in gQUIC vengano prese in considerazione e corrette.
Un po' di futuro: che dire di HTTP/3?
Ma qui tutto è chiarissimo: l'API non cambierà in alcun modo. Tutto rimarrà esattamente come in HTTP/2. Ebbene, se l'API rimane la stessa, la transizione a HTTP/3 dovrà essere risolta utilizzando una nuova versione della libreria sul backend che supporti il trasporto tramite QUIC. Certo, sarà necessario mantenere un fallback alle vecchie versioni di HTTP per un periodo piuttosto lungo, poiché Internet non è pronta per una transizione completa a UDP.
Chi già supporta
Qui implementazioni QUIC esistenti. Nonostante la mancanza di uno standard, l'elenco non è male.
Attualmente nessun browser supporta QUIC nella versione di produzione. Di recente si è saputo che Chrome ha incluso il supporto per HTTP/3, ma finora solo in Canary.
Tra i backend, HTTP/3 supporta solo и , ma ancora sperimentale. NGINX nella tarda primavera del 2019 , che hanno iniziato a lavorare sul supporto HTTP/3, ma non l'hanno ancora terminato.
Quali sono i problemi?
Viviamo nel mondo reale, dove nessuna tecnologia di rilievo può raggiungere le masse senza incontrare resistenza, e QUIC non fa eccezione.
La cosa più importante è spiegare in qualche modo al browser che "https://" non conduce più necessariamente alla porta TCP 443. Potrebbe non esserci affatto TCP. A questo scopo viene utilizzata l'intestazione Alt-Svc. Permette di comunicare al browser che questo sito web è disponibile anche su un certo protocollo a un certo indirizzo. In teoria, questo dovrebbe funzionare alla perfezione, ma in pratica scopriremo che UDP potrebbe, ad esempio, essere vietato sul firewall per evitare attacchi DDoS.
Ma anche se UDP non è proibito, il client potrebbe trovarsi dietro un router NAT configurato per mantenere una sessione TCP tramite indirizzo IP e, poiché stiamo utilizzando UDP, che non ha una sessione hardware, NAT non manterrà la connessione e la sessione QUIC .
Tutti questi problemi sono legati al fatto che UDP non veniva utilizzato in precedenza per trasmettere contenuti Internet e i produttori di hardware non potevano prevedere che ciò sarebbe mai accaduto. Allo stesso modo, gli amministratori non hanno ancora compreso appieno come configurare correttamente le proprie reti per funzionare con QUIC. Questa situazione cambierà gradualmente e, in ogni caso, tali cambiamenti richiederanno meno tempo dell'implementazione di un nuovo protocollo di livello di trasporto.
Inoltre, come già descritto, QUIC aumenta notevolmente l'utilizzo della CPU. Daniel Stenberg crescita del processore fino a tre volte.
Quando arriverà HTTP/3?
Standard entro maggio 2020, ma dato che al momento i documenti previsti per luglio 2019 restano incompiuti, si può affermare che molto probabilmente la data verrà posticipata.
Ebbene, Google utilizza la propria implementazione di gQUIC dal 2013. Se si osserva la richiesta HTTP inviata al motore di ricerca Google, si può vedere quanto segue:

risultati
QUIC sembra ora una tecnologia piuttosto grezza, ma molto promettente. Considerando che negli ultimi 20 anni tutte le ottimizzazioni dei protocolli di livello trasporto hanno riguardato principalmente TCP, QUIC, che nella maggior parte dei casi si distingue in termini di prestazioni, appare già molto valido.
Tuttavia, ci sono ancora alcuni problemi irrisolti che dovranno essere affrontati nei prossimi anni. Il processo potrebbe subire ritardi a causa dell'hardware coinvolto, che nessuno ama aggiornare, ma ciononostante tutti i problemi sembrano risolvibili e, prima o poi, avremo tutti HTTP/3.
Il futuro è dietro l'angolo!
Fonte: habr.com
