HTTP/2 Server Push

HTTP/2 Server Push är en valfri funktion i HTTP/2- och HTTP/3- nätverksprotokollen som gör att servern kan skicka resurser till en klient innan klienten begär dem. Server Push är en prestandateknik som syftar till att minska latensen genom att ladda resurser förebyggande, även innan klienten vet att de kommer att behövas. I praktiken resulterar Server Push ofta i slöseri med bandbredd eftersom servern sällan vet vilka resurser som redan laddas av klienten och sänder samma resurs flera gånger, vilket resulterar i nedgångar om resurserna som pressas konkurrerar om bandbredd med resurser som faktiskt efterfrågades.

HTTP/2 Server Push är inte en meddelandemekanism från server till klient. Istället används pushade resurser av klienten när den annars kan ha producerat en begäran om att få resursen ändå.

Grundläggande koncept

Till exempel, i fallet med en webbplats med tre resurser: index.html, styles.css och script.js, när en användare, via sin webbläsare, ansluter till Wikipedias webbserver för att få hemsidan, hämtar de automatiskt index.html. När webbläsaren analyserar HTML- texten i index.html, hittar den instruktioner som kräver styles.css och script.js. Vid den tidpunkten kommer webbläsaren att utfärda förfrågningar om att få dessa andra två filer. För att sammanställa hela webbsidan kommer webbläsaren att stapla sådana förfrågningar när den gradvis upptäcker webbplatsens sammansättning.

Med HTTP/2 Push kan servern ta initiativet genom att ha regler som utlöser att innehåll skickas redan innan det efterfrågas. I det här exemplet vet servern att alla som begär index.html kommer att behöva styles.css och script.js, så den kan skicka dem till klienten omedelbart utan att vänta på att klienten ska begära dem. Om det görs på rätt sätt, när webbläsaren slutar analysera index.html, skulle överföringen av styles.css och script.js redan ha börjat, eller till och med slutförts, vilket tar bort fördröjningen att behöva begära dessa och vänta på att de kommer fram.

Hur HTTP/2 PUSH fungerar på protokollnivå

Push fungerar över HTTP/2, som i sin kärna är ett ramprotokoll, vilket innebär att information utbyts i grupper av byte som kallas ramar. Dessutom är ramar en del av strömmar och strömmar identifieras med ett nummer. Strömnumret finns i varje ram som ett binärt fält. Strömmar tillåter matchning av förfrågningar till svar, t.ex. måste svaret på begäran GET /index.html vid ström 3 också vara vid ström 3.

Det finns olika typer av ramar och alla har olika funktioner. HTTP/2 har bara ett fåtal av dessa typer, och vi behöver inte alla för att förklara grunderna. Här är de intressanta för denna beskrivning:

  • HEADERS ram. Som namnet antyder har denna typ av ram HTTP-rubriker. När webbläsaren skickar den till servern signalerar den att en begäran görs. När den skickas av servern till webbläsaren, signalerar den att ett svar på en tidigare begäran eller push-löfte skickas.
  • PUSH_PROMISE ram. Denna ram skickas av servern till webbläsaren för att börja pusha en resurs. Den innehåller även HTTP-rubriker. Den typ av rubriker som finns i en PUSH_PROMISE-ram är dock rubriker som normalt skulle finnas i en begäran. Detta skiljer sig från de svarsrubriker som en server normalt skulle skicka. Begärans URL, till exempel, finns i PUSH_PROMISE-ramen som den HTTP/2-specifika :path-pseudo-headern, liksom :authority-pseudo-headern för att indikera en värd. Andra rubriker som kan finnas i en PUSH_PROMISE och som vissa webbläsare använder är cachehuvuden, till exempel if-none-match.
  • DATA ramar. Dessa ramar skickas i endera riktningen för att bära det faktiska innehållet i en resurs eller innehållet som webbläsaren POST eller PUT skickar till servern.
  • RST_STREAM ramar. Dessa ramar tjänar många syften. En av dem är att webbläsaren signalerar till servern att en pushad ström inte behövs.

När servern vill pusha en resurs förbereder den en PUSH_PROMISE-ram, som skapar den på bästa möjliga sätt för att förföra webbläsaren att använda det pushade innehållet. Sedan annekterar servern PUSH_PROMISE-ramen till svarsdelen av en normal webbläsarinitierad ström. Den faktiska datan för den pushade resursen skickas dock i en ny ström som startas av servern och därmed med ett jämnt nummer.

Webbläsaren håller den skickade datan i en tillfällig "karantän"-zon tills den bestämmer sig för att använda den. Senare, varje gång webbläsaren ska göra en faktisk förfrågan, undersöker den innehållet i alla mottagna push-löften för att se om det liknar den begäran den vill göra. Servern behöver dock inte vänta till det ögonblicket för att börja skicka data för den utlovade resursen. Efter att PUSH_PROMISE-ramen har skickats på den webbläsarinitierade strömmen, kan servern skicka vad som skulle vara svarsrubriker med hjälp av en HEADERS-ram i den nya serverinitierade strömmen, och senare kan den skicka data från resursen med hjälp av DATA-ramar. Och när som helst kan webbläsaren avbryta alla överföringar genom att använda RST_STREAM.

Så här skulle det fungera i föregående exempel. Om servern är HTTP/2 PUSH-klar, när den tar emot en förfrågan till index.html kan den förutsäga att förfrågningar till styles.css och script.js följer tätt i efterhand. Så det ger push-löften att komma en bit före händelserna. Så här kan saker och ting se ut, i ordningsföljd efter förekomst och strömningsnumren:

  • Servern tar emot HEADERS-ram som frågar efter index.html i ström 3, och den kan förutsäga behovet av styles.css och script.js.
  • Servern skickar en PUSH_PROMISE för styles.css och en PUSH_PROMISE för script.js, igen i ström 3. Dessa ramar motsvarar ungefär en webbläsares begäran.
  • Servern skickar en HEADERS-ram i ström 3 för att svara på begäran om index.html.
  • Servern skickar DATA-ram(ar) med innehållet i index.html, fortfarande i ström 3.
  • Servern skickar HEADERS-ram för svaret på styles.css i ström 4 notera det jämna strömnumret och sedan för svaret på script.js i ström 6.
  • Servern skickar DATA-ramar för innehållet i styles.css och script.js, med deras respektive strömnummer.

Push-löften skickas så tidigt som möjligt för att webbläsaren ska ha dem långt före eventuella upptäckter. Lägg märke till att HTTP-rubriker (särskilt länka till nyckelordet 'preload') kan avslöja webbadresser som webbläsaren behöver hämta, och en ivrig webbläsare skulle börja fråga efter resurserna när de såg dessa rubriker. Därför skickas push-löften bäst före ens svarsrubriker i strömmen där de är bifogade.

Genomföranden

HTTP/2 Server push implementeras successivt, till exempel implementerade Nginx webbserver den i version 1.13.9 i februari 2018.

Enligt Google Chrome- teamet används Server Push i HTTP/2 och gQUIC sällan, och de pushade resurserna är oftare oanvända än de används. De har föreslagit att ta bort funktionen från Chrome och Chromium.