In einem kommenden Post zum Thema Wordpress und Pagespeed Optimierung möchte ich einige Methoden aufgreifen wie man den eigenen Blog mit meist einfachen Hausmitteln beschleunigen kann. Um nicht alles in einem Endlos Posting abzuwickeln erkläre ich vorab einige Themen auf die ich dann später in den entsprechenden Passagen wieder zurück kommen werde.

Heute – Der oder das ETag

etag_stark_vereinfacht

etag_abb1
ETag steht für Entity-Tag, dieses Tag kann ein Bestandteil eines HTTP Headers sein. Das Tag beinhaltet meist einen Hexadezimalen Wert, welcher Auskunft über den Inhalt bzw der Version einer Datei gibt. Das ETag wird bei modernen Browsern zur Cachesteuerung eingesetzt und stellt quasi einen "Fingerabdruck" oft eine "Quersumme" einer Datei dar.

Beim ersten anfordern einer Datei teilt der Webserver im HTTP Header das Etag dieser mit, der Browser verarbeitet diese Datei und speichert beim ablegen im lokalem Cache das zugeordnete Etag. Ein Beispielheader des “Erstkontakts” mit eingebettetem Etag ist in Abb.1 zu sehen.

Der Browser nutzt das ETag um die Datei auf dem Webserver mit der lokal im Cache liegenden zu vergleichen, ist das ETag beider Dateien identisch so kann davon ausgegangen werden das sich an der Datei nichts geändert hat und der Cache somit Valide ist - sprich die Datei wird nicht erneut geladen sondern aus dem lokalem Cache geholt. Wird der Inhalt einer Datei modifiziert so ändert sich auch das ETag der Datei und der Webserver sendet in der Regel die Datei neu.

Erhält der Browser in einem HTML Dokument z.B. die Anweisung die Datei bild.jpg zu laden prüft er zuerst ob eine bild.jpg im lokalem etag_abb2Cache liegt. Wenn dies so ist, und lokal ein ETag dazu gespeichert wurde, wird dem Webserver in der Bildanfrage direkt “mitgeteilt” welche Version der Browser lokal gespeichert hat. Dies Geschieht in der Form:

If-None-Match: "877f3628b738c76a54"

Eine Beispiel für einen vom Browser, zur validierung, verschickten Etag ist in Abb.2 zu sehen. Stellt der Webserver nun fest das dieses ETag der bild.jpg identisch mit dem eigenen ist, so wird nur ein “304 Not Modified” entgegnet (Abb.3) anstatt die ganze Datei erneut quer durch das Internet zu senden. Weicht der Etag jedoch ab so wird der Cacheeintrag als nicht valide betrachtet. Die ebenfalls überlieferte If-Modified-Since anfrage darf bei einem nicht passendem Etag vom Webserver nicht berücksichtigt werden. Dies hat daher in der Regel zur Folge das die Datei erneut vom Webserver übertragen wird.

Nach zugehöriger RFC2616 darf der Browser auch direkt mehrere Etags, Kommagetrennt, in einem Header anfragen. Dieses Verhalten habe ich in freier Wildbahn aber noch nicht beobachten können.

etag_abb3unterschiedliche Etag Typen

Ohne nun trocken die RFC zu rezitieren möchte ich nur kurz auf Technische Unterschiede der Etags eingehen, wem das Technische Bla Bla bereits zu viel wird kann diesen Absatz in aller Ruhe überspringen ^^

In der Theorie könnte ein Etag ein zufällig generierter Wert sein, dies ist aber unsinnig da der Wert ja aufzeigen soll ob sich eine Datei verändert hat oder nicht. Daher haben sich im Apache folgende drei Methoden etabliert; Zum einen wäre da die Methode MTime (Last Modified) Information des Dateisystems, nach dieser ändert sich das Etag nur dann wenn die Datei im Filesystem des Servers neu geschrieben wird. (z.B. neue Version via FTP hochgeladen) Eine weitere Möglichkeit ist die Generierung des Tags anhand der Dateigröße, Size. Dies ist jedoch alleinstehend recht uninteressant denn eine exakte Dateigröße kann bei kleinen Änderungen schnell zum Nebeneffekt führen das neue Grafiken im Browser nicht angezeigt werden. Die dritte Möglichkeit ist die INode der Datei im Filesystem. Ohne nun in Dateisystemfunktionen abzutauchen; (Da schreiben andere Menschen ganze Bücher von) Die Inode ist platt gesagt die Hausnummer einer Datei im Dateisystem. Diese ist alleine wie auch die Size nicht tauglich als Etag. Anders als bei “Size” gibt es hier sogar noch einen weiteren Nachteil, verwendet man über mehrere Server verteilte Dateisysteme (Stichwort CDN) so ist die Inode von Webserver zu Webserver unterschiedlich.

Eine wesentlich Ressourcen intensivere Möglichkeit wäre z.B. bei dynamischem PHP Content einen Etag manuell anhand eines selbst generierten Hashwertes des Contents zu generieren.

Neben den eigentlichen Typen gibt es noch die Unterscheidung in starke und schwache Etags, diese Mitteilung sendet ebenfalls der Webserver beim Erstkontakt. Ein starker Etag darf eigentlich nur dann verwendet werden wenn man sagen kann das alle Daten die diesen Etag verwenden dann auch absolut identisch sind (Bit-für-Bit). Nutzt man z.B. nur eine der oben aufgeführten Methoden so müsste dies als schwacher Etag gekennzeichnet werden denn in der Theorie können ja duzende Dateien auf dem Webserver z.B. die exakte MTime haben. Ein schwacher tag wird durch ein vorangestelltes W/ gekennzeichnet.

Beispiel:           ETag: W/"877f3628b738c76a54"

Verwendung im Apache

Im Apache Webserver ist die Verwendung des ETags anhand der FileETag Direktive möglich, als Parameter werden die im vorherigem Absatz beschriebenen Methoden akzeptiert. Je nach Hostkonfiguration ist das Etag per Default nicht eingeschalten, hat man Zugriff auf seine Apache Config so kann man dies manuell durch den Eintrag:

FileETag All

in der httpd.conf nachholen. Wird es vom Hoster nicht untersagt kann die Direktive auch direkt in der .htaccess mit selben Befehl gesetzt werden. Ist beides nicht möglich oder führt zu einem “Serverfehler 500” so fragt man am besten beim Hoster nach ob dies für den eigenen Virtuellen Host eingeschaltet werden könnte.

Unsinnige Verwendung des Etags

Nicht immer ist es sinnvoll ein Etag auch zu verwenden, bei statischen Inhalten die sich niemals ändern werden ist ein Etag unnötiger Kommunikationsaufwand. Vielleicht ist schon mal aufgefallen das einige Große Webseiten ihre statischen Inhalte wie Bilder von einer anderen Subdomain liefern, dies hat unter anderem den Vorteil das man hier die Header global für die Subdomain einstellen kann. Nehmen wir an man betreibt eine Newsseite die pro Tag mehrere Artikel veröffentlicht, in den Artikel sind passende Bilder vorhanden die das beschriebene dokumentieren. In der Regel ändern diese Bilder sich nicht sondern werden bei Veröffentlichung des Beitrages online gestellt und verbleiben unverändert dort. Hier nun den Browser und Webserver jedes mal eine Etag Validierung durchführen zu lassen ist unsinnig da man davon ausgehen kann das die Bilder sich nicht verändern. Um dies zu vermeiden setzt man auf das Bilderverzeichnis, oder Subd omain, FileETag None. Statt des tags verwendet man nur den max-age Header mit einer sehr hohen Angabe. (Angabe in Sekunden z.B. 31536000 für ein Jahr) Aber dazu mal in einem anderem Posting mehr ;)

Um dem angesprochenem Problem, mit Etags bei über mehrere Servern verteilten Seiten, Herr zu werden ist es Sinnvoll dem Apache mitzuteilen das er die Inode Methode nicht berücksichtigen soll. Der passende Aufruf wäre: FileETag MTime Size
Damit wird der Etag nur aus Modified Time und Dateigröße gebildet.

Besseres Etag Handling in PHP

Ok, letzter Absatz ;) Endspurt. Verfügt man über eine in PHP geschriebene Webseite so kann man den Etag bei z.B. Contentseiten oder Stylesheets selbst ausgeben. In Contentseiten nimmt man einfach den darzustellenden Inhalt und generiert daraus einen md5 diesen Hash übergibt man per Funktion in den HTTP Header:  header(‘ETag: "’.md5($content).’"’);

Möchte man das ganze weiter führen so könnte man einen Wrapper via mod_rewrite für JS und CSS Daten auf dem Webserver bauen, dieser würde dann die CSS Files dynamisch anhand ihres Inhaltes mit einem Sicherem Etag versehen. Bei unserem Hostingprojekt 3Q für kleine-mittelständische Unternehmen handhaben wir dies erfolgreich um die Clientperformance zu steigern und Probleme mit nicht mehr validen Caches zu verhindern. Wichtig beim setzen des Etags über PHP ist natürlich das dann das komplette Handling, also auch das auswerten der “If-None-Match” Header über PHP erfolgen muss. Wie genau würde hier nun den sowieso schon sehr gedehnten Rahmen sprengen, bei Interesse komme ich darauf gerne mal in einem gesondertem Posting zurück.

Weiterführende Links / Quellen

Amazon Logo Diesen Blog unterstützen?
Bestell dir doch etwas bei Amazon. Nutze diesen speziellen Link, es kostet dich nichts extra und für jeden Kauf darüber erhalte ich eine kleine Gutschrift. Danke!
✉ Marco Götze//

Kommentare

noch 5 Einträge