Navigatie overslaan
Deel IV Hoofdstuk 22

HTTP/2

Inleiding

HTTP is een applicatielaagprotocol dat is ontworpen om informatie tussen netwerkapparaten uit te wisselen en wordt uitgevoerd bovenop andere lagen van de netwerkprotocolstapel. Nadat HTTP/1.x was uitgebracht, duurde het meer dan 20 jaar voordat de eerste grote update, HTTP/2, in 2015 een standaard werd.

Daar bleef het niet bij: de afgelopen vier jaar zijn HTTP/3 en QUIC (een nieuw latentieverminderend, betrouwbaar en veilig transportprotocol) in standaarden ontwikkeld in de IETF QUIC-werkgroep. Er zijn eigenlijk twee protocollen die dezelfde naam hebben: “Google QUIC” (afgekort “gQUIC”), het oorspronkelijke protocol dat is ontworpen en gebruikt door Google, en de nieuwere IETF-gestandaardiseerde versie (IETF QUIC/QUIC). IETF QUIC was gebaseerd op gQUIC, maar is uitgegroeid tot een heel ander ontwerp en implementatie. Op 21 oktober 2020 bereikte concept 32 van IETF QUIC een belangrijke mijlpaal toen het werd verplaatst naar Last Call. Dit is het deel van het standaardisatieproces wanneer de werkgroep denkt dat ze bijna klaar zijn en vraagt om een laatste beoordeling van de bredere IETF-gemeenschap.

In dit hoofdstuk wordt de huidige status van HTTP/2 en gQUIC-implementatie besproken. Het onderzoekt hoe goed sommige van de nieuwere functies van het protocol, zoals prioriteitstelling en server-push, zijn overgenomen. Vervolgens kijken we naar de motivaties voor HTTP/3, beschrijven we de belangrijkste verschillen tussen de protocolversies en bespreken we de mogelijke uitdagingen bij het upgraden naar een UDP-gebaseerd transportprotocol met QUIC.

HTTP/1.0 naar HTTP/2

Terwijl het HTTP-protocol is geëvolueerd, is de semantiek van HTTP hetzelfde gebleven; er zijn geen wijzigingen in de HTTP-methoden (zoals GET of POST), statuscodes (200 of de gevreesde 404), URI’s of headervelden. Waar het HTTP-protocol is veranderd, zijn de verschillen de draadcodering en het gebruik van functies van het onderliggende transport.

HTTP/1.0, gepubliceerd in 1996, definieerde het op tekst gebaseerde applicatieprotocol, waardoor cliënten en servers berichten kunnen uitwisselen om bronnen aan te vragen. Voor elk verzoek/antwoord was een nieuwe TCP-verbinding vereist, waardoor overhead werd geïntroduceerd. TCP-verbindingen gebruiken een algoritme voor congestiecontrole om te maximaliseren hoeveel gegevens er tijdens de vlucht kunnen zijn. Dit proces kost tijd voor elke nieuwe verbinding. Deze “langzame start” betekent dat niet alle beschikbare bandbreedte onmiddellijk wordt gebruikt.

In 1997 werd HTTP/1.1 geïntroduceerd om hergebruik van TCP-verbindingen mogelijk te maken door “keep-alives” toe te voegen, gericht op het verlagen van de totale kosten van het opstarten van verbindingen. Na verloop van tijd leidden de toenemende prestatieverwachtingen van de website tot de behoefte aan gelijktijdigheid van verzoeken. HTTP/1.1 kon alleen een andere bron opvragen nadat het vorige antwoord was voltooid. Daarom moesten extra TCP-verbindingen tot stand worden gebracht, waardoor de impact van de keep-alive-verbindingen werd verkleind en de overhead nog groter werd.

HTTP/2, gepubliceerd in 2015, is een binair protocol dat het concept van bidirectionele streams tussen cliënt en server introduceerde. Met behulp van deze streams kan een browser optimaal gebruik maken van een enkele TCP-verbinding om meerdere HTTP-verzoeken/-antwoorden tegelijkertijd te multiplexen. HTTP/2 introduceerde ook een prioriteitsschema om deze multiplexing te sturen; cliënten kunnen een verzoekprioriteit aangeven waardoor belangrijkere bronnen vóór anderen kunnen worden verzonden.

HTTP/2-adoptie

De gegevens die in dit hoofdstuk worden gebruikt, zijn afkomstig uit het HTTP Archive en testen meer dan zeven miljoen websites met een Chrome-browser. Net als bij andere hoofdstukken, wordt de analyse opgesplitst in mobiele en desktopwebsites. Wanneer de resultaten tussen desktop en mobiel vergelijkbaar zijn, worden statistieken uit de mobiele dataset gepresenteerd. U kunt meer details vinden op de pagina Methodologie. Houd er bij het bekijken van deze gegevens rekening mee dat elke website evenveel gewicht krijgt, ongeacht het aantal verzoeken. We raden u aan dit meer te zien als het onderzoeken van de trends op een breed scala aan actieve websites.

HTTP/2-gebruik op verzoek. (Bron: HTTP Archive)
Figuur 22.1. HTTP/2-gebruik op verzoek. (Bron: HTTP Archive)

Uit de analyse van HTTP Archive-gegevens vorig jaar bleek dat HTTP/2 werd gebruikt voor meer dan 50% van de verzoeken en, zoals te zien is, is de lineaire groei in 2020 voortgezet; nu wordt meer dan 60% van de verzoeken bediend via HTTP/2.

64%
Figuur 22.2. Het percentage verzoeken dat gebruikmaakt van HTTP/2.

Wanneer Figuur 22.3 wordt vergeleken met de resultaten van vorig jaar, is er een toename van 10% in HTTP/2-verzoeken en een overeenkomstige afname van 10% in HTTP/1.x-verzoeken. Dit is het eerste jaar dat gQUIC in de dataset te zien is.

Protocol Desktop Mobiel
HTTP/1.1 **34,47% 34,11%
HTTP/2 63,70% 63,80%
gQUIC 1,72% 1,71%
Figuur 22.3. Gebruik van HTTP-versie op verzoek.

** Net als bij de crawl van vorig jaar, meldde ongeveer 4% van de desktopverzoeken geen protocolversie. Analyse toont aan dat dit meestal HTTP/1.1 is en we hebben eraan gewerkt om dit gat in onze statistieken voor toekomstige crawls en analyses te dichten. Hoewel we de gegevens baseren op de crawl van augustus 2020, hebben we de correctie in de gegevensset van oktober 2020 vóór publicatie bevestigd, die inderdaad aantoonde dat dit HTTP/1.1-verzoeken waren en hebben ze daarom aan die statistiek in de bovenstaande tabel toegevoegd.

Bij het beoordelen van het totale aantal websiteverzoeken, zal er een voorkeur zijn voor algemene domeinen van derden. Om een beter begrip te krijgen van de HTTP/2-acceptatie door serverinstallatie, zullen we in plaats daarvan kijken naar het protocol dat wordt gebruikt om de HTML aan te bieden vanaf de startpagina van een site.

Vorig jaar werd ongeveer 37% van de startpagina’s bediend via HTTP/2 en 63% via HTTP/1. Dit jaar is de combinatie van mobiel en desktop ongeveer gelijk, met iets meer desktopsites die voor het eerst via HTTP/2 worden bediend, zoals weergegeven in figuur 22.4.

Protocol Desktop Mobiel
HTTP/1.0 0,06% 0,05%
HTTP/1.1 49,22% 50,05%
HTTP/2 49,97% 49,28%
Figuur 22.4. HTTP-versiegebruik voor startpagina’s.

gQUIC wordt om twee redenen niet gezien in de gegevens van de startpagina. Om een website over gQUIC te meten, zou de HTTP Archivecrawl protocolonderhandelingen moeten uitvoeren via de alternative services-header en vervolgens dit eindpunt gebruiken om de site over gQUIC te laden. Dit werd dit jaar niet ondersteund, maar verwacht dat het volgend jaar beschikbaar zal zijn in de Web Almanac. gQUIC wordt ook voornamelijk gebruikt voor Google-tools van derden in plaats van startpagina’s weer te geven.

De drang om beveiliging en privacy op het web te verbeteren, heeft geleid tot een toename van het aantal verzoeken over TLS met meer dan 150% in de afgelopen 4 jaar. Tegenwoordig is meer dan 86% van alle verzoeken op mobiel en desktop versleuteld. Als we alleen naar startpagina’s kijken, zijn de cijfers nog steeds een indrukwekkende 78,1% van de desktop en 74,7% van de mobiele apparaten. Dit is belangrijk omdat HTTP/2 alleen wordt ondersteund door browsers via TLS. Het aandeel dat via HTTP/2 wordt bediend, zoals weergegeven in figuur 22.5, is ook met 10 procentpunten gestegen ten opzichte van vorig jaar, van 55% naar 65%.

Protocol Desktop Mobiel
HTTP/1.1 36,05% 34,04%
HTTP/2 63,95% 65,96%
Figuur 22.5. HTTP-versiegebruik voor HTTPS-startpagina’s.

Nu meer dan 60% van de websites wordt bediend via HTTP/2 of gQUIC, gaan we wat dieper kijken naar het patroon van protocoldistributie voor alle verzoeken die op individuele sites worden gedaan.

Figuur 22.6. Vergelijk de verdeling van fractie van HTTP/2-aanvragen per pagina in 2020 met 2019.

Figuur 22.6 Vergelijkt hoeveel HTTP/2 of GQUIC wordt gebruikt op een website tussen dit jaar en vorig jaar. De meest opvallende verandering is dat meer dan de helft van de sites nu 75% of meer van hun verzoeken heeft geserveerd via HTTP/2 of GQUIC vergeleken met 46% vorig jaar. Minder dan 7% van de sites maakt geen HTTP/2- of GQUIC-aanvragen, terwijl (alleen) 10% van de sites volledig HTTP/2- of GQUIC-verzoeken is.

Hoe zit het met de uitsplitsing van de pagina zelf? We praten meestal over het verschil tussen inhoud van de eerste partij en derden. Derde-partij wordt gedefinieerd als inhoud die niet binnen de directe controle van de eigenaar van de site, functionaliteit, zoals reclame, marketing of analyse biedt. De definitie van bekende derden is afkomstig van de third party web repository.

Figuur 22.7 bestelt van elke website door de fractie van HTTP/2-verzoeken voor bekende derden of eerste partijverzoeken in vergelijking met andere verzoeken. Er is een merkbaar verschil als meer dan 40% van alle sites geen HTTP/2 of GQUIC-aanvragen heeft. Daarentegen heeft zelfs de laagste 5% van de pagina’s 30% van de inhoud van derden geserveerd via HTTP/2. Dit geeft aan dat een groot deel van de brede goedkeuring van HTTP/2 wordt aangedreven door de derde partijen.

Figuur 22.7. De verdeling van de fractie van derden en eerste-Partij HTTP/2-aanvragen per pagina.

Is er een verschil in welke inhoud-typen worden geserveerd via HTTP/2 of GQUIC? Figuur 22.8 toont bijvoorbeeld dat 90% van de websites 100% van de lettertypen van derden en audio via HTTP/2 of GQUIC serveert, slechts 5% boven HTTP/1.1 en 5% zijn een mix. De meerderheid van de activa van derden is scripts of afbeeldingen en worden uitsluitend geserveerd over HTTP/2 of GQUIC op respectievelijk 60% en 70% van de websites.

Figuur 22.8. De fractie van bekende HTTP/2- of GQUIC-verzoeken van derden door inhoudstype per website.

Advertenties, Analytics, Content Delivery Network (CDN)-bronnen en tag-managers worden voornamelijk geserveerd via HTTP/2 of GQUIC zoals getoond in Figuur 22.9. Customer-success en Marketing-inhoud wordt waarschijnlijk meer geserveerd via HTTP/1.

Figuur 22.9. De fractie van bekende HTTP/2- of GQUIC-verzoeken van derden per categorie per website.

Serverondersteuning

Browser auto-update-mechanismen zijn een drijffactor voor de aanneming van de klantzijde van nieuwe webnormen. Het is geschat dat meer dan 97% van de wereldwijde gebruikers HTTP/2 ondersteunt, enigszins omhoog van 95% gemeten vorig jaar.

Helaas is het verbeteringspad voor servers moeilijker, vooral met de eis om TLS te ondersteunen. Voor mobiel en desktop kunnen we zien vanaf figuur 22.10, dat de meerderheid van de HTTP/2-sites worden bediend door NGINX, CloudFlare en Apache. Bijna de helft van de HTTP/1.1-sites wordt bediend door Apache.

Figuur 22.10. Servergebruik door HTTP-protocol op mobiel

Hoe wordt HTTP/2-adoptie in het laatste jaar voor elke server gewijzigd? Figuur 22.11 toont een algemene HTTP/2-goedkeuring van ongeveer 10% in alle servers sinds vorig jaar. Apache en IIS zijn nog steeds minder dan 25% HTTP/2. Dit suggereert dat nieuwe servers de neiging hebben NGINX te zijn of het wordt gezien als te moeilijk of niet de moeite waard om Apache of IIS naar HTTP/2 en/of TLS te upgraden.

Figuur 22.11. Percentage pagina’s geserveerd via HTTP/2 per server

Een aanbeveling op lange termijn om de website-prestaties te verbeteren, is geweest om een CDN te gebruiken. Het voordeel is een vermindering van de latentie door zowel de inhoud en het beëindigen van verbindingen dichter bij de eindgebruiker. Dit helpt de snelle evolutie in Protocol-implementatie en de extra complexiteiten in tuningservers en besturingssystemen te beperken (zie de sectie Prioritering voor meer informatie). Om de nieuwe protocollen effectief te gebruiken, kan het gebruik van een CDN worden gezien als de aanbevolen aanpak.

CDN’s kunnen worden geclassificeerd in twee brede categorieën: degenen die de startpagina en/of activa-subdomeinen serveren, en degenen die voornamelijk worden gebruikt om inhoud van derden te dienen. Voorbeelden van de eerste categorie zijn de grotere generieke CDN’s (zoals Cloudflare, Akamai of Fastly) en de specifieker (zoals WordPress of Netlify). Kijkend naar het verschil in HTTP/2-goedkeuringscijfers voor startpagina’s geserveerd met of zonder een CDN, zien we:

  • 80% van de mobiele startpagina’s wordt bediend via HTTP/2 als een CDN wordt gebruikt
  • 30% van de mobiele startpagina’s wordt bediend via HTTP/2 als er geen CDN wordt gebruikt

Figuur 22.12 toont de meer specifieke en moderne CDN’s die een groter deel van het verkeer bedienen via HTTP/2.

HTTP/2 (%) CDN
100% Bison Grid, CDNsun, LeaseWeb CDN, NYI FTW, QUIC.cloud, Roast.io, Sirv CDN, Twitter, Zycada Networks
90 - 99% Automattic, Azion, BitGravity, Facebook, KeyCDN, Microsoft Azure, NGENIX, Netlify, Yahoo, section.io, Airee, BunnyCDN, Cloudflare, GoCache, NetDNA, SFR, Sucuri Firewall
70 - 89% Amazon CloudFront, BelugaCDN, CDN, CDN77, Erstream, Fastly, Highwinds, OVH CDN, Yottaa, Edgecast, Myra Security CDN, StackPath, XLabs Security
20 - 69% Akamai, Aryaka, Google, Limelight, Rackspace, Incapsula, Level 3, Medianova, OnApp, Singular CDN, Vercel, Cachefly, Cedexis, Reflected Networks, Universal CDN, Yunjiasu, CDNetworks
< 20% Rocket CDN, BO.LT, ChinaCache, KINX CDN, Zenedge, ChinaNetCenter
Figuur 22.12. Percentage HTTP/2-verzoeken dat wordt geleverd door de eerste-partij CDN’s via mobiel.

Typen inhoud in de tweede categorie zijn doorgaans gedeelde bronnen (JavaScript of lettertype-CDN’s), advertenties of analyses. In al deze gevallen zal het gebruik van een CDN de prestaties en ontlasting voor de verschillende SaaS-oplossingen verbeteren.

Figuur 22.13. Vergelijking van HTTP/2- en gQUIC-gebruik voor websites die een CDN gebruiken.

In figuur 22.13 kunnen we het grote verschil zien in HTTP/2- en gQUIC-acceptatie wanneer een website een CDN gebruikt. 70% van de pagina’s gebruikt HTTP/2 voor alle verzoeken van derden wanneer een CDN wordt gebruikt. Zonder CDN gebruikt slechts 25% van de pagina’s HTTP/2 voor alle verzoeken van derden.

HTTP/2-impact

Het meten van de impact van hoe een protocol presteert is moeilijk met de huidige HTTP Archive benadering. Het zou echt fascinerend zijn om de impact van gelijktijdige verbindingen, het effect van pakketverlies en verschillende mechanismen voor congestiecontrole te kunnen kwantificeren. Om de prestaties echt te kunnen vergelijken, zou elke website via elk protocol over verschillende netwerkomstandigheden moeten worden gecrawld. Wat we in plaats daarvan kunnen doen, is kijken naar de impact op het aantal verbindingen dat een website gebruikt.

Verbindingen verminderen

Zoals eerder besproken, staat HTTP/1.1 slechts één verzoek per keer via een TCP-verbinding toe. De meeste browsers omzeilen dit door zes parallelle verbindingen per host toe te staan. De belangrijkste verbetering met HTTP/2 is dat meerdere verzoeken via een enkele TCP-verbinding kunnen worden gemultiplexed. Dit zou het totale aantal verbindingen - en de bijbehorende tijd en middelen - die nodig zijn om een pagina te laden, moeten verminderen.

Figuur 22.14. Verdeling van het totale aantal verbindingen per pagina

Figuur 22.15 laat zien hoe het aantal TCP-verbindingen per pagina in 2020 is afgenomen ten opzichte van 2016. De helft van alle websites gebruikt nu 13 of minder TCP-verbindingen in 2020 ten opzichte van 23 verbindingen in 2016; een afname van 44%. In dezelfde periode is het mediaan aantal verzoeken slechts gedaald van 74 naar 73. Het mediaan aantal verzoeken per TCP-verbinding is gestegen van 3,2 naar 5,6.

TCP is ontworpen om een gemiddelde gegevensstroom te behouden die zowel efficiënt als eerlijk is. Stelt u een stroomcontroleproces voor waarbij elke stroom zowel druk uitoefent op als reageert op alle andere stromen, om een eerlijk deel van het netwerk te leveren. In een eerlijk protocol verdringt elke TCP-sessie geen enkele andere sessie en zal na verloop van tijd 1/N van de padcapaciteit in beslag nemen.

De meeste websites openen nog steeds meer dan 15 TCP-verbindingen. In HTTP/1.1 kunnen de zes verbindingen die een browser met een domein zou kunnen openen, na verloop van tijd zes keer zoveel bandbreedte claimen als een enkele HTTP/2-verbinding. Bij netwerken met een lage capaciteit kan dit de levering van inhoud van de primaire activadomeinen vertragen naarmate het aantal concurrerende verbindingen toeneemt en bandbreedte wegneemt van de belangrijke verzoeken. Dit is in het voordeel van websites met een klein aantal domeinen van derden.

HTTP/2 staat hergebruik van verbindingen toe voor verschillende, maar gerelateerde domeinen. Voor een TLS-bron is een certificaat vereist dat geldig is voor de host in de URI. Dit kan worden gebruikt om het aantal verbindingen te verminderen dat nodig is voor domeinen die onder controle staan van de site-auteur.

Prioritering

Omdat HTTP/2-reacties kunnen worden opgesplitst in veel individuele frames en omdat frames uit meerdere streams kunnen worden gemultiplexed, wordt de volgorde waarin de frames worden interleaved en geleverd door de server een kritieke prestatie-overweging. Een typische website bestaat uit veel verschillende soorten bronnen: de zichtbare inhoud (HTML, CSS, afbeeldingen), de applicatielogica (JavaScript), advertenties, analyses voor het volgen van sitegebruik en marketing-trackingbakens. Met kennis van hoe een browser werkt, kan een optimale ordening van de bronnen worden gedefinieerd die zal resulteren in de snelste gebruikerservaring. Het verschil tussen optimaal en niet-optimaal kan aanzienlijk zijn - wel 50% prestatieverbetering of meer!

HTTP/2 introduceerde het concept van prioritering om de cliënt te helpen communiceren met de server hoe hij denkt dat het multiplexen moet worden uitgevoerd. Aan elke stream wordt een gewicht toegekend (hoeveel van de beschikbare bandbreedte de stream zou moeten worden toegewezen) en mogelijk een ouder (een andere stream die als eerste zou moeten worden afgeleverd). Met de flexibiliteit van het prioriteitsmodel van HTTP/2 is het niet helemaal verrassend dat alle huidige browser-engines verschillende prioriteitsstrategieën hebben geïmplementeerd, die geen van alle optimaal zijn.

Er zijn ook problemen aan de serverzijde, wat ertoe leidt dat veel servers de prioriteitstelling slecht of helemaal niet implementeren. In het geval van HTTP/1.x heeft het afstemmen van de serverzijde verzendbuffers om zo groot mogelijk te zijn geen nadeel, behalve de toename van het geheugengebruik (inruilen van geheugen voor CPU), en is het een effectieve manier om de doorvoersnelheid van een webserver. Dit geldt niet voor HTTP/2, aangezien gegevens in de TCP-verzendbuffer niet opnieuw geprioriteerd kunnen worden als een verzoek om een nieuwe, belangrijkere bron binnenkomt. Voor een HTTP/2-server is de optimale grootte van de verzendbuffer dus het minimale hoeveelheid data die nodig is om de beschikbare bandbreedte volledig te benutten. Hierdoor kan de server onmiddellijk reageren als een verzoek met een hogere prioriteit wordt ontvangen.

Dit probleem van grote buffers die knoeien met (her)prioritering bestaat ook in het netwerk, waar het de naam “bufferbloat” draagt. Netwerkapparatuur buffert liever pakketten dan ze te laten vallen als er een korte burst is. Als de server echter meer gegevens verzendt dan het pad naar de cliënt kan verbruiken, worden deze buffers volledig gevuld. Deze bytes die al op het netwerk zijn “opgeslagen”, beperken het vermogen van de server om eerder een antwoord met een hogere prioriteit te verzenden, net zoals een grote verzendbuffer dat doet. Om de hoeveelheid gegevens in buffers te minimaliseren, zou een recent algoritme voor congestiebeheer, zoals BBR gebruikt moeten worden gebruikt.

Deze testsuite die wordt beheerd door Andy Davies, meet en rapporteert hoe verschillende CDN- en cloudhostingservices presteren. Het slechte nieuws is dat slechts 9 van de 36 services de juiste prioriteiten stellen. Figuur 22.16 laat zien dat voor sites die een CDN gebruiken, ongeveer 31,7% niet de juiste prioriteiten stelt. Dit is gestegen van 26,82% vorig jaar, voornamelijk als gevolg van de toename van het Google CDN-gebruik. In plaats van te vertrouwen op de door de browser verzonden prioriteiten, zijn er enkele servers die een prioriteitsschema aan de serverzijde implementeren, waarbij de hints van de browser worden verbeterd met extra logica.

CDN Prioriteer
correct
Desktop Mobiel
Zonder CDN Onbekend 59,47% 60,85%
Cloudflare Pass 22,03% 21,32%
Google Fail 8,26% 8,94%
Amazon CloudFront Fail 2,64% 2,27%
Fastly Pass 2,34% 1,78%
Akamai Pass 1,31% 1,19%
Automattic Pass 0,93% 1,05%
Sucuri Firewall Fail 0,77% 0,63%
Incapsula Fail 0,42% 0,34%
Netlify Fail 0,27% 0,20%
Figuur 22.15. Ondersteuning voor HTTP/2-prioriteitstelling in veelgebruikte CDN’s.

Voor niet-CDN-gebruik verwachten we dat het aantal servers dat correct HTTP/2-prioriteitstelling toepast aanzienlijk kleiner zal zijn. De HTTP/2-implementatie van NodeJS ondersteunt bijvoorbeeld geen prioritering.

Vaarwel server push?

Server push was een van de extra functies van HTTP/2 die voor enige verwarring en complexiteit zorgde om in de praktijk te implementeren. Push probeert te voorkomen dat een browser/cliënt moet wachten om een HTML-pagina te downloaden, die pagina te parsen en pas dan te ontdekken dat er extra bronnen nodig zijn (zoals een stylesheet), die op hun beurt moeten worden opgehaald en geparseerd om nog meer dependencies te ontdekken (zoals lettertypen). Al dat werk en rondreizen kost tijd. Met server push kan de server in theorie gewoon meerdere reacties tegelijk verzenden, waardoor extra roundtrips worden vermeden.

Helaas, met TCP-congestiecontrole in het spel, begint de gegevensoverdracht zo langzaam dat niet alle activa kan worden gepusht totdat meerdere roundtrips de overdrachtssnelheid voldoende hebben verhoogd. Er zijn ook implementatieverschillen tussen browsers als het cliëntverwerkingsmodel niet volledig was overeengekomen. Elke browser heeft bijvoorbeeld een andere implementatie van een push cache.

Een ander probleem is dat de server niet weet welke bronnen de browser al in de cache heeft opgeslagen. Wanneer een server iets probeert te pushen dat ongewenst is, kan de cliënt een RST_STREAM frame verzenden, maar tegen de tijd dat dit is gebeurd, heeft de server mogelijk al alle gegevens verzonden. Dit verspilt bandbreedte en de server heeft de mogelijkheid verloren om onmiddellijk iets te verzenden dat de browser echt nodig had. Er waren voorstellen om klanten in staat te stellen de server te informeren over hun cachestatus, maar deze leden aan privacyproblemen.

Zoals te zien is in figuur 20.17 hieronder, gebruikt een zeer klein percentage van de sites server push.

Cliënt HTTP/2 pagina’s HTTP/2 (%) gQUIC pagina’s gQUIC (%)
Desktop 44.257 0,85% 204 0,04%
Mobiel 62.849 1,06% 326 0,06%
Figuur 22.16. Pagina’s die HTTP/2 of gQUIC server push gebruiken.

Als we verder kijken naar de verdelingen voor gepushte activa in figuur 22.18 en 22.19, pusht de helft van de sites 4 of minder bronnen met een totale grootte van 140 KB op desktop en 3 of minder bronnen met een grootte van 184 KB op mobiel. Voor gQUIC is desktop 7 of minder en mobiel 2. De ergste beledigende pagina duwt 41 activa over gQUIC op desktop.

Percentiel HTTP/2 Grootte (KB) gQUIC Grootte (KB)
10 1 3,95 1 15,83
25 2 36,32 3 35,93
50 4 139,58 7 111,96
75 8 346,70 21 203,59
90 17 440,08 41 390,91
Figuur 22.17. Distributie van gepushte middelen op desktop.
Percentiel HTTP/2 Grootte (KB) gQUIC Grootte (KB)
10 1 15,48 1 0,06
25 1 36,34 1 0,06
50 3 183,83 2 24,06
75 10 225,41 5 204,65
90 12 351,05 18 453,57
Figuur 22.18. Distributie van gepushte activa op mobiel.

Als we kijken naar de frequentie van push per inhoudstype in figuur 22.20, zien we 90% van de pagina’s scripts pushen en 56% CSS. Dit is logisch, aangezien dit kleine bestanden kunnen zijn die zich doorgaans op het kritieke pad bevinden om een pagina weer te geven.

Figuur 22.19. Percentage pagina’s dat specifieke inhoudstypen pusht

Gezien de lage acceptatie en na te hebben gemeten hoe weinig van de gepushte bronnen daadwerkelijk nuttig zijn (dat wil zeggen, ze komen overeen met een verzoek dat nog niet in de cache is opgeslagen), heeft Google de intentie om push-ondersteuning van Chrome te verwijderen voor zowel HTTP/2 als gQUIC. Chrome heeft ook geen push geïmplementeerd voor HTTP/3.

Ondanks al deze problemen zijn er omstandigheden waarin server push voor verbetering kan zorgen. De ideale use case is om een pushbelofte veel eerder te kunnen verzenden dan de HTML-respons zelf. Een scenario waarin dit kan profiteren is wanneer een CDN in gebruik is. De “dode tijd” tussen het CDN dat het verzoek ontvangt en het ontvangen van een antwoord van de oorsprong kan intelligent worden gebruikt om de TCP-verbinding op te warmen en activa te pushen die al in de cache zijn opgeslagen op het CDN.

Er was echter geen gestandaardiseerde methode om aan een CDN-edge-server te signaleren dat een activa moest worden gepusht. Implementaties hebben in plaats daarvan de vooraf geladen HTTP-link-header hergebruikt om dit aan te geven. Deze eenvoudige benadering lijkt elegant, maar maakt geen gebruik van de dode tijd voordat de HTML wordt gegenereerd, tenzij de headers worden verzonden voordat de daadwerkelijke inhoud gereed is. Het triggert de edge om bronnen te pushen wanneer de HTML aan de rand wordt ontvangen, wat zal strijden met de levering van de HTML.

Een alternatief voorstel dat wordt getest, is RFC 8297, dat een informatieve 103 (Early Hints) reactie definieert . Hierdoor kunnen headers onmiddellijk worden verzonden, zonder dat u hoeft te wachten tot de server de volledige responsheaders heeft gegenereerd. Dit kan worden gebruikt door een oorsprong om gepushte bronnen naar een CDN voor te stellen, of door een CDN om de cliënt te waarschuwen voor bronnen die moeten worden opgehaald. Momenteel is de ondersteuning hiervoor vanuit zowel cliënt- als serverperspectief echter erg laag, maar blijft groeit.

Op weg naar een beter protocol

Laten we zeggen dat een cliënt en server zowel HTTP/1.1 als HTTP/2 ondersteunen. Hoe kiezen ze welke ze willen gebruiken? De meest gebruikelijke methode is TLS Application Layer Protocol Negotiation (ALPN), waarbij cliënten een lijst met protocollen die ze ondersteunen naar de server sturen, die kiest voor degene die het bij voorkeur gebruikt voor die verbinding. Omdat de browser moet onderhandelen over de TLS-parameters als onderdeel van het opzetten van een HTTPS-verbinding, kan hij tegelijkertijd ook onderhandelen over de HTTP-versie. Omdat zowel HTTP/2 als HTTP/1.1 kunnen worden bediend vanaf dezelfde TCP-poort (443), hoeven browsers deze selectie niet te maken voordat een verbinding wordt geopend.

Dit werkt niet als de protocollen zich niet op dezelfde poort bevinden, een ander transportprotocol gebruiken (TCP versus QUIC) of als u geen TLS gebruikt. Voor die scenario’s begint u met alles wat beschikbaar is op de eerste poort waarmee u verbinding maakt en ontdekt u vervolgens andere opties. HTTP definieert twee mechanismen om protocollen voor een oorsprong te wijzigen na verbinding: Upgrade en Alt-Svc.

Upgrade

De Upgrade-header maakt al lange tijd deel uit van HTTP. In HTTP/1.x staat Upgrade een cliënt toe om een verzoek in te dienen met behulp van één protocol, maar de ondersteuning voor een ander protocol aan te geven (zoals HTTP/2). Als de server ook het aangeboden protocol ondersteunt, reageert deze met status 101 (Switching Protocols) en gaat verder met het beantwoorden van het verzoek in het nieuwe protocol. Als dit niet het geval is, beantwoordt de server het verzoek in HTTP/1.x. Servers kunnen hun ondersteuning van een ander protocol adverteren met behulp van een Upgrade-header bij een antwoord.

De meest voorkomende toepassing van Upgrade is WebSockets. HTTP/2 definieert ook een Upgrade-pad, voor gebruik met zijn niet-versleutelde cleartext-modus. Er is echter geen ondersteuning voor deze mogelijkheid in webbrowsers. Daarom is het niet verwonderlijk dat minder dan 3% van de cleartext HTTP/1.1-verzoeken in onze dataset een Upgrade-header in het antwoord ontving. Een zeer klein aantal verzoeken met behulp van TLS (0,0011% van HTTP/2, 0,064% van HTTP/1.1) ontving ook Upgrade-headers als reactie; dit zijn waarschijnlijk duidelijke HTTP/1.1-servers achter tussenpersonen die HTTP/2 spreken en/of TLS beëindigen, maar de Upgrade-headers niet correct verwijderen.

Alternative Services

Alternative Services (Alt-Svc) stelt een HTTP-oorsprong in staat om andere eindpunten aan te duiden die dezelfde inhoud bedienen, mogelijk via verschillende protocollen. Hoewel ongebruikelijk, kan HTTP/2 zich op een andere poort of een andere host bevinden dan de HTTP/1.1-service van een site. Wat nog belangrijker is, aangezien HTTP/3 QUIC gebruikt (vandaar UDP) waar eerdere versies van HTTP TCP gebruiken, zal HTTP/3 zich altijd op een ander eindpunt bevinden dan de HTTP/1.x- en HTTP/2-service.

Bij gebruik van Alt-Svc, doet een cliënt zoals normaal verzoeken aan de oorsprong. Als de server echter een header bevat of een frame met een lijst met alternatieven verzendt, kan de cliënt een nieuwe verbinding maken met het andere eindpunt en deze gebruiken voor toekomstige verzoeken naar die oorsprong.

Het is niet verwonderlijk dat het gebruik van Alt-Svc bijna volledig wordt gevonden in services die geavanceerde HTTP-versies gebruiken: 12,0% van de HTTP/2-verzoeken en 60,1% van de gQUIC-verzoeken ontving een Alt-Svc-header als reactie, in vergelijking met 0,055% van HTTP/1.x-verzoeken. Merk op dat onze methodologie hier alleen Alt-Svc-headers vastlegt, niet ALTSVC-frames in HTTP/2, dus de realiteit kan enigszins onderschat zijn.

Hoewel Alt-Svc naar een geheel andere host kan verwijzen, verschilt de ondersteuning voor deze mogelijkheid per browser. Slechts 4,71% van de Alt-Svc headers adverteerde een eindpunt op een andere hostnaam; dit waren bijna universeel (99,5%) advertenties voor gQUIC- en HTTP/3-ondersteuning op Google Ads. Google Chrome negeert cross-host Alt-Svc-advertenties voor HTTP/2, dus veel van de andere instanties zouden zijn genegeerd.

Gezien de zeldzaamheid van ondersteuning voor cross-host HTTP/2, is het niet verwonderlijk dat er vrijwel geen (0,007%) advertenties waren voor HTTP/2-eindpunten met behulp van Alt-Svc. Alt-Svc werd typisch gebruikt om ondersteuning voor HTTP/3 (74,6% van Alt-Svc headers) of gQUIC (38,7% van Alt-Svc headers) aan te geven.

Kijkend naar de toekomst: HTTP/3

HTTP/2 is een krachtig protocol dat in slechts een paar jaar tijd aanzienlijk is toegepast. HTTP/3 over QUIC gluurt echter al om de hoek! Na meer dan vier jaar in de maak is deze volgende versie van HTTP bijna gestandaardiseerd op de IETF (verwacht in de eerste helft van 2021). Op dit moment zijn er al veel QUIC- en HTTP/3-implementaties beschikbaar, beide voor servers en browsers. Hoewel deze relatief volwassen zijn, kan nog steeds worden gezegd dat ze zich in een experimentele staat bevinden.

Dit wordt weerspiegeld door de gebruiksnummers in de HTTP Archive-gegevens, waar helemaal geen HTTP/3-verzoeken werden geïdentificeerd. Dit lijkt misschien een beetje vreemd, aangezien Cloudflare al enige tijd experimentele HTTP/3-ondersteuning heeft, net als Google en Facebook. Dit komt voornamelijk omdat Chrome het protocol niet standaard had ingeschakeld toen de gegevens werden verzameld.

Maar zelfs de cijfers voor de oudere gQUIC zijn relatief bescheiden, goed voor minder dan 2% van de verzoeken in totaal. Dit wordt verwacht, aangezien gQUIC grotendeels werd ingezet door Google en Akamai; andere partijen wachtten op IETF QUIC. Als zodanig wordt verwacht dat gQUIC binnenkort volledig wordt vervangen door HTTP/3.

1,72%
Figuur 22.20. Het percentage verzoeken dat gQUIC gebruikt op desktop en mobiel

Het is belangrijk op te merken dat deze lage acceptatie alleen het gebruik van gQUIC en HTTP/3 voor het laden van webpagina’s weerspiegelt. Facebook heeft al een aantal jaren een veel uitgebreider gebruik van IETF QUIC en HTTP/3 voor het laden van gegevens in zijn eigen applicaties. QUIC en HTTP/3 maken al meer dan 75% van hun totale internetverkeer uit. Het is duidelijk dat HTTP/3 nog maar net is begonnen!

Nu vraagt u u misschien af: als niet iedereen al HTTP/2 gebruikt, waarom zouden we dan zo snel HTTP/3 nodig hebben? Welke voordelen kunnen we in de praktijk verwachten? Laten we de interne mechanismen eens nader bekijken.

QUIC en HTTP/3

Eerdere pogingen om nieuwe transportprotocollen op internet in te zetten zijn moeilijk gebleken, bijvoorbeeld Stream Control Transmission Protocol (SCTP). QUIC is een nieuw transportprotocol dat bovenop UDP draait. Het biedt vergelijkbare functies als TCP, zoals betrouwbare levering op volgorde en congestiecontrole om overstroming van het netwerk te voorkomen.

Zoals besproken in de sectie HTTP/1.0 tot HTTP/2, HTTP/2 multiplext meerdere verschillende streams bovenop één verbinding. TCP zelf is zich hier jammerlijk niet van bewust, wat leidt tot inefficiënties of invloed op de prestaties wanneer pakketverlies of vertragingen optreden. Meer informatie over dit probleem, bekend als head-of-line blocking (HOL-blokkering), is hier te vinden.

QUIC lost het HOL-blokkeerprobleem op door HTTP/2-streams naar de transportlaag te brengen en verliesdetectie en hertransmissie per stream uit te voeren. Dus dan zetten we HTTP/2 gewoon over QUIC, toch? Welnu, we hebben enkele van de moeilijkheden die ontstaan door het hebben van flow control in TCP en HTTP/2 al genoemd. Het zou een bijkomend probleem zijn om twee afzonderlijke en concurrerende streaming-systemen op elkaar te laten draaien. Bovendien, omdat de QUIC-streams onafhankelijk zijn, zou het knoeien met de strikte bestelvereisten die HTTP/2 vereist voor verschillende van zijn systemen.

Uiteindelijk werd het gemakkelijker geacht om een nieuwe HTTP-versie te definiëren die QUIC direct gebruikt en zo werd HTTP/3 geboren. De functies op hoog niveau lijken erg op die we kennen van HTTP/2, maar de interne implementatiemechanismen zijn behoorlijk verschillend. HPACK-headercompressie is vervangen door QPACK, waardoor handmatige afstemming van de afweging tussen compressie-efficiëntie en HOL-blokkeerrisico, en de prioriteitstelling systeem wordt vervangen door een eenvoudigere. Dit laatste kan ook worden teruggevoerd naar HTTP/2, wat mogelijk helpt bij het oplossen van de prioriteitsproblemen die eerder in dit artikel zijn besproken. HTTP/3 blijft een server-push-mechanisme bieden, maar Chrome implementeert het bijvoorbeeld niet.

Een ander voordeel van QUIC is dat het in staat is om verbindingen te migreren en ze in leven te houden, zelfs wanneer het onderliggende netwerk verandert. Een typisch voorbeeld is het zogenaamde “parkeerprobleem”. Stelt u voor dat uw smartphone is verbonden met het wifi-netwerk op de werkplek en dat u net bent begonnen met het downloaden van een groot bestand. Als u het Wi-Fi-bereik verlaat, schakelt uw telefoon automatisch over naar het mooie nieuwe mobiele 5G-netwerk. Met gewoon oud TCP zou de verbinding verbreken en een onderbreking veroorzaken. Maar QUIC is slimmer; het gebruikt een connection ID, die robuuster is voor netwerkveranderingen, en biedt een actieve connection migratie functie voor cliënten om zonder onderbreking te schakelen.

Ten slotte wordt TLS al gebruikt om HTTP/1.1 en HTTP/2 te beschermen. QUIC heeft echter een diepe integratie van TLS 1.3, waardoor zowel HTTP/3-gegevens als QUIC-pakketmetagegevens, zoals pakketnummers, worden beschermd. Door TLS op deze manier te gebruiken, wordt de privacy en beveiliging van de eindgebruiker verbeterd en wordt de voortdurende evolutie van het protocol eenvoudiger. De combinatie van transport en cryptografische handshakes betekent dat het opzetten van een verbinding slechts één RTT vereist, vergeleken met het minimum van twee van TCP en het slechtste geval van vier. In sommige gevallen kan QUIC zelfs nog een stap verder gaan en HTTP-gegevens verzenden samen met het allereerste bericht, genaamd 0-RTT. Van deze snelle verbindingstijden wordt verwacht dat ze HTTP/3 echt helpen beter te presteren dan HTTP/2.

Dus, zal HTTP/3 helpen?

Op het eerste gezicht verschilt HTTP/3 niet zo heel veel van HTTP/2. Het voegt geen belangrijke functies toe, maar verandert voornamelijk hoe de bestaande onder de oppervlakte werken. De echte verbeteringen zijn afkomstig van QUIC, dat snellere verbindingsopstellingen, grotere robuustheid en veerkracht bij pakketverlies biedt. Als zodanig wordt verwacht dat HTTP/3 het beter doet dan HTTP/2 op slechtere netwerken, terwijl het vergelijkbare prestaties biedt op snellere systemen. Als de webgemeenschap echter HTTP/3 kan laten werken, kan dat in de praktijk een uitdaging zijn.

HTTP/3 implementeren en ontdekken

Omdat QUIC en HTTP/3 over UDP draaien, is het niet zo eenvoudig als met HTTP/1.1 of HTTP/2. Meestal moet een HTTP/3-cliënt eerst ontdekken dat QUIC beschikbaar is op de server. De aanbevolen methode hiervoor is HTTP Alternative Services. Bij het eerste bezoek aan een website maakt een cliënt via TCP verbinding met een server. Het ontdekt dan via Alt-Svc dat HTTP/3 beschikbaar is, en kan een nieuwe QUIC-verbinding opzetten. De Alt-Svc-vermelding kan in de cache worden opgeslagen, waardoor volgende bezoeken de TCP-stap kunnen vermijden, maar de vermelding zal uiteindelijk verouderd worden en moet opnieuw worden gevalideerd. Dit zal waarschijnlijk voor elk domein afzonderlijk moeten worden gedaan, wat waarschijnlijk zal leiden tot het laden van de meeste pagina’s met een combinatie van HTTP/1.1, HTTP/2 en HTTP/3.

Maar zelfs als bekend is dat een server QUIC en HTTP/3 ondersteunt, kan het netwerk ertussen het blokkeren. UDP-verkeer wordt veel gebruikt bij DDoS-aanvallen en wordt standaard geblokkeerd in bijvoorbeeld veel bedrijfsnetwerken. Hoewel er uitzonderingen kunnen worden gemaakt voor QUIC, maakt de versleuteling ervan het moeilijk voor firewalls om het verkeer te beoordelen. Er zijn mogelijke oplossingen voor deze problemen, maar in de tussentijd wordt verwacht dat QUIC het meest waarschijnlijk zal slagen op bekende poorten zoals 443. En het is heel goed mogelijk dat QUIC helemaal wordt geblokkeerd. In de praktijk zullen klanten waarschijnlijk geavanceerde mechanismen gebruiken om terug te vallen op TCP als QUIC faalt. Een optie is om zowel een TCP- als een QUIC-verbinding te “racen” en degene te gebruiken die het eerst voltooit.

Er wordt gewerkt aan het definiëren van manieren om HTTP/3 te ontdekken zonder dat de TCP-stap nodig is. Dit moet echter als een optimalisatie worden beschouwd, omdat de problemen met het blokkeren van UDP waarschijnlijk betekenen dat op TCP gebaseerde HTTP blijft hangen. De HTTPS DNS-record is vergelijkbaar met HTTP Alternative Services en sommige CDN’s zijn al aan het experimenteren met deze records. Op de lange termijn, wanneer de meeste servers HTTP/3 aanbieden, kunnen browsers overschakelen naar een standaard poging dat te doen; dat zal lang duren.

HTTP/1.x HTTP/2
TLS versie Desktop Mobiel Desktop Mobiel
onbekend 4,06% 4,03% 5,05% 7,28%
TLS 1.2 26,56% 24,75% 23,12% 23,14%
TLS 1.3 5,25% 5,11% 35,78% 35,54%
Figuur 22.21. TLS-acceptatie door HTTP-versie.

QUIC is afhankelijk van TLS 1.3, dat wordt gebruikt voor ongeveer 41% van de verzoeken, zoals weergegeven in figuur 22.21. Dat laat 59% van de verzoeken over die hun TLS-stack moeten bijwerken om HTTP/3 te ondersteunen.

Is HTTP/3 al klaar?

Dus, wanneer kunnen we HTTP/3 en QUIC echt gaan gebruiken? Nog niet helemaal, maar hopelijk binnenkort. Er is een groot aantal volwassen open source-implementaties en de belangrijkste browsers hebben experimentele ondersteuning. De meeste typische servers hebben echter wat vertraging opgelopen: nginx loopt een beetje achter op andere stacks, Apache heeft geen officiële ondersteuning aangekondigd en NodeJS vertrouwt op OpenSSL, dat binnenkort geen QUIC-ondersteuning zal toevoegen. Toch verwachten we dat het aantal HTTP/3- en QUIC-implementaties in 2021 zal toenemen.

HTTP/3 en QUIC zijn zeer geavanceerde protocollen met krachtige prestatie- en beveiligingsfuncties, zoals een nieuw HTTP-prioriteitssysteem, verwijdering van HOL-blokkering en het tot stand brengen van 0-RTT-verbindingen. Deze verfijning maakt het ook moeilijk om ze correct te implementeren en te gebruiken, zoals het geval is gebleken voor HTTP/2. We voorspellen dat vroege implementaties voornamelijk zullen plaatsvinden via de vroege acceptatie van CDN’s zoals Cloudflare, Fastly en Akamai. Dit zal waarschijnlijk betekenen dat een groot deel van het HTTP/2-verkeer in 2021 automatisch kan en zal worden geüpgraded naar HTTP/3, waardoor het nieuwe protocol bijna uit de doos een groot verkeersaandeel krijgt. Wanneer en of kleinere implementaties zullen volgen, is moeilijker te beantwoorden. Hoogstwaarschijnlijk zullen we de komende jaren een gezonde mix van HTTP/3, HTTP/2 en zelfs HTTP/1.1 op internet blijven zien.

Gevolgtrekking

Dit jaar is HTTP/2 het dominante protocol geworden, dat 64% van alle verzoeken bedient, en in de loop van het jaar met 10 procentpunten is gegroeid. Startpagina’s hebben een toename van 13% in HTTP/2-acceptatie gezien, wat heeft geleid tot een gelijkmatige opsplitsing van pagina’s die worden bediend via HTTP/1.1 en HTTP/2. Het gebruik van een CDN om uw startpagina te bedienen, verhoogt de acceptatie van HTTP/2 tot 80%, vergeleken met 30% voor niet-CDN-gebruik. Er zijn nog enkele oudere servers, Apache en IIS, die resistent blijken te zijn tegen upgraden naar HTTP/2 en TLS. Een groot succes is de afname van het gebruik van websiteverbindingen als gevolg van HTTP/2-verbindingsmultiplexing. Het mediane aantal aansluitingen in 2016 was 23 ten opzichte van 13 in 2020.

HTTP/2-prioriteitstelling en server push zijn veel complexer gebleken om in het algemeen te implementeren. Bij bepaalde implementaties laten ze duidelijke prestatievoordelen zien. Er is echter een aanzienlijke belemmering voor het inzetten en afstemmen van bestaande servers om deze functies effectief te gebruiken. Er is nog steeds een groot deel van de CDN’s die het stellen van prioriteiten niet effectief ondersteunen. Er zijn ook problemen met consistente browserondersteuning.

HTTP/3 is net om de hoek. Het zal fascinerend zijn om de acceptatiegraad te volgen, te zien hoe ontdekkingsmechanismen evolueren en erachter te komen welke nieuwe functies met succes zullen worden geïmplementeerd. We verwachten dat de Web Almanac van volgend jaar interessante nieuwe gegevens zal bevatten.

Auteurs

Citaat

BibTeX
@inbook{WebAlmanac.2020.HTTP/2,
author = "Galloni, Andrew en Marx, Robin en Bishop, Mike en Pardue, Lucas en Pollard, Barry en Alam, Sawood en Wolf, Greg en Viscomi, Rick",
title = "HTTP/2",
booktitle = "De 2020 Web Almanac",
chapter = 22,
publisher = "HTTP Archive",
year = "2020",
language = "Nederlands",
url = "https://almanac.httparchive.org/en/2020/http"
}