Web Performance - Teil 1

Nicht nur für Benutzer ist es ein Thema. Auch Suchmaschinen, insbesondere Google, legen großen Wert darauf: Eine schnelle Ladezeit der Webseite bzw. der Applikation.

TL;DR

  • Low hanging fruits: HTTP/2 + Server Push + Cache
  • Tipps für HTTP/1.1 gelten nicht für HTTP/2
  • Stellen Sie auf HTTP/2 um. Heute.

HTTP/2 und Caching

Das seit 2015 in der RFC 7540 veröffentlichte Protokoll HTTP/2 hat gegenüber seinem Vorgänger HTTP/1.1 entscheidende Vorteile. Das haben viele Webmaster erkannt, immerhin nutzen mittlerweile schon 33,9% der Top 10 Millionen Webseiten bereits HTTP/2 (Stand März 2019).

Was spricht also dafür oder dagegen von HTTP/1.1 auf HTTP/2 umzustellen? Gleich vorweg: Nichts. Allerdings muss man ein paar Rahmenbedingungen beachten, um auch alle Vorteile von HTTP/2 zu nutzen. (Der einfachen Lesart halber verwendet der Autor im Folgenden statt HTTP/2 das gebräuchliche Kürzel “H2”).

HTTP/1.1

Beim alten Protokoll fragt der Client jede Ressource einzeln beim Server an. Das erfolgt üblicherweise in dieser Reihenfolge:

  1. Laden des HTML-Dokumentes (z.B. index.html)
  2. Browser interpretiert HTML, lädt erkannte Inhalte nach (Style Sheets, JavaScript, Bilder, Fonts)
  3. Browser rendert alle Inhalte dann zusammen, wenn sie beim Client eingetroffen sind.

Das alte Protokoll sieht bis zu sechs gleichzeitige Verbindungen von Client zu Server vor, so dass auch nur maximal sechs Elemente gleichzeitig übertragen werden. Besteht eine Webseite aus z.B. 60 Elementen muss der Client in 10 Runden jeweils sechs Streams anstoßen, um alle Elemente zu laden.

Bisherige Abhilfe (mit H2 nicht mehr empfohlen):

  • Sprites:
    Zusammenfassen mehrerer Bilder zu einem Bild
  • Pseudo-DNS-Namen mit vHosts:
    Umgeht die Beschränkung auf sechs Streams
  • JS-Dateien zusammenfassen:
    Es wird nur eine, große “globale” Datei geladen


HTTP/2 aka H2

Die Beschränkung des HTTP/1.1 auf höchstens sechs Streams ist in H2 aufgehoben. Vielmehr werden jetzt in einer einzigen Verbindung mehrere Elemente gleichzeitig übertragen. Das passiert nicht sequenziell hintereinander, sondern verschränkt im binären Mulitplex-Verfahren.

Das hat weitreichende Folgen: Die bisherigen “Best Practices”, die für HTTP/1.1 noch der heilige Gral der Performance-Optimierung waren, gelten nun schlicht nicht mehr. Im Gegenteil, sie sind sogar schädlich. Hat ein Webmaster die statischen Ressourcen unter pseudo vHosts (static-01.website…, static-02.website…, etc.) verfügbar gemacht, müssen nun bei H2 zu jedem einzelnen vHosts TCP-Session aufgebaut werden. Das bedeutet nicht nur mehr TCP Overhead sonder auch mehrere DNS-Abfragen. Insgesamt führt das dazu, dass die “alten Tricks” bei H2 zu einer eher schlechterern Performance als ohne Tricks führen.

Wer mit dem Gedanken spielt, auf H2 umzustellen, sollte sich von den alten Tricks verabschieden. Für Entwickler neuer Projekte ist das eine gute Nachricht, denn sie müssen sich keine Gedanken darüber machen, wie Webseiten-Elemente zu gestalten sind, dass sie schnell laden. Darum kümmert sich ab sofort das Protokoll. Manchmal kann’s so einfach sein.

HTTP/1.1Abb 1: Aufruf einer Websiete über HTTP/1.1

Im Bild sieht man die Ladezeit einer Webseite mit 100 Einzelbildern. Insgesamt benötigt der Browser knapp 5 Sekunden, um alle Elemente zu laden und darzustellen.

HTTP/1.1Abb 2: Gleiche Webseite, jetzt mit HTTP/2

Die exakt gleiche Webseite (gleicher Server, gleicher Client, gleiche Internet-Verbindung) jetzt über HTTP/2. Die Ladezeit ist auf unter eine halbe Sekunde zurück gegangen! HTTP/2 bewirkt in diesem Beispiel eine mehr als 10-mal schnellere Ladezeit. Insbesondere bei langsameren Mobilfunk-Anschlüssen, die eine höhre Latenz als Festnetzanschlüsse haben, macht sich der positive Effekt noch deutlicher bemerkbar.

Wer das live selbst ausprobieren will, kann das hier tun:
https://http2.golang.org/gophertiles

Server Push

Noch einen oben drauf setzt die neue Funktion “Server Push”. Dabei werden dem Client vom Server Daten mitgeschickt, die der Client eigentlich noch gar nicht angefragt hat.

Beispiel: Der Client fragt das Dokument “index.html” an. Der Server entscheidet, neben der index.html auch gleich die passende CSS- und JavaScript-Datei mitzuschicken, schließlich wird sie vom Client ja ohnehin benötigt. Der Client weiß zwar zu diesem Zeitpunkt noch nicht, dass er die Daten benötigt, hat sie dann aber vorrätig, wenn er die index.html interpretiert. Zusätzliche Requests enfallen, die Seite kann direkt korrekt dargestellt werden.

Klingt sehr einfach. Wollen Sie jetzt Ihrem Webmaster Bescheid geben, dass er nicht nur H2 sondern gleich noch Server Push für alle CSS und JS-Dateien einschalten soll? Stop! Das sollten Sie unterlassen.

Schließlich soll der Server nur dann CSS- oder JavaScript-Dateien schicken, wenn der Client diese Daten noch nicht hat. Würden diese Daten bei jedem Request auf eine HTML-Datei immer gesendet werden, werden sie mehrfach und unnötig übertragen.

Der Trick: Der Client sendet dem Server ein Info mit, falls er bestimmte Assets schon geladen hat. Das kann im Header des Requests gemacht werden, z.B. als Cookie. Der Server kann dann erkennen, dass er diese zusätzlichen Daten nicht mehr senden muss.

Cache

Bilder, JavaScript, Style Sheets und Schriftarten können üblicherweise per Cache im Client vorgehalten werden. Die alten Mechanismen des Client-Caching gelten auch für H2 genau so weiterhin.

Beispiel:

  • Last-Modified: Sat, 23 Mar 2019 21:02:37 GMT
  • ETag: “12345678-12345”
  • Cache-Control: max-age=86400
  • Expires: Sun, 24 Mar 2019 21:02:37 GMT

Fazit

Es gibt keinen Grund, H2 nicht sofort zu verwenden. Machen Sie es. Heute. Prüfen Sie, ob noch alte “Tricks” online sind, die für HTTP/1.1 eine bessere Performance versprachen. Werfen Sie diese alten Tricks raus. Fertig.