Guide

Come raddoppiare la velocità di caricamento con HTTP/2

HTTP/2, detto anche HTTP/2.0, è la nuova versione del protocollo HTTP che rende le applicazioni web più veloci, snelle e robuste, consentendo di fare a meno di alcune tecniche di ottimizzazione adottate per porre rimedio ai limiti di HTTP/1.1. Tra gli obiettivi primari di HTTP/2 vi sono:

  • la riduzione della latenza di rete mediante l’instaurazione di una singola connessione tra client e server e l’abilitazione del multiplexing per un download parallelo delle risorse;
  • la riduzione dell’overhead del protocollo mediante un’efficiente compressione degli header HTTP;
  • la definizione delle priorità di download delle risorse mediante il server push.

Le implementazioni per raggiungere tali obiettivi, che stavano alla base del progetto sperimentale SPDY di Google, consentono di aumentare i livelli di performance fino anche a raddoppiare la velocità di caricamento di una pagina web

HTTP/2 mira inoltre ad essere retrocompatibile, infatti tutti i concetti chiave come status code, headers, metodi HTTP ecc.. rimangono inalterati, difatti il passaggio da HTTP/1.1 ad HTTP/2.0 non richiede alcuna modifica alle applicazioni.

Funzionamento di HTTP/2

Se sei uno sviluppatore probabilmente ti starai chiedendo perché hanno ribattezzato il protocollo HTTP/2.0 invece di HTTP/1.2 o similari? Il motivo sta nel cambiamento nel come i dati vengono scambiati tra client e server. Per raggiungere gli obiettivi elencati poc’anzi, HTTP/2 aggiunge un nuovo layer in formato binario non retrocompatibile con i server ed i client HTTP/1.x, motivo per cui si è deciso di incrementare la versione a 2.0.

Quindi il protocollo è retrocompatibile per quanto concerne le applicazioni web ma richiede un upgrade del web server e del browser ad una versione supportata. Chiusa questa parentesi, vediamo come funziona nel dettaglio questa nuova versione del protocollo HTTP.

Layer binario

A differenza di HTTP/1.1, i messaggi HTTP sono incapsulati e trasmessi tra client e server all’interno di un frame binario come rappresentato dalla figura sottostante.

Dall’immagine si nota come la semantica HTTP non viene alterata ma è la codifica durante la fase di trasmissione a cambiare. I dati, infatti, vengono suddivisi in messaggi e frame più piccoli i quali vengono codificati in binario e trasmessi.

Pertanto è necessario disporre di client e server in grado di utilizzare il nuovo meccanismo di codifica, una banalità che consente di rendere le applicazioni web praticamente identiche. Un toccasana per gli sviluppatori web che non dovranno effettuare alcuna modifica ai miliardi di siti web presenti in tutto il mondo per supportare il nuovo protocollo.

Frame, Stream e Messaggi

A differenza di HTTP/1.1, tutte le comunicazioni in HTTP/2 vengono effettuate mediante l’ausilio di un’unica connessione TCP. Gli header che compongono il pacchetto HTTP vengono suddivisi in frame codificati in binario che a loro volta vengono raggruppati in messaggi che appartengono a stream ben precisi, i quali vengono trasmessi mediante la connessione TCP aperta.

Ad ogni stream e frame viene assegnato un ID univoco che servirà a client e server per ricomporre il messaggio originale ed elaborare la richiesta. Questo consente di utilizzare la stessa connessione TCP per la trasmissione di diversi messaggi HTTP e grazie alla suddivisione in frame ne consente il download parallelo.

Naturalmente la trasmissione dei frame è regolamentata da un algoritmo di assegnazione delle priorità affinché l’ordine di trasmissione non comprometta le performance.

Multiplexing

Con HTTP/1.1, per velocizzare il download delle risorse esterne e quindi velocizzare il tempo di rendering della pagina, il browser era obbligato ad aprire diverse connessioni TCP, una per ogni richiesta. Un male assoluto che ha portato gli sviluppatori ad adottare tecniche di minificazione e concatenazione di risorse critiche e immagini per ridurre il numero di richieste HTTP e quindi di connessioni.

L’introduzione del layer binario e la conseguente suddivisione dei pacchetti HTTP in frame bypassa queste limitazioni e consente di avviare una comunicazione in multiplexing, dove diversi frame facenti parte anche di diversi pacchetti/risorse possono essere trasmessi in rete per poi essere riassemblati grazie ai loro ID univoci.

Questo consente al client di scaricare in parallelo le risorse necessarie per effettuare il rendering della pagina. Com’è possibile notare dalla figura sottostante, infatti, mentre il client invia al server uno stream identificato dell’ID 5 il server invia al client gli stream 1 e 3 ad intervalli diversi, facenti capo a risorse diverse.

È possibile visualizzare in pratica questo comportamento analizzando il waterfall delle risorse di rete quando si visita un sito web con e senza supporto HTTP 2. Le immagini successive riportano il waterfall di Chrome DevTools dello stesso sito, prima e dopo l’applicazione di HTTP 2. È possibile notare come nel primo caso le risorse vengono scaricate in modalità sequenziale mentre nel secondo caso in parallelo.

Da notare come il tempo di download necessario per scaricare le risorse sia praticamente dimezzato rispetto alla versione HTTP/1.1. Il nuovo protocollo inoltre implementa un algoritmo per il controllo del flusso di trasmissione dati che mira a non sovraccaricare una delle due parti (client o server) con dati che non vuole o che non può in quel momento elaborare.

Utilizzo di un’unica connessione TCP

Come già detto più volte nei paragrafi precedenti, HTTP/2 supporta un’unica connessione TCP per origine che offre diversi benefici in termini di performance. Molte delle risorse che compongono una pagina web sono piccole al punto che l’apertura di una nuova connessione TCP con tutto quello che ne comporta, ovvero risoluzione DNS, TCP handshake, eventuale negoziazione TLS e tempo di download, risulta più lenta del download della risorsa stessa.

Inoltre l’utilizzo di un’unica connessione consente di ridurre il consumo di memoria ed overhead di CPU. La migrazione ad HTTP/2 quindi non va vista solo dal punto di vista della riduzione della latenza di rete ma anche come un’ottimizzazione delle risorse computazionali.

Server Push

Una tipica pagina web è formata da una dozzina di risorse che vengono scoperte dal client durante il parsing HTML e successivamente richieste al server. HTTP/2 consente al server di anticipare al client questa scoperta e ridurre così il tempo necessario per richiedere il download di tali risorse. Questa caratteristica è nota come server push.

Praticamente, oltre alla risposta alla richiesta originale, il server può inviare al client risorse aggiuntive senza che sia il client a richiederle esplicitamente. Dalla figura sottostante il server invia al client la risposta allo stream 1 ma in più invia due ulteriori stream, 2 e 4, corrispondenti a risorse differenti, ad esempio uno script Javascript e un CSS che di per certo verranno utilizzati all’interno della pagina.

Il client può decidere se prendere o meno in considerazione il download della risorsa comunicata tramite server push. Ad esempio se la risorsa è già stata scaricata ed è disponibile in cache, il browser declinerà la richiesta.

Compressione degli header

Ogni pacchetto HTTP è composto da header in formato testo che riportano proprietà e caratteristiche della risorsa in fase di trasferimento. Mentre in HTTP/1.1 questi dati vengono sempre trasmessi in chiaro, compreso i cookie con tutto il loro peso, in HTTP/2 vengono compressi utilizzando il formato di compressione HPACK, applicando un algoritmo che consente di rimuovere tutto ciò che è duplicato, ottenendo header più snelli.

Per maggiori informazioni sul funzionamento di HPACK su HTTP/2 vi invito a leggere il documento IETF HPACK – Header Compression for HTTP/2.

Secondo i test condotti da KeyCDN, la compressione degli header riduce la loro dimensione di circa il 30%.

Supporto HTTP/2

Per utilizzare HTTP/2 è richiesto l’utilizzo di HTTPS. Grazie ad HTTP/2 ed al suo multiplexing, le connessioni cifrate sono diventate molto più veloci delle classiche connessioni non sicure. Per verificarlo basta effettuare una comparazione di velocità tra HTTP e HTTPS

Come verificare il supporto HTTP/2

Per verificare se un sito web supporta HTTP/2 basta visitarlo, aprire la Chrome DevTools, posizionarsi sul tab Network, cliccare con il tasto destro sulla tabella e abilitare la visualizzazione della colonna Protocol se non già visibile ed aggiornare la pagina. Se il sito supporta HTTP/2, le risorse scaricate dallo stesso avranno h2 come protocollo.

Alternativamente, per capire se il browser che stiamo utilizzando supporta HTTP/2 basta visitare il test online di Akamai che oltre a verificare il supporto effettuerà un test di velocità di download delle stesse immagini prima in HTTP/1.1 e poi in HTTP/2 per farvi notare la reale differenza nel tempo di caricamento.

Elenco dei browser che supportano HTTP/2

Ad oggi più del 77% dei browser supporta HTTP/2, tuttavia alcuni non lo supportano ancora in tutte le sue caratteristiche. Di seguito la lista completa dei browser che supportano HTTP/2. È possibile verificare via via il supporto cliccando qui.

Come abilitare il supporto HTTP/2 su Nginx

Per utilizzare HTTP/2 su Nginx occorre utilizzare una versione maggiore o uguale alla 1.9.5. Configurarlo è facilissimo:

  • Aprire il file di configurazione del sito web (quello che per Apache viene chiamato Virtual Host)
  • Inserire http2 in corrispondenza della direttiva listen
  • Salvare e riavviare nginx
server {
  listen 443 ssl http2 default_server;
  ssl_certificate /path/to/server.cert;
  ssl_certificate_key /path/to/server.key;

  ...

}

Come abilitare il supporto HTTP/2 su Apache

Per utilizzare HTTP/2 su Apache occorre utilizzare una versione maggiore o uguale alla 2.4. Se è su un server Ubuntu LTS 16.04 occorre prima aggiornare il repository:

sudo add-apt-repository ppa:ondrej/apache2
sudo apt-get update
sudo apt-get upgrade

Una volta installato Apache occorre abilitare il modulo http2:

sudo a2enmod http2

Dopodiché modificare il Virtual Host SSL ed aggiungere la direttiva Protocols:

<VirtualHost *:443>
  ServerAdmin webmaster@localhost
  ServerName your-domain.com
  SSLEngine On
  SSLCertificateFile /path/to/server.cert
  SSLCertificateKeyFile /path/to/server.key
  Protocols h2 http/1.1

  ...
</VirtualHost>

Riavviare Apache.

Conclusione

HTTP/2 consente out of the box di ottenere performance più elevate rispetto ad HTTP/1.1 grazie alle implementazioni che consentono di parallelizzare il download delle risorse ed anticiparne i tempi di richiesta, oltre che ad una maggiore velocità di trasmissione dovuta alla compressione dati.

Il passaggio da HTTP/1.1 ad HTTP/2 non comporta alcuna modifica dell’applicazione web ma tecniche di ottimizzazione utilizzate per HTTP/1.1 devono essere riviste in ottica HTTP/2, in particolar modo quelle che mirano a ridurre il numero di richieste HTTP.

Salvatore Fresta

Disqus Comments Loading...
Share
Pubblicato da
Salvatore Fresta

Recent Posts

Cloudflare: come identificare la location del server

Cloudflare si antepone tra il server di origine e la richiesta dell'utente per servire file…

18 Marzo 2019

Ottimizzazione MySQL: come scegliere il valore di InnoDB Buffer Pool

L'ottimizzazione del database MySQL è tra i tuning più importanti in tema di performance web.…

5 Marzo 2019

Cache di post e pagine WordPress con Cloudflare

Cloudflare è un ottimo servizio utilizzato sia per migliorare le performance in caso di traffico…

19 Settembre 2018

WordPress, CDN, offloading e compressione immagini

Una delle tante pratiche di ottimizzazione del tempo di caricamento pagina quando si riceve un…

22 Maggio 2018

WordPress e WebP: guida completa

WebP è un formato di immagine sviluppato da Google ed appositamente pensato per ottimizzare il…

17 Maggio 2018

Caching avanzato con i Service Worker

Qualche settimana fa abbiamo visto cosa sono i service worker e come utilizzarli per creare…

12 Maggio 2018