apache/2.2.* deflate_module work around für ein HTTP-Fehler
Edgar Ehritt
- webserver
Hallo,
bis eben hatte ich über ein Problem mit der CPU-Last grübeln müssen, für das ich eine Lösung, die vielleicht den einen oder anderen interessieren könnte, fand. Generell gehe ich aber davon aus, dass dieses Problem sicher noch die nächsten Jahre bestehen wird, sodass mein derzeitig eher als experimentell zu bezeichnendes Szenario, realer werden könnte. Denn das Dilemma hat mit der Infrastruktur des Apachen selbst zu tun. Folgender Hintergrund:
OS: Linux 2.6.29.3
Webserver: Apache/2.2.11 (alle MPMs)
Server Module: deflate_module, header_module
Laut Bugliste krebst Apache seit dem Jahr 2006 mit einem (weiteren) Problem durch deflate_module herum. Der Etag-Response-Header war i. V. m. content-encoding RFC-widrig und führte zu Problemen mit Cache-Proxies. Soweit zu erkennen ist, hat man dies durch ein Suffix "-%{transformation}" am ETag - äh - 'behoben'. Die Variable %{transformation} nimmt als Inputfilter _derzeit_ nur den Wert "gzip" an. So sieht das dann ganz verkürzt als Response aus:
HTTP/1.1 200 OK
Last-Modified: Wed, 12 Jul 2006 03:20:01 GMT
Etag: "677d6-48f2-41859ec369a40"-gzip
Vary: Accept-Encoding
Content-Encoding: gzip
Ein Browser senden darauf an die selbe Ressource etwa einen solchen eingekürzten Request:
GET /index.html HTTP/1.1
Accept-Encoding: gzip,deflate
If-Modified-Since: Wed, 12 Jul 2006 03:20:01 GMT
If-None-Match: "677d6-48f2-41859ec369a40"-gzip
Wer die Infrastruktur bezüglich der Filter innerhalb des Apachen kennt, ahnt sicher was kommt; kurz: Apache prüft _ohne_Einbezug_von_Filtern_ den Wert If-None-Match des Requests gegen den Wert Etag der auszuliefernden Ressource und findet keine Übereinstimmung, da er Äpfel (Wert: "677d6-48f2-41859ec369a40"-gzip) mit Birnen (Wert: "677d6-48f2-41859ec369a40") vergleicht. Suffix "-gzip" würde erst vom Filter deflate_module angehängt werden. Fände Apache eine Übereinstimmung, müsste die Ressource weder komprimiert werden noch gesendet werden. (Andere Idiotien, die sich im Quellcode des deflate_module befinden, wie zum Beispiel, dass der Apache mit der Konfigurationen ContentDigest On den message digest vor der Kompression und nach der Kompression (doppelt) berechnet, sind dagegen nicht so schlimm.)
In wieweit das Problem auch auf älteren Versionen und/oder anderen Zweigen (Apache/1.3, Apache/2.0) äquivalent anwendbar ist, weis ich nicht und bitte um Rückmeldungen!
header_module, was per Voreinstellung _nicht_Teil_ der Standardmodule Apaches ist, bietet eine Möglichkeit, dieses Problem zu beheben - jedoch erst seit der Version 2.2.4(!) des Webserver. Durch die Direktive RequestHeader edit können eingehende Anfragen -für diesen Fall effektiv- vorverarbeitet werden, da header_module kein Filter ist.
<IfModule headers_module>
RequestHeader edit If-None-Match "\"(.*)\".*" "\"$1\""
# derzeit, wie geschrieben, ginge auch
RequestHeader edit If-None-Match "(.*)-gzip" $1
</IfModule>
Andernfalls (ältere Versionen / andere Versionszweige) hilft - nach wie vor - die konsequente Deaktivierung des deflate_module, vorherige Kompression der Ressourcen und Auslieferung via Apache mittels content negotiation. Dies kommt im Eigentlichen CONTENT-encoding nach. ;)
Gruß aus Berlin!
eddi