HTTP/2: Welchen Vorteil bringt der neue Webstandard?

Diesen Artikel habe ich bereits im Firmen Blog von menadwork GmbH veröffentlicht: Düsseldorf, am 04.11.2015 von Lars Moelleken


Der im Mai 2015 veröffentlichte Webstandard HTTP/2 bewirkt, dass Webseiten schneller angezeigt werden. Die Kompatibilität von HTTP/2 ist in fast allen aktuellen Webbrowsern gegeben, wer dies jedoch einsetzen will muss zwangsläufig ein SSL-Zertifikat einsetzen, so dass die Webseite verschlüsselt übertragen wird.

In Kürze vorab:

Haben Browser und Ser73_221_de_ver im vorherigen HTTP/1.x Standard aus dem Jahr 1996 noch sehr viel Zeit mit „Warten“ verbracht, können durch den neuen Webstandard HTTP2 Webseiten schneller angezeigt werden.

Die Kompatibilität von HTTP/2 ist in fast allen aktuellen Webbrowsern gegeben – ein guter Grund, auf das neue Protokoll zu setzen. Serverseitig unterstützt der Apache Webserver (v2.4.17) den entsprechenden Webstandard.

73_222_de

Wer HTTP/2 einsetzen will muss zwangsläufig ein SSL-Zertifikat einsetzen, so dass die Webseite verschlüsselt (via https://) übertragen wird.

Und nun zu den Details …

Grundsätzliches: So funktioniert das Internet

73_224_de

Um zu erklären, was HTTP/2 ist, sollte man zuerst verstehen wie das Internet grundsätzlich funktioniert. Alle Daten im Computer und auch im Internet sind digital, das bedeutet so viel wie „die Daten werden intern binär verarbeitet“ (z.B. a => 01100001, b => 01100010, c => 01100011).

Um diese Daten nun an einen anderen Computer zu übertragen, benötigt jeder Computer, jedes Smartphone usw. eine eindeutige Adresse, die sogenannte IP-Adresse.

Die Daten werden bei der Übertragung im Internet bzw. im Netzwerk zu sogenannten Paketen zusammengefasst. Jedes Paket wird zusätzlich mit der Information bestückt von welcher IP-Adresse diese gesendet und an welche IP-Adresse diese gesendet werden sollten, solche Informationen nennt man Header-Informationen.

Um nun eine Verbindung von einem zum anderen Computer herzustellen, nutzt man sogenannte Netzwerkprotokolle: Diese definieren einen Standard, so dass unterschiedliche Systeme miteinander kommunizieren können. Im Internet werden UDP (User Datagram Protocol) bzw. TCP (Transmission Control Protocol) verwendet.Das Netzwerkprotokoll UDP ist im Gegensatz zu TCP verbindungslos, d. h. es wird keine eindeutige Verbindung aufgebaut. UDP wird z. B. verwendet um eine Domain (menadwork.com) in die entsprechende IP-Adresse aufzulösen.

Diese Netzwerkprotokolle nutzen unterschiedliche Ports, welche man sich wie Türen vorstellen kann: Jeder Computer hat – ähnlich einem Haus – eine eindeutige Adresse (IP-Adresse) und bietet Platz für unterschiedliche Dinge. diese Dinge können z. B. Webseiten (Port:80), E-Mails (Port:143) oder Dateien (Port:21) sein. Dies ist der Grund, warum man beispielsweise eine Webseite auch wie folgt aufrufen kann: „menadwork.com:80„.

Auch diese Ports sind zumindest von 0 bis 1023 mit fest definierten Anwendungsprotokollen (z. B. HTTP: 80, IMAP: 143, FTP: 21) belegt, so dass man verschiedene Anwendungen über TCP bzw. UDP ansteuern kann.

Die Einführung von HTTP/1.0 und HTTP/1.1

HTTP (Hypertext Transfer Protocol) wurde zusammen mit den Konzepten für die URL und HTML geschaffen und 1996 als HTTP/1.0 publiziert. Für jede verknüpfte Datei in einem HTML-Dokument – wie z. B. Bilder – wurde eine neue TCP-Verbindung aufgebaut.

Im Jahr 1999 wurde dann HTTP/1.1 publiziert, welches unter anderem Pipelining ermöglicht: Dabei werden mehrere HTTP-Anfragen über eine TCP/IP-Verbindung geschickt, so dass man den Overhead beim Verbindungsauf- und -abbau nicht bei jeder HTTP-Anfrage (Bilder, JavaScript-Dateien oder CSS-Dateien) hat. Jedoch ist dieses Feature bei fast allen Browsern standardmäßig deaktiviert und kann somit meistens nicht genutzt werden. Zudem kollidiert hier mal wieder Theorie und Praxis, da zwar theoretisch mehrere Anfragen direkt nacheinander abgearbeitet werden können, aber das sogenannte „head-of-line blocking“-Problem tritt auf: Denn die Anfragen werden noch immer nach dem FIFO-Prinzip (First In – First Out) verarbeitet und die erste Anfrage muss vor der zweiten Anfrage vom Server verarbeitet werden. Man kann sich dies wie die Kasse beim Supermarkt vorstellen: Nur, weil man mehrere Kunden an einer Kasse bedient heißt dies nicht, dass diese schneller bedient werden, solange man auch hier nach dem FIFO-Prinzip arbeitet.

Der neue Webstandard HTTP/2

HTTP/2 wurde im Mai 2015 veröffentlicht und unterstützt unter anderem das Zusammenfassen von mehrere HTTP-Anfragen über ein Multiplexverfahren. Beim Multiplexen werden Daten gebündelt und gemeinsam übertragen. Außerdem werden die Daten und Header nun komprimiert übermittelt und Daten werden binär kodiert übermittelt.

Webseite via HTTP/1.1 laden Webseite via HTTP/2 laden
1. Erstellt sechs bis acht HTTP-Verbindungen zum Server 1. Erstellt eine Verbindung zum Server
2. Anfrage der HTML-Seite 2. Anfrage der HTML-Seite
3. Empfang der HTML-Seite 3. Empfang der HTML-Seite
4. Decode der HTML-Seite 4. Decode der HTML-Seite
5. Erstellt sechs bis acht Verbindungen zu Dateien in der HTML-Seite, ohne Prioritäten

(unkomprimierten, plain-text Header)

5. Empfang von allen Dateien in der HTML-Seite, mit Prooritäten

(komprimierte, binary Header)

6. Die Verbindung wartet, bis die angeforderte Datei ankommen ist (Dateien werden über den gemultiplexten

Stream gesendet)

7. Fordert die nächste Datei, auf der jetzt offenen Verbindung an
8. Wiederhole Punkt 6-7 bis alle Dateien angekommen sind
9. Schließe sechs bis acht HTTP-Verbindungen 8. Schließe die eine Verbindung

Quelle: https://www.nginx.com/wp-content/uploads/2015/09/NGINX_HTTP2_White_Paper_v4.pdf

73_227_de

Statement von Google: „Google observed an ~88% reduction in the size of request headers and an ~85% reduction in the size of response headers after enabling compression. This amounted to a saving of between 45 and 1142 ms in the overall page load time.“ Quelle: http://www.chromium.org/spdy/spdy-whitepaper

Diese binären Daten werden als Streams bezeichnet und können mit unterschiedlichen Priorisierungen angefordert werden, zum Beispiel 1. HTML, 2. JavaScript, 3. CSS, 4. Fonts, 5. Bilder. Zudem kann man theoretisch mit der Funktion „Server-Push“ auch Dateien zum Client senden, welche dieser gar nicht angefragt hat, so könnte man HTML, CSS und Font senden, wenn nur das HTML angefragt wurde, jedoch ist dieses Funktion z. B. in der aktuellen Version von Apache (v2.4.17) noch nicht implementiert.

Im offiziellen Standard ist HTTP/2 zwar auch ohne SSL (https://) geplant, aber die Browser-Hersteller bieten HTTP/2 nicht ohne Verschlüsselung an. Da SSL-Zertifikate jedoch momentan nicht kostenlos sind, haben Mozilla, die Electronic Frontier Foundation (EFF), Cisco, Akamai und IdenTrust eine neue SSL-Zertifizierungsstelle (CA) mit dem Namen „Let’s Encrypt“ gegründet, welche in Zukunft kostenlose Zertifikate ausstellt.

 

UPDATE: (04.11.2015)

Let’s Encrypt hat heute sein Beta-Programm gestartet, sodass man über wenige Zeilen auf der Kommandozeile bereits ein gültiges SSL-Zertifikat nutzen kann.

  git clone https://github.com/letsencrypt/letsencrypt
  cd letsencrypt
  ./letsencrypt-auto --agree-dev-preview --server \
  https://acme-v01.api.letsencrypt.org/directory certonly
 Wer noch einen weiteren Grund benötigt, seine Webseite über eine verschlüsselte Verbindung (SSL) auszuliefern, der sollte sich das neue Feature von Firefox 44 anschauen, welches eine Warnung anzeigt, wenn Login-Daten über eine nicht verschlüsselte Verbindung übermittelt werden.

Was ändert sich für Webentwickler?

Jede Technik, welche HTTP-Anfragen reduziert, ist mittels HTTP/2 obsolet, da einzelne kleine HTTP-Anfragen nun schneller abgearbeitet werden als eine große Anfrage. Zu diesen Techniken zählen z. B. das Zusammenfassen (concat) von JavaScript- und CSS-Dateien oder auch das Sprite-Image, welches mehrere kleine Bilder zu einem Bild darstellt. Aber auch das aufteilen von HTTP-Request auf verschiedene Subdomains ist nicht länger sinnvoll, da ansonsten wieder neue TCP-Verbindungen aufgebaut werden müssen. Zudem ist das „Inlinen“ von z. B. Bildern via Data-URIs (data:image:png;base64,…) nicht mehr zweckmäßig.

Mit der „Server-Push-Funktion“ können bereits einige Webserver umgehen, so dass man serverseitig bestimmen kann, dass bestimmte Dateien zusätzlich ausgeliefert werden sollen, wenn z. B. eine HTML-Datei angefragt wird. Dafür müssen in den meisten Fällen bestimmte Header-Daten definiert werden (z. B. X-Associated-Content: „/foo.css“:1,“/bar.js“:1,“/baz.js“:1).

Alle diese Änderungen spielen Frameworks wie Polymer in die Hände, da der Quelltext hier in einzelne Pakete bzw. Komponenten geordnet ist und somit schneller übertragen werden kann.

Was ändert sich für Administratoren?

Administratoren müssen zunächst Server aktualisieren, da z. B. nur die aktuelle Version von Apache (v2.4.17) HTTP/2 unterstützt. Darüber hinaus müssen Pakete für die verschiedenen Linux-Distributionen müssen gebaut werden.

Indem via HTTP/2 die HTTP-Anfragen über eine TCP-Verbindung laufen, werden weniger Verbindungen pro User zum Server aufgebaut, der Web-Server benötigt weniger Speicher und die CPU-Last wird verringert.

HTTP HTTPS SPDY (HTTP/2)
Max. pages/s 16.3 @ 120 users 15.9 @ 120 users 98 @ 777 users
Response @ 100 users 1.1s 1.3s 1.1s
Response @ 120 users 1.4 s 1.5s 1.1s
Response @ 200 users 7.1s 7.8s 1.1s
Response @ 777 users 70.2s 72s 2.7s
First error 405 Users 225 Users 884 Users

Quelle: http://www.neotys.com/blog/performance-of-spdy-enabled-web-servers/

Server-Anfrage Speicherverbrauch (für die selbe Beispiel-Anfrage)
HTTP 59 MB
HTTPS 79 MB
SPDY (HTTP/2) 24 MB

Quelle: http://www.neotys.com/blog/performance-of-spdy-enabled-web-servers/

Vergleich der Ladezeiten

73_232_de

Außerdem sollte man sich ein wenig mehr mit dem Thema SSL auseinandersetzen, so kann man z. B. über den „Strict Transport Security„-Header die Ladezeit von HTTP/2 Seiten weiter reduzieren. Dies geschieht, indem die Nutzung von HTTPS sozusagen gecacht wird und Anfragen via HTTP direkt via HTTPS verarbeitet werden.

Quellen:

Apache & HTTP/2: http://www.apache.org/dist/httpd/CHANGES_2.4.17
„Can I use“ HTTP/2: http://caniuse.com/#search=http%2F2
Info zu HTTP/2: http://http2-explained.readthedocs.org/en/latest/
FAQ zu HTTP/2: https://http2.github.io/faq/
Spec zu HTTP/2: https://http2.github.io/http2-spec/
Präsentation zu HTTP/2 (von @derSchepp): https://schepp.github.io/HTTP-2/#/
Präsentation zu HTTP/2 (von @mnot): https://www.mnot.net/talks/http2-expectations/#/
W3C – preload: http://w3c.github.io/preload/
nghttp2 – Server-Push: https://nghttp2.org/documentation/nghttpx.1.html#server-push
heise: HTTP/2: http://www.heise.de/netze/artikel/Wie-HTTP-2-0-das-Surfen-beschleunigt-2164146.html
Free SSL: https://letsencrypt.org/2015/10/19/lets-encrypt-is-trusted.html
heise: Free SSL: http://www.heise.de/netze/meldung/Let-s-Encrypt-Meilenstein-zu-kostenlosen-SSL-Zertifikaten-fuer-alle-2679600.html

Demos:

https://http2.akamai.com/demo
http://http2.golang.org/gophertiles?latency=0

HTTP/2 ist angekommen | Apache 2.4.17

Was ist HTTP/2? Diese Frage haben andere bereits ausführlich geklärt. https://http2.github.io/faq/ :) daher wollen wir dies heute in Kombination mit dem Apache Webserver ausprobieren.

Im Februar 2015 hat Google den Support für SPDY bereits zugunsten von HTTP/2 eingestellt. Und die Kompatibilität von HTTP/2 ist in fast allen aktuellen Webbrowsern gegeben, so das es bereits seit einiger Zeit keinen Grund gibt, nicht auf das neue Protokoll zu setzen. Seit dieser Woche unterstützt auch der Apache Webserver (2.4.17) das Protokoll, „Stefan Eissing“ hat das Module „mod_http2“ gesponsert, welches wir im folgenden testen werden.

Installation unter Ubuntu 14.04 via Fremdquellen (PPA)

Warnung: „Zusätzliche Fremdquellen können das System gefährden.“
–> https://wiki.ubuntuusers.de/paketquellen_freischalten/ppa

Zu beginn stellen wir sicher, dass SPDY nicht mehr verwendet wird.

a2dismod spdy

Und deinstallieren dies am besten direkt, falls dies über den Paket-Manager installiert wurde.

apt-get purge mod-spdy-beta

service apache2 restart

Um die Quellen (/etc/apt/sources.list.d/) nicht manuell zu ändern, installieren wir kurzerhand das Programm „add-apt-repository“ via:

aptitude install software-properties-common

# Web: https://launchpad.net/~ondrej/+archive/ubuntu/apache2
# Issues: https://github.com/oerdnj/deb.sury.org/issues
#
add-apt-repository ppa:ondrej/apache2

Falls es beim Hinzufügen des Keys zu Problem kommt, kann man dies auch manuell durchführen:

apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 4F4EA0AAE5267A6C

Anschließend installieren wir das Update via „aptitude„, sodass wir mehr Kontrolle über den Update-Prozess haben.

apt-get update; aptitude

aptitude

Nach der Installation können wir das „http2“-Module wie folgt aktivieren.

cd /etc/apache2/mods-available/

vim http2.load

# Depends: setenvif mime socache_shmcb
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so

vim http2.conf

<IfModule http2_module>
ProtocolsHonorOrder On
Protocols h2 h2c http/1.1
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Und anschließend muss das Module nur noch aktiviert werden:

a2enmod http2

service apache2 restart

Um zu testen, ob HTTP/2 via https genutzt wird, können wir z.B. direkt im Chrome nachschauen. Dafür öffnen wir einfach die Seite chrome://net-internals und nutzen oben links im DropDown-Menü den Punkt „HTTP/2“.

chrome_http2

 

Quellen:

Server-Probleme im Zeitalter von HTTP/2

Ich hatte heute das Problem, dass einige Webseiten extrem langsam bis gar nicht mehr vom Webserver ausgeliefert wurden. Also prüfe ich als erstes mit „htop“ ob die CPU ausgelastet ist, danach via „iotop“ die Festplatte, mit „iftop“ den Traffic, mit „netstat“ die offenen Netzwerkverbindungen und via „free“ wie viel Speicher noch zur Verfügung steht. Und die Hardware war nicht mal ansatzweise ausgelastet. Nach einigen weitere Tests ist schnell aufgefallen, dass nur „http“-Anfragen betroffen waren. Selbst eine einfach GET-Anfrage eines Bildes ist zeitweise fehlgeschlagen.

Die größte Änderung am Vortag war, dass eine Webseite mit zirka 1 Millionen Usern komplett auf „https://“ umgestellt wurde. Daher habe ich kurzfristig wieder auf „http://“ umgestellt, jedoch ohne eine Änderung festzustellen.

linux_kill_9
Quelle: http://www.reddit.com/r/ProgrammerHumor/comments/27vcjg/signal_kill/

Zeitgleich ist aufgefallen das der MySQL-Prozess nicht korrekt neugestartet ist, somit liefen zwei MySQL-Server (ps aux | grep mysql), wobei nur einer wirklich Anfragen angenommen hat. Der zweite Prozess wollte sich nicht mehr via „service mysql restart“ neustarten lassen, hat die Fehlermeldung „Can’t connect to local MySQL server through socket ‚/var/run/mysqld/mysql.sock‘“ produziert und wurde daher via „kill“ getötet und anschließend der MySQL-Server neugestartet.

Dies hat auch das Problem mit den langsamen Webseiten behoben, zumindest kurzweilig. Danach hatten „http“-Anfragen wieder Probleme. Im „error“-Logfile (/var/log/apache2/error.log) vom Apache habe ich dann endlich eine Meldung gefunden, welche mich auf die richtige Fährte gebracht hat: „server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers settings“

website-download-with-spdy

Vor einer Woche hatte ich das „SPDY„-Protokoll auf dem Server aktiviert und getestet, alles hat ohne Probleme funktioniert. Dann habe ich gestern die bereits erwähnte Webseite komplett auf „https“ umgeroutet und noch immer kein Problem festgestellt. Am Morgen wurden dann Newsletter versendet und eine ganze Menge Leute sind in kurzer Zeit via „https“ auf die Webseite gekommen, da das „SPDY“-Protokoll nur mit „https“ arbeite haben diese User nicht die üblichen Anfragen  (HTTP 1.0 / 1.1) an den Server gestellt, sondern durch Multiplexverfahren mehrere Anfragen gleichzeitig verarbeitet werden.

http-diagram-spdy
Quelle: http://stackoverflow.com/questions/10480122/difference-between-http-pipeling-and-http-multiplexing-with-spdy

Die erste Intuition, dass es etwas mit der „SSL“-Umstellung zu tun hatte war schon mal nicht verkehrt, jedoch hatte ich die entsprechenden Einstellungen nur in der „.htaccess“ auskommentiert, die „https“-Verbindungen jedoch nicht zurück nach „http“ umgeleitet …

RewriteCond %{SERVER_PORT} !^443
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

… und den Apache nicht neugestartet, somit waren die aktuellen Anfragen noch aktiv und Nutzer welche auf der Webseite waren haben weiter „https“-Anfragen generiert.

Im nächsten Schritt musste nun festgestellt werden, wie viele Apache Prozesse bzw. gleichzeitige Verbindungen einstellt werden mussten und wie man dies am besten konfiguriert. Die Apache-Dokumentation sagt hierzu folgendes:

„The MaxRequestWorkers directive sets the limit on the number of simultaneous requests that will be served … For non-threaded servers (i.e., prefork), MaxRequestWorkers translates into the maximum number of child processes that will be launched to serve requests. The default value is 256; to increase it, you must also raise ServerLimit.“

Also habe ich via …

netstat -anp | grep -E ":80|:443" | grep ESTABLISHED | wc -l

… bzw. zur groben Orientierung via …

ps aux | grep apache | wc -l

… herausgefunden wie viele http(s) Anfragen bzw. Apache Prozesse aktuell vorhanden sind und habe diese Einstellungen zunächst entsprechend hoch eingestellt („/etc/apache2/mods-enabled/mpm_prefork.conf“), so dass die Webseite wieder korrekt funktionierte. Anschließend habe ich die zuvor beschriebenen Befehle verwendet, um die endgültigen Einstellungen zu ermitteln. Die folgenden Einstellungen sind an einen Server mit 32G Arbeitsspeicher getestet und sollte nicht einfach übernommen werden.

<IfModule mpm_prefork_module>
ServerLimit                                    1024
StartServers                                        1
MinSpareServers                              32
MaxSpareServers                          250
MaxRequestWorkers              1024
MaxConnectionsPerChild             0
</IfModule>

————————————————–

Lösung: Wenn man das „SPDY“-Modul aktiviert und später auf „SSL“ umstellt, sollten man vorher die Apache-Konfiguration anpassen! ;)

————————————————–

Es folgt noch ein kleines Tutorial, wie man „SPDY“ für Apache installieren kann. Jeder der bereits auf „nginx“ umgestiegen ist, kann dies ggf. bereits ohne weitere Installation ausprobieren: http://ginx.org/en/docs/http/ngx_http_spdy_module.html

Installation: SPDY für Apache 2.2

Download: https://developers.google.com/speed/spdy/mod_spdy/

# z.B.: wget https://dl-ssl.google.com/dl/linux/direct/mod-spdy-beta_current_amd64.deb
dpkg -i mod-spdy-*.deb
apt-get -f install

Installation: spdy für Apache 2.4

apt-get -y install git g++ apache2 libapr1-dev libaprutil1-dev patch binutils make devscripts fakeroot
cd /usr/src/
git clone https://github.com/eousphoros/mod-spdy.git
## wähle deine Apache Version  
# z.B.: git checkout apache-2.4.7
# z.B.: git checkout apache-2.4.10
cd mod-spdy/src
./build_modssl_with_npn.sh
chmod +x ./build/gyp_chromium
rm -f out/Release/mod-spdy-beta*.deb
BUILDTYPE=Release make linux_package_deb
dpkg-i out/Release/mod-spdy-beta*.deb

Video:

Links:

– Projekt Webseite: http://www.chromium.org/spdy/

– Quellcode: https://code.google.com/p/mod-spdy/wiki/GettingStarted

– „mod_spdy“ für Apache 2.2: https://developers.google.com/speed/spdy/mod_spdy/

– „mod_spdy“ für Apache 2.4: https://github.com/eousphoros/mod-spdy

– Online-Test für „SPDY“: https://spdycheck.org/

– Präsentation zum Thema „HTTP/2“ von @derschepphttps://schepp.github.io/HTTP-2/

– Browserkompatibilität mit „SPDY“: http://caniuse.com/#search=spdy

„gzip“ für Webseiten

Um das Verhalten von „gzip / deflate“ besser zu verstehen, möchte ich als erstes ganz kurz auf den Algorithmus hinter der Komprimierung eingehen. Dafür muss man zumindest zwei Grundlegende Theorien verstehen. Zum einen die sogenannte Huffman-Kodierung, dabei geht darum Text mit möglichst wenig Bits (0 || 1) zu übersetzen.

Es folgt ein einfaches Beispiel:

String: „im westen nichts neues“

Die Länge des Strings beträgt 22 Zeichen, was bei einem 4-Bit-Code (0000, 0001 …) eine Anzahl von 22 * 4 Bit = 88 Bit ergeben würde.

Berücksichtigt man jedoch die Häufigkeit der wiederkehrenden Zeichen, kann man für bestimmte Zeichen, welche oft im String vorkommen, kürzere Bit-Codes nutzen.

huff1

Als erstes Zählen wir die Anzahl der vorkommenden Zeichen. Die Zeichen welche die geringste Häufigkeit aufweisen werden anschließend als erstes miteinander Verknüpft und jeweils addiert.

huff4

Wie man bereits erkennt bekommen die Zeichen welche nicht so häufig auftreten längere Strecken und somit gleich auch längere Bit-Codes.

huff7

Wenn man alle Zweige verknüpft hat, entsteht daraus dann ein Binär-Baum, welcher von oben nach unten gelesen wird.

Die eindeutigen Bit-Codes sind nun z.B.: 00 für e, 100 für n, 1011 für t und so weiter. Nun benötigen wir nur noch 73 Bit anstatt 88 Bit, um den String binär darzustellen. ;)

Das zweite Prinzip hat auch mit Wiederholung von Zeichen zu tun. Die sogenannte „LZ77″ Kompression, welche wiederkehrende Muster in Strings erkennt und durch Referenzen von vorherigen Strings ersetzt.

Es Folgt ein einfaches Beispiel:

String: „Blah blah blah blah blah!“

 vvvvv     vvvvv     vvv
Blah blah blah blah blah!
      ^^^^^     ^^^^^

Wenn man nun die Wiederholung durch eine Referenz angibt, welche aus der Länge des Wortes (“ blah“ = 5) und Länge der Wiederholungen. („lah blah blah blah“ = 18). Daraus ergibt sich anschließend der folgende komprimierte Text.

Blah b(5,18)!

… aber nun endlich zum praktischen Teil! Es folgen ein paar Beispiele und Überlegungen im Zusammenhang mit Webseiten / Webservern.

1.) „gzip“, ABER weniger ist manchmal mehr

Bei kleinen Webseiten und schwachen V-Servern kann es vorkommen, dass die serverseitige Komprimierung im Gesamtkontext keinen Geschwindigkeitsvorteil bietet, da die Komprimierung ggf. mehr Overhead (Payload, CPU-Rechenzeit, Verzögerung der Auslieferung) mit sich bringt als es Vorteile (geringere Dateigröße) bietet. Zumal viele Dateien (Bilder, CSS, JS) nach dem ersten Seitenaufruf im Cache sind und nicht wieder vom Server ausgeliefert werden müssen. Gerade für mobile Geräte macht die Komprimierung jedoch fast immer Sinn, daher würde ich die Komprimierung immer aktivieren!

PS: hier noch ein Blog-Post zum Thema Webseiten Beschleunigen

moelleken_org-gzip
mit gzip
moelleken_org-nogzip
ohne gzip

GRÜN = Download
GELB = Wartet
BLAU = Verbindung zum / vom Server

Bei „nginx“ gibt es zudem ein Modul (HttpGzipStaticModule) welches direkt vorkomprimierte Dateien ausliefert, anstatt diese bei Anfrage zu komprimieren. Jedoch muss man bisher selber dafür sorgen, dass eine entsprechende Datei mit dem selben Timestamp vorhanden ist. (z.B.: main.css & main.css.gz) Falls jemand hier eine Alternative oder ein einfaches Script zum erstellen der zu komprimierenden Dateien hat, meldet euch bitte bei mir oder einfach in den Kommentaren.

2.) „gzip“, ABER nicht für alles

Zunächst sollte man bereits komprimierte Dateien (z.B. JPEG, PNG, zip etc.) nicht noch zusätzlich via „gzip“ ausliefern, da die Dateigröße im schlimmsten Fall noch steigen kann oder zumindest wird für sehr wenig Dateigröße, sehr viel CPU-Zeit auf der Server (Komprimierung) und auf dem Client (Dekomprimierung) verbraucht.

gzip_images

Ich empfehle an dieser Stelle mal wieder die „.htaccess„-Datei vom HTML5-Boilerplate, welche bereits viele Einstellungen für den Apache-Webserver liefert. Außerdem gibt es dort auch eine optimierte Konfiguration „nginx.conf“ für den nginx-Webserver.

3.) „gzip“, ABER nicht immer

Die „gzip“-Komprimierung kann Ihre Stärken bei größeren Dateien viel besser ausspielen, da wir ja bereits im theoretischen Teil gelernt haben, dass die Komprimierung auf Wiederholungen aufbaut und wenn wenig wiederkehrende Zeichen und Muster vorhanden sind lässt es sich schlecht komprimieren.

Beim „nginx“-Webserver kann man die minimale zu bearbeitende Dateigröße angeben, sodass eine 6 Byte große Datei mit dem Inhalt „foobar“ bei schwacher „gzip“ nicht auf 40 Byte vergrößert wird.

gzip_small_file

4.) „gzip“, ABER nicht so hoch

Zudem sollte man nicht mit der höchsten Komprimierungsstufe komprimieren, da man pro Komprimierungsstufe immer weniger Erfolg bei immer mehr CPU-Zeit bekommt. Man sollte weniger stark komprimieren und dadurch Rechenleistung /-zeit einsparen, um die Webseite schneller ausliefern zu können.

gzip_level

test2_1.js.gz (schwache Komprimierung)
test2_2.js.gz (normale Komprimierung)
test2_3.js.gz (starke Komprimierung)

5.) „gzip“ + Minifizierung

Durch Minifizierung von CSS und JS kann man die Dateigröße ebenfalls reduzieren, auch wenn man nicht an die Dateigröße von komprimierten Dateien herankommt, außerdem sinkt der Erfolg der Komprimierung, da wir durch die Minifizierung bereits einige Wiederholungen minimiert haben.

Es folgt ein Beispiel mit „jquery.js / jquery.min.js“:

Zustand

Größe der Datei

gewonnene Größe durch die Komprimierung

nicht minifiziert + nicht komprimiert Datei

250 kB (¼ MB)

nicht minifiziert + schnelle Komprimierung

76,3 kB

173,7 kB

nicht minifiziert + normale Komprimierung

68,3 kB

181,7 kB

nicht minifiziert + hohe Komprimierung

68 kB

182 kB

minifiziert + nicht komprimiert Datei

82,3 kB

minifiziert + schnelle Komprimierung

30,8 kB

51,5 kB

6.) „gzip“ + Komprimierung verbessern

Im Gegensatz zur Programmierung, wo man Wiederholungen vermeidet, sollte man im Frontend (HTML, CSS) gezielt Wiederholungen nutzen, um die Komprimierung zu optimieren. So zeigt  das folgende Beispiel wie man die Dateigröße durch die korrekte Positionierung von Attributen der HTML-Tags verbessern kann.

Zwei Dateien mit dem selben Dateigröße, nur die Reihenfolge der Attribute in der zweiten HTML-Dateien („test1_2.html“) wurden nicht in der selben Reihenfolge angegeben.

html_order_3
test1_1.html
html_order_2
test1_2.html

html_order

Wie man in dem Bild erkennen kann, haben wir die Dateigröße der HTML-Datei um zirka 10% reduziert indem wir den Komprimierungsalgorithmus  bei der Arbeit unterstützen. ;)

Videos:

 

Webseiten Analyse

Zurück zur „Webseiten beschleunigen“ – Übersicht

1.) Webseiten Analyse

Dies ist der Erste Teil von meiner Blog-Reihe „Webseiten beschleunigen“. Um die ursprüngliche Ladegeschwindigkeit deiner Webseite zu prüfen, installieren wir uns zwei Erweiterungen für Firefox.

Firebug +
YSlow

ggf. kann man sich auch nach die nachfolgenden Links anschauen, jedoch habe ich mit der Kombination „ Firebug + YSlow“ sehr gute Erfahrungen gemacht, daher folgt nun diesbezüglich ein kleines Video.

 

 

Alternative von Google:

Firebug +
Page-Speed

 

Alternative Online-Analyse:

Bisher habe ich nur zwei Online-Analyse-Dienste gefunden, welche mir wirklich geholfen haben.

a.) Auf Pingdom.com kannst du die Ladezeit deiner Webseite und dessen Inhalt sehr schön in einem Graphen sehen und Schwachstellen somit sehr einfach erkennen, z.B. wenn eine externe Datei nicht erreichbar ist.

tools.pingdom.com

 

pingdom
pingdom

 

b.) Die nächste Webseite ist AOL’s WebPageTest ist ein wenig umfangreicher, so zeigt diese Webseite wie bereits beim vorherigen Link einen Graphen mit den geladen Dateien an, jedoch führt diese Webseite den Test zweimal durch, so dass die Auswirkung vom Browser-Cache simuliert wird. Außerdem gibt es eine Checkliste, wo alle Dateien noch einmal einzeln geprüft werden.

AOL’s WebPageTest

 

aol_webpagetest
aol_webpagetest

 

1.1) Webseiten Benchmark

Außerdem könnte kann die Abfragen auch direkt von der Shell aus starten z.B. mit „httperf“. Es folgt ein kleines HowTo für Debian:

sudo bash
aptitude install httperf
httperf --hog --server voku-online.de --num-conn 20 --ra 10 --timeout 5

jedoch kann ich zumindest mit der Ausgabe nicht viel anfangen, da mir diese vielen Zahlen auf Anhieb nicht viel sagen, daher folgt eine kleine Anleitung, wie man aus diesen Werten einen Graphen zeichnet

cd /usr/src/
wget http://www.xenoclast.org/autobench/downloads/debian/autobench_2.1.2_i386.deb
dpkg -i autobench_2.1.2_i386.deb
autobench --single_host --host1  www.test.de --uri1 /10K --quiet
--low_rate 20  --high_rate 200 --rate_step 20 --num_call 10
--num_conn  5000 --timeout 5 --file results.tsv
aptitude install gnuplot
bench2graph results.tsv result.ps

so nun laden wir die Datei „result.ps“ z.B. per WinSCP auf unsern Windows Rechner und öffnen die Datei mit Ghostscript

Hier mein Beispiel:

 

webserver_bench
webserver_bench

 

(1) req_rate: request rate, requests per second
(2) con_rate: connection rate, connections per second
(3) min_rep_rate: minimum reply rate, replies per second
(4) avg_rep_rate: average reply rate, replies per second
(5) max_rep_rate: maximum reply rate, replies per second
(6) stddev_rep_rate: standard deviation for reply rate
(7) resp_time
(8) net_io: Net I/O, KB per second
(9) error

Link:
autobench

 

Anstatt diesen Vorgang komplett per Hand zu bewerkstelligen, kann man auch folgende Webseite dazu nutzen:

-> loadimpact.com

So kannst du herausfinden, wie sich deine Webseite verhält, wenn sehr viele Besucher diese besuchen. Anbei das Ergebnis von diesem Blog. (Nach meiner Optimierung per „PHP XCache“ + „Nginx“ + „W3 Total Cache

 

loadimpact

 

Hier ist ein schneller Überblick darüber, was diese Kurve nun aussagt. -> loadimpact.com/forum/

Webserver beschleunigen

Zurück zur „Webseiten beschleunigen“ – Übersicht

5.) Webserver beschleunigen

5.1) Apache-Module deaktivieren


Ggf. kann man auch einige Module (Erweiterungen) von Apache abschaltet, wer z.B. auf seiner Webseite gar keine SSL-Verschlüsselung verwendet, könnte das entsprechende Modul deaktivieren.

a2dismod  ssl
/etc/init.d/apache2 restart

Die momentan aktiven Erweiterungen kann man unter „/etc/apache2/mods-enabled/“ einsehen, die installierten Erweiterungen sind unter „/etc/apache2/mods-available/“ zu finden.

Dynamische Seiten:
mod_log_config erlaubt die access_log-Dateien in div. Formaten.
mod_cgi braucht man, wenn man CGI zulassen will.
mod_suexec erlaubt CGIs als ein bestimmter User zu laufen.
mod_perl braucht man nicht um Perl als CGI auszuführen!
mod_php5 ist schneller als suphp (aber nicht so sicher).
mod_suphp führt php Skript mit den Rechten des entsprechenden webs aus.
mod_include erlaubt die Verwendung von SSI.

URL-Manipulationen:
mod_alias braucht man zum Einblenden von virtuellen Verzeichnissen.
mod_rewrite erlaubt URL-Manipulationen, kostet aber Performance.
mod_autoindex & mod_dir erlauben eine Navigation ohne index.html
mod_userdir erlaub User-URLs mit z.B.: www.huschi.net/~huschi/
mod_negotiation analysiert Accept-Anfragen.
mod_vhost_alias erlaubt das Anlegen von virtuellen Hosts.

Environment- & Header-Manipulation:
mod_mime setzt automatisch den richtigen Header anhand der Dateiendung.
mod_env & mod_setenvif erlauben die modifizierung von ENV-Variablen.
mod_expires erlaubt die HTTP-Header Manipulation des Expires-Date (Verfall-Zeit).
mod_ssl erlaubt die Verwendung von SSL (https).

Zudem kann man folgende Option in der Apache-Konfiguration ändern, so dass man DNS-Lookups reduziert.

vim /etc/apache2/apache2.conf

HostNameLookups off

5.2) Reverse Proxy (Nginx)

nginx_logo
Wir wollen unsere Webseite mal wieder ein wenig beschleunigen, dies können wir auf verschiedenen Wegen bewerkstelligen, heute beschäftigen wir uns mit dem Reverse-Proxy vor einem Webserver, in diesem Beispiel nutzen wir für diesen Zweck Nginx + apache2. Der große Vorteil von einen Proxy vor dem Webserver ist, dass mehrere Anfragen gleichzeitig gestellt werden könne, um die Performance von statischen Daten zu steigern. Die Anfragen an dynamische Inhalte werden dann noch immer an einen zweiten bzw. an mehrere Webserver, hinter dem Proxy weitergereicht.

Wer sich jetzt fragt, warum man nicht komplett auf Nginx umsteigen sollte, da die Benchmarks zeigen, dass dieser schneller ist als der Apache Webserver, derjenige hat nicht bedacht, dass bei diesen Tests nur die Reaktionen des Webservers auf eine gewisse Anzahl von Anfragen geprüft wird, wenn man jedoch mit „nginx + fcgi“ viele php-Dateien verarbeiten möchte, ist ein „apache + mod_php“ schneller, zudem kann man diese Daten z.B. mittels eAccelerator zusätzlich cachen, was die Geschwindigkeit von php-Daten noch einmal positiv beeinflusst.

Update: Inzwischen konnte ich die ganzer Sache ausgiebig testen und setzte momentan eine Kombination aus „Varnish“ + „Nginx“ + „php5-fpm“ (+ xcache) ein, so werden die Seiten von Varnish zwischengespeichert alle neue Anfragen von Nginx entgegengenommen, Bilder etc. sofort ausgeliefert und PHP-Anfragen an einen laufendem PHP-Daemon weitergereicht, jedoch erst-einmal zurück zum Beispiel mit Nginx als Reverse-Proxy…

Als Lösung für diese Problem habe ich mir einen Nginx-Proxy gebastelt, der statische Daten (Bilder…) ausliefert und diese zusätzlich für 24 Stunden zwischenspeichert, alle andern dynamischen Inhalte (php,cgi…) werden sofort an apache durch-gereicht. In diesem Beispiel laufen sowohl der Proxy als auch Apache auf einem Server.
reverse_proxy

5.2.1.) Apache auf einem neuen Port laufen lassen

Folgende Datei öffnen…

vim /etc/apache2/ports.conf

…Port „80“ durch z.B. „127.0.0.1:8080“ ersetzen.

!!! Wichtig ist hier, darauf zu achten, dass der Apache selber nicht mehr über eine Öffentliche IP-Adresse erreichbar ist. !!!

Ggf. helfen dir die folgenden Zeilen weiter, um alle Einträge in einer Datei zu Ändern (mit vi / vim).

:%s/^80/127.0.0.1:8080/g

:%s/SERVER_IP_ADRESSE:80/127.0.0.1:8080/g

SERVER_IP_ADRESSE muss nun noch mit der IP-Adresse des Servers ersetzte werden und anschließend musst du den Apache Webserver noch neu-starten. Ggf. müssen noch weitere Dateien von Apache angepasst werden.

Mit dem folgendem Befehl kannst du prüfen, ob noch weitere Einträge (Port 80) in der Apache Konfiguration sind.

/bin/grep -wr 80 /etc/apache2/


5.2.2) Ggf. ISPConfig anpassen

Falls du z.B. ISPConfig installiert hat, werden wie Änderungen am Apache Webserver, bei der nächsten Änderung über die Admin-Oberfläche wieder verworfen, daher müssen wir das Template von ISPConfig dementsprechend anpassen.

vim ~/ispconfig/isp/conf/vhost.conf.master

NameVirtualHost 127.0.0.1:8080


5.2.3.) Reverse-Proxy: nginx installieren & konfigurieren

aptitude install nginx
vim /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
worker_rlimit_nofile 3000;
pid /var/run/nginx.pid;

# [ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log;

#google_perftools_profiles /tmp/profile/;

events {
        worker_connections 2048;
        # use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ;
        use epoll;
        multi_accept on;
}

http {
        server_names_hash_bucket_size 64;

        ## Size Limits
        client_max_body_size        10M;
        client_header_buffer_size   32k;
        client_body_buffer_size     128k;
        large_client_header_buffers 64 8k;

        ## Timeouts
        client_body_timeout   3m;
        client_header_timeout 3m;
        send_timeout          3m;
        #expires              24h;
        keepalive_timeout     120 120;

        ## General Options
        ignore_invalid_headers   on;
        keepalive_requests       100;
        limit_zone normal $binary_remote_addr 5m;
        recursive_error_pages    on;
        sendfile                 on;
        server_name_in_redirect  off;
        server_names_hash_max_size 512;
        server_tokens            off;
        set_real_ip_from 127.0.0.1;
        real_ip_header X-Forwarded-For;

        ## TCP options
        #tcp_nopush on;
        tcp_nodelay off;
        #send_lowat 12000;

        include mime.types;
        default_type application/octet-stream;

        access_log /var/log/nginx/access.log;

        log_format main '$remote_addr - $remote_user [$time_local] $status '
        '\"$request\" $body_bytes_sent \"$http_referer\" '
        '\"$http_user_agent\" \"http_x_forwarded_for\"';

        ## Cache
        open_file_cache max=1000 inactive=24h;
        open_file_cache_valid    24h;
        open_file_cache_min_uses 2;
        open_file_cache_errors   on;

        ## Compression
        gzip              on;
        gzip_static       on;
        gzip_disable      "MSIE [1-6]\.";
        gzip_buffers      32 8k;
        gzip_comp_level   5;
        gzip_http_version 1.0;
        gzip_min_length   0;
        gzip_proxied      any;
        gzip_types text/plain text/css text/xml text/javascript application/json application/xml application/xml+rss application/x-javascript image/x-icon application/x-perl application/x-httpd-cgi;
        gzip_vary         on;

        output_buffers   10 128k;
        postpone_output  1500;

        # Beispiel: Loadbalance
        #upstream webbackend  {
                #ip_hash;
                #server web1.domain.lan weight=10 max_fails=3 fail_timeout=30s;
                #server web2.domain.lan weight=1 backup;
        #}
        # Beispiel: Reverse-Proxy
        #server {
                #access_log  /var/log/nginx/access.proxy.log main;
                #error_log   /var/log/nginx/error.proxy.log;
                #listen      80;
                #server_name _;

                ## PROXY - Web
                #location ~ \.php$ {
                        #proxy_cache            cache;
                        #proxy_pass  http://127.0.0.1:8080;
                #}
        #}

        # Beispiel: HTTP Server (sollte jedoch besser unter /etc/nginx/sites-available/ angelegt werden)
        #server {
                #listen       8000;
                #listen       somename:8080;
                #server_name  somename  alias  another.alias;

                #location / {
                        #root   html;
                        #index  index.html index.htm;
                        #}
                #}

        # Beispiel: HTTPS Server (sollte jedoch besser unter /etc/nginx/sites-available/ angelegt werden)
        #server {
                #listen       443;
                #server_name  localhost;

                #ssl                  on;
                #ssl_certificate      cert.pem;
                #ssl_certificate_key  cert.key;

                #ssl_session_timeout  5m;

                #ssl_protocols  SSLv2 SSLv3 TLSv1;
                #ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
                #ssl_prefer_server_ciphers   on;

                #location / {
                #root   html;
                #index  index.html index.htm;
                #}
        #}

include /etc/nginx/proxy.conf;
include /etc/nginx/sites-enabled/*.conf;
}
vim /etc/nginx/proxy.conf
proxy_buffering            on;
proxy_cache_min_uses       3;
proxy_cache_path           /usr/local/nginx/proxy_cache/ levels=1:2 keys_zone=cache:10m inactive=24h max_size=1000M;
proxy_cache                cache;
proxy_cache_valid          200 24h;
proxy_cache_use_stale      error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_ignore_client_abort  off;
proxy_intercept_errors     on;
proxy_next_upstream        error timeout invalid_header;
proxy_redirect             off;
proxy_set_header           Host            $host;
proxy_set_header           X-Real-IP       $remote_addr;
proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffers              32 1M;
proxy_busy_buffers_size    31M;
proxy_temp_file_write_size 30M;
proxy_buffer_size          30M;
proxy_connect_timeout      90;
proxy_send_timeout         90;
proxy_read_timeout         90;
proxy_ignore_headers       Expires Cache-Control;
mkdir /usr/local/nginx/proxy_cache/
chown -R www-data:www-data /usr/local/nginx/proxy_cache/

Link:
wiki.nginx.org/NginxHttpProxyModule

/etc/init.d/apache2 restart
/etc/init.d/nginx restart

Nginx läuft nun auf Port 80 und nimmt die Anfragen von Client an und der Apache wartet auf die weitergeleiteten Anfragen von Reverse-Proxy.

Bei mir hat der cache (Zwischenspeicherung) jedoch Probleme verursacht, so dass Captcha’s nicht mehr funktioniert haben, daher habe ich diesen im Nachhinein abgeschaltet.


Links:
www.joeandmotorboat.com/2008/02/28/apache-vs-nginx


5.2.4.) Logfiles korrigieren

Nun stehen wir noch vor dem Problem, dass im Logfile von apache die IP-Adresse vom Reverse-Proxy auftauscht und zwar nur noch diese, um dies zu umgehen installieren wir nun noch folgendes…

aptitude install libapache2-mod-rpaf

Nun noch folgendes in den Vhost-Einträgen bzw. in dem ISPConfig Template ergänzen.


RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1

/etc/init.d/apache2 reload

…und schon haben wir einen Reverse-Proxy („Apache“ + „Nginx“) installiert. Unter Punkt 5.3 zeige ich wie du ganz auf Nginx setzten kannst und somit nicht zwei Webserver, betreiben & konfigurieren musst.

Browser-Cache nutzen

Zurück zur „Webseiten beschleunigen“ – Übersicht

4.) Browser-Cache nutzen

4.1) Browser-Cache manuell einstellen

Falls du keinen Zugriff auf die Konfiguration von Apache hast, kannst du den Browser-Cache folgendermaßen beeinflussen. Nun wollen wir unseren JS/CSS Dateien noch einen Header mitgeben, welcher wiederum bewirkt, dass der entsprechende Browser (Client) die Datei für eine gewisse Zeit speichert und für „neu“ hält, dies spart wieder Traffic, welchen wir nicht bezahlen müssen und außerdem beschleunigt es den Seitenaufruf.


CSS in PHP umbenennen, um den php-Code in der Datei ausführen zu können.

mv test.css test.css.php

Anschließend werden wir am Anfang der Datei folgendes mit einfügen.

<?php
require_once("gzipCSS.php");
?>

Im folgenden Beispiel wird die Datei für 3 Tage (60 * 60 * 24 * 3) gespeichert.

vim gzipCSS.php
<?php
ob_start ("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>


JS in PHP umbenennen, um den php-Code in der Datei ausführen zu können.

mv test.js test.js.php

Anschließend werden wir am Anfang der Datei folgendes mit einfügen.

<?php
ob_start ("ob_gzhandler");
header("Content-type: text/javascript; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>


Falls man die Komprimierung jedoch bereits serverseitig aktiviert hat, hatte ich das Problem, dass die Webseite nicht zu-ende geladen werden konnte, daher würde ich empfehlen auf diese Methode zu verzichten, sofern man Zugriff auf das System hat und die Einstellungen am Webserver selber einstellen kann, zumal es relativ lange dauern dürfte, bis man alle Dateien auf diese weiße optimiert hat!


Link:
www.php.net/ob_gzhandler
www.php.net/zlib


4.2) Browser-Cache serverseitig einstellen


Expires – in diesen Header-Eintrag wird, für jede Server-Antwort festgelegt, wie lange diese gültig ist. Um jedoch erst-einmal zu verstehen, was in diesem Header steht folgt ein kleines Beispiel in

PHP:

function setExpires($expires) {
header(
'Expires: '.gmdate('D, d M Y H:i:s', time()+$expires).'GMT');
}
setExpires(10);
echo ( 'This page will self destruct in 10 seconds<br />' );
echo ( 'The GMT is now '.gmdate('H:i:s').'<br />' );
echo ( '<a href="'.$_SERVER['PHP_SELF'].'">View Again</a><br />' );

nach 10 Sekunden ist diese Webseite alt und muss vom Browser erneut geladen werden.


weitere Beispiele:
www.sitepoint.com


Kommen wir nun zurück zur Konfiguration von Apache, um „expires“ zu aktivieren führen wir unter Linux Debian/Ubuntu folgendes Kommando aus.

a2enmod expires
a2enmod headers


Nun passen wir die entsprechende Konfiguration an, um bestimmte Dateien für eine gewisse Zeit clientseitig zu speichern.

vim /etc/apache2/mods-available/expires.conf
<IfModule mod_expires.c>

AddType image/vnd.microsoft.icon .ico
AddType application/javascript .js
AddType application/x-tar .tgz
AddType text/plain .c
AddType text/plain .h

ExpiresActive On
ExpiresDefault "access plus 4 houres"

ExpiresByType image/vnd.microsoft.icon "access plus 3 months"
ExpiresByType image/ico "access plus 3 month"
ExpiresByType image/x-icon "access plus 3 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/js "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType video/x-flv "access plus 1 month"
ExpiresByType video/quicktime "access plus 1 months"
ExpiresByType video/mp4 "access plus 1 months"
ExpiresByType video/mpeg "access plus 1 months"
ExpiresByType video/x-ms-wmv "access plus 1 months"
ExpiresByType audio/mpeg "access plus 1 months"
ExpiresByType audio/y-wav "access plus 1 months"
ExpiresByType application/pdf "access plus 2 weeks"
ExpiresByType application/zip "access plus 2 weeks"
ExpiresByType application/x-tar "access plus 2 weeks"
ExpiresByType application/x-download "access plus 2 weeks"
ExpiresByType application/ps "access plus 2 weeks"
ExpiresByType application/msword "access plus 2 weeks"
ExpiresByType text/css "access plus 2 weeks"
ExpiresByType application/xml "access plus 24 houres"
ExpiresByType application/xhtml+xml "access plus 24 houres"
ExpiresByType text/html "access plus 12 houres"
ExpiresByType text/htm "access plus 12 houres"
ExpiresByType text/plain "access plus 12 hours"
ExpiresByType text/xml "access plus 12 hours"

<IfModule mod_headers.c>

<FilesMatch "\\.(ico)$">
Header set Cache-Control "max-age=29030400, public"
</FilesMatch>

<FilesMatch "\\.(css|pdf|flv|jpg|jpeg|png|gif|swf)$">
Header set Cache-Control "max-age=2419200, public"
</FilesMatch>

<FilesMatch "\\.(js)$">
Header set Cache-Control "max-age=216000, private"
</FilesMatch>

<FilesMatch "\\.(xml|txt)$">
Header set Cache-Control "max-age=216000, public, must-revalidate"
</FilesMatch>

<FilesMatch "\\.(html|htm)$">
Header set Cache-Control "max-age=300, private, must-revalidate"
</FilesMatch>

<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
ExpiresActive Off
Header unset Expires
Header unset Last-Modified
Header set Pragma "no-cache"
Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
</FilesMatch>
</IfModule>

FileETag none

</IfModule>


… und den Apache-Webserver neu-starten, um die neue Konfiguration zu übernehmen.

/etc/init.d/apache2 restart


Nun werden bestimmte Daten z.B. Bilder erst nach einem Monat wieder von der Webseite geholt, solange diese noch im Cache des Browsers sind und nicht manuell neu angefragt werden (F5).


ohne Expires:

no_cache_expires


mit Expires:

cache_expires

Die Grafik sind ebenfalls von YSlow, die Erweiterung, welche ich am Anfang des Artikels bereits beschrieben habe. Im ersten Bild siehst du die Ausgabe, wenn ein neuer Besucher (leerer Browsercache) meine Seite besucht und im zweiten, wenn z. B. ein Stammbesucher die Website aufruft, somit lässt sich gut erkennen wie viel Traffic it dieser Methode bereits bei einem Seitenaufruf eingespart werden kann, rechnet das mal für einen Monat hoch. ^^


Syntax:

ExpiresByType <TYPE> „<BASIS> [ plus ] <ANZAHL> <TYP>“

  • <TYPE> hier wird der Datei-Type definiert
  • <BASIS>

– modification ist das Änderungsdatum

– access oder now stehen für den Zugriffszeitpunkt

 

Das Schlüsselwort „plus“ ist optional. Es verdeutlicht die Tatsache, dass die nachfolgende Zeitangabe zum Basiszeitpunkt addiert wird


  • <ANZAHL> ist eine beliebige positive ganze Zahl
  • <TYP> können folgende Angaben sein

– year/years (Jahre)
– month/months (Monate)
– week/weeks (Wochen)
– day/days (Tage)
– hour/hours (Stunden)
– minute/minutes (Minuten)
– second/seconds (Sekunden)

 

Link:
www.askapache.com

Webseiten beschleunigen – Übersicht

Der Artikel beschreibt, wie man seine Webseite bzw. seinen Server analysiert und optimiert um Performance zu gewinnen, Ladezeit zu reduzierten bzw. Traffic einzusparen. Man kann einiges an Performance gewinnen, indem man z.B. Bilder im richtigen Format abspeichert bzw. komprimiert, CSS- / JS-Dateien kombiniert und ebenfalls komprimiert oder auch bestimmt Daten vorkomprimiert zur Verfügung stellt.

1.) Webseiten Analyse
1.1) Webseiten Benchmark

2.) Komprimierung
2.1) Bilder komprimieren
2.1.1) Bilder Sprites
2.1.2) PNG-Bilder komprimieren
2.1.3) JPEG-Bilder komprimieren
2.1.4) Bilder komprimieren – Online
2.2) JavaScript/CSS komprimieren
2.2.1) JavaScript/CSS komprimieren – serverseitig
2.2.2) JavaScript/CSS komprimieren – Online
2.3) Apache gzip-Kompression
2.3.1) Aktiviere mod_deflate (gzip) – serverseitig
2.3.2) Aktiviere mod_gzip – serverseitig
2.3.3) Aktiviere gzip – manuell

3.) JavaScript richtig im HTML-Code platzieren

4.) Browser-Cache nutzen
4.1) Browser-Cache manuell einstellen
4.2) Browser-Cache serverseitig einstellen

5.) Webserver beschleunigen
5.1) Apache-Module deaktivieren
5.2) Reverse Proxy (Nginx)
5.3) Nginx als Webserver
5.4) Nginx mit Varnish (Proxy)

6.) PHP optimieren/caching
6.1) PHP-Daten zwischenspeichern
6.2) SQL-Abfrage mittels PHP zwischenspeichern
6.3) PHP-Module deaktivieren
6.4) php.ini (Konfiguration) optimieren

7.) MySQL optimieren
7.1) MariaDB (MySQL-Fork)


Zusammenfassung

Abschließend möchte ich diesen Thema noch einmal kurz zusammenfassen, so dass man ggf. selber weitere Möglichkeiten erkennt, die Ladegeschwindigkeit seiner Webseite zu verbessern, jedoch nicht auf die Technische Umsetzung eingehen.

Kenne deinen Feind !!!

80 bis 90% der schlechten Performance liegt an der Webseite selber und nicht auf der Serverseite, solange nur wenig Besucher auf deiner Webseite sind, braucht man sich eigentlich um einen Revere-Proxy oder eine alternative zu Apache keine oder zumindest nur wenig Gedanken machen, da die Performance erst mit steigender Besucherzahl einbricht. Jedoch sollte man in jedem Fall die gzip-Komprimierung und den Browser-Cache nutzen.

Externe Dateien (Bilder, JS, CSS, Videos…)

Jeder Aufruf einer Datei kostet Performance und Bandbreite, daher sollte man im allgemeinen weniger Requests produzieren, indem man z.B. JS- bzw. CSS-Dateien kombiniert. Dieser negative Einwirkung steigt dramatisch bei externen Dateien von andern Servern und besonders dann, wenn dieser gerade mal nicht erreichbar ist.

Scripte

Immer wenn eine Browser eine Webseite abruft und im HTML-Code ein Script finde, wird das weitere laden der Webseite eingestellt und erst-einmal die JavaScript Engine damit beansprucht, diesen zu interpretieren. Daher sollte man diese Dateien erst am Ende der Webseite laden lassen, so dass der User die Webseite früher sehen kann, auch wenn z.B. die Animation des Menüs erst nach nachgeladen werden muss. Mit diesem Ansatz, erscheint es nur Sinnvoll CSS-Daten am Anfang laden zu lassen, so dass sich die Webseite dem User direkt im korrektem Layout präsentiert.

Bilder

Ein weites großer Bereich sind Bilder, dabei muss man jedoch ein gutes Mittelmaß an Text und Bildern finden, da die User zwar Bilder immer schön finden.. Logo, Hintergrundbild u.s.w. jedoch macht es nur wenig Sinn seine selbst jeder kleine Datei zu optimieren, wenn man oben über der Webseite ein 300 KB großes Bild eingefügt hat. Wie bereit im Artikel beschrieben gibt es jedoch zahlreiche Methoden (PNG- und JPEG-Dateien) diese zu optimieren.

Yahoo hat zudem eine sehr umfassende Liste von weiteren Regeln zusammengestellt, welche man beachten sollte.

Spammer/Hacker fernhalten (Apache2)

mod_spamhaus ist ein Apache-Modul, welches deine Webseite vor Spammern und Hackern schützen kann, indem „böse“ IP-Adressen keinen Zugriff mehr auf deine Webseite bekommen, für diesen Zweck wird auf eine „DNS-based Blackhole List“ (DNSBL) zurückgegriffen.

Es gibt mehrere Möglichkeiten dieses Modul zu installieren…

1.) selber bauen

aptitude install apache2-prefork-dev
wget http://switch.dl.sourceforge.net/project/mod-spamhaus/mod-spamhaus/0.7/mod-spamhaus-0.7.tar.gz
tar zxvf mod-spamhaus-0.7.tar.gz
cd mod-spamhaus
make
make install
vim /etc/apache2/httpd.conf

LoadModule spamhaus_module /usr/lib/apache2/modules/mod_spamhaus.so

vim /etc/apache2/apache2.conf

[…]
MS_METHODS POST,PUT,OPTIONS,CONNECT
MS_WhiteList /etc/spamhaus.whitelist
MS_CacheSize 256
[…]

touch /etc/spamhaus.whitelist
/etc/init.d/apache2 restart

2.) neue Debian-Pakete

Falls du bereits Debian >= Squeeze einsetzt, kannst du diese Apache-Erweiterung bereits ohne jegliche Änderung am System mittels folgendem Befehl installieren.

aptitude install libapache2-mod-spamhaus

andernfalls kannst du dieses Paket erlauben, Daten aus dem Squeeze-Repository zu installieren…

sudo bash
echo “deb http://ftp.de.debian.org/debian/ squeeze main contrib non-free” >> /etc/apt/sources.list
echo “deb-src http://ftp.de.debian.org/debian/ squeeze main contrib non-free” >> /etc/apt/sources.list
apt-get update
vim /etc/apt/preferences

Package: libapache2-mod-spamhaus
Pin: release a=squeeze
Pin-Priority: 999

aptitude install libapache2-mod-spamhaus
a2enmod mod-spamhaus
/etc/init.d/apache2 restart

nach der Installation wirst du bald Einträge ähnlich dem folgendem finden

[ … ]
[Mon Dec 01 00:05:26 2008] [error] [client 149.156.67.236] denied by DNSBL: sbl-xbl.spamhaus.org for: /news.php
[ … ]

.htaccess & Mod-Rewrite

„Eine Rewrite-Engine ermöglicht es, an den Webserver gerichtete Anfragen intern umzuschreiben oder extern weiterzuleiten.“ – Wiki

1.) Seiten ohne subdomain (http://domain.de)
2.) Seiten mit www (http://www.domain.de)
3.) Schrägstrich hinzufügen
4.) Eine einfache Weiterleitungen
5.) alle Anfragen auf ein Unterverzeichnis auf die Hauptseite weiterleiten
6.) Bilder von Ihrer domain schützen
7.) SSL-Verbindung an einen SSL-Proxy weiterleiten
8.) Verbindungen auf Port umbiegen
9.) Sub-Domain umleiten
10.) Client aussperren
11.) Umleiten der Anfrage
12.) Neue Index-Datei
13.) Webseiten Zugriff schützen
14.) ErrorSeite umleiten
15.) Slash am Ende einer Datei entfernen
16.) doppelten Slash in der URL entfernen
17.) Dateien sperren
18.) .htaccess umbenennen
19.) Verzeichnisauflistung an/aus
20.) Fehlermeldungen (parse-errors) ausgeben
21.) SubDomain in einen Unterverzeichnis umleiten (ohne die URL (Path) zu ändern)

Vorbereitung:
Unsern Apache2 Webserver müssen wir beibringen, dass er eine URL neu-schreiben kann.

a2enmod rewrite

Und in der ersten Zeile unserer „.htaccess“-Datei muss folgendes stehen, wenn wir die „rewrite“-Funktion nutzen wollen.

RewriteEngine On

 

1.) Seiten ohne subdomian (http://domain.de)

wenn irgendeine Subdomain in der url mit angegeben wird, wird trotzdem die domain ohne subdomain angezeigt

RewriteCond %{HTTP_HOST} ^([^.]+).domain.de$ [NC]
RewriteRule ^(.*)$ http://domain.de/$1 [R=301,L]

 

1.2) mann kann auch bestimmte subdomains von dieser Regel ausschließen

RewriteCond %{HTTP_HOST} ^([^.]+).domain.de$ [NC] [OR]
RewriteCond %{HTTP_HOST} !^subdomain.domain.de$ [NC]
RewriteRule ^(.*)$ http://domain.de/$1 [R=301,L]

 

1.3) Seiten ohne www (http://domain.de)

RewriteCond %{HTTP_HOST} ^www.domain.de$ [NC]
RewriteRule ^(.*)$ http://domain.de/$1 [R=301,L]

 

2.) Seiten mit www (http://www.domain.de)

wenn irgendwas außer www vor der Domain angegeben ist, wird www eingefügt

RewriteCond %{HTTP_HOST} !^www.domain.de$ [NC]
RewriteRule ^(.*)$ http://www.domain.de/$1 [R=301,L]

 

2.1) mann kann auch bestimmte subdomains von dieser Regel ausschließen

RewriteCond %{HTTP_HOST} !^www.domain.de$ [NC] [OR]
RewriteCond %{HTTP_HOST} !^subdomain.domain.de$ [NC]
RewriteRule ^(.*)$ http://www.domain.de/$1 [R=301,L]

 

3.) Schrägstrich hinzufügen

um z.B. einen Schrägstrich hinter die angegebene URL setzen möchte, kann man dies wie folgt machen

RewriteCond %{REQUEST_URI} ^/[^.]+[^/]$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [R=301,L]

 

4.) Eine einfache Weiterleitungen

alle Anfragen auf forum.html werden auf
forum/forum.php weitergeleitet, in der URL steht nun noch immer forum.html

RewriteRule forum.html forum/forum.php

 

4.1) alle Unterverzeichnisse auch umleiten, in der URL steht nun der neue Pfad

RewriteRule forum/(.*)$ forum_neu/forum.php [R=301,L]

 

4.2) die Unterverzeichnisse mit übertragen, somit kommen wir z.B. von forum/Unterverzeichnis nach forum_neu/Unterverzeichnis

RewriteRule forum/(.*)$ forum_neu/$1 [R=301,L]

 

4.3) URL neu-schreiben (rewriting)

Der nachfolgende Code bewirkt, dass

„http://www.domain.de/index.php?go=home“

wie folgt umbenannt wird

„http://www.domain.de/home.html“

RewriteRule ^(.*).html$ index.php?go=$1 [L]

 

5.) alle Anfragen auf ein Unterverzeichnis auf die Hauptseite weiterleiten

RewriteRule forum/?$ / [R=301,L]

 

6.) Bilder von Ihrer domain schützen

Bilder von Ihrer domain schützen, indem diese nicht von anderen domians (Referer) geladen werden dürfen, sobald dies geschieht, wird im folgendem Beispiel, anstatt des Bildes ein RSS-Feed Bild angezeigt, wobei google von dieser Regel ausgenommen ist…

RewriteCond %{HTTP_REFERER} !^http://(www.)?domain.de(/.*)?$ [NC] [OR]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google.(de|com)(/.*)?$ [NC]
RewriteRule .(BMP|JPG|JPEG|GIF|PNG)$ http://feeds2.feedburner.com/voku-online.4.gif [L]

domain.de muss du noch durch deine eigene Domain ersetzen und „RewriteEngine On“ am Anfang deiner .htaccess-Datei einfügen

weitere Dateiendungen welche Sie blocken könnten

BMP|JPG|JPEG|GIF|PNG|SWF|WMV|MPG|MPEG|AVI|DIVX|MP3|WMA|MOV|RM
|FLV|bmp|jpg|jpeg|gif|png|swf|wmv|mpg|mpeg|avi|divx|mp3|wma|mov|rm|flv

auf folgender Webseite, kannst du testen, ob deine Bilder nun geschützt sind…
coldlink.com

 

7.) SSL-Verbindung an einen SSL-Proxy weiterleiten

RewriteCond %{SERVER_PORT} ^443$
RewriteRule (.*) https://ssl-id1.de/%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

 

8.) Verbindungen auf Port umbiegen


8.1) Verbindungen auf Port 80 umbiegen

Verbindungen welche nicht auf Port 80 eintreffen (solange im Webserver mehrere offene Port konfiguriert sind – meistens Port 80 [http] 443 [https]) auf Port 80 weiterleiten

RewriteCond %{SERVER_PORT} !^80
RewriteRule ^(.*)$ http://www.domainname.de$1 [R=301,L]

 

8.2) Verbindungen auf Port 443 umbiegen

RewriteCond %{SERVER_PORT} !=443
RewriteRule ^(.*)$ https://www.domainname.de$1 [R=301,L]

alternativ

RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} (.*)
RewriteRule (.*) https://%{HTTP_HOST}%1 [R=301,L]

 

9.) Sub-Domain umleiten

um z.B. eine subdomains „linux.voku-online.de“ einfach nur umzuleiten, kann man folgendes eintragen, somit bleibt die Sub-Domain in der URL erhalten

RewriteCond %{HTTP_HOST} ^linux.voku-online.de [NC]
RewriteRule ^$ /news-c5.html [R=301,L]

bzw. wenn man dies auf die Hauptdomain weiterleiten möchte dann müsste folgendes eingetragen werden

RewriteCond %{HTTP_HOST} ^windows.voku-online.de [NC]
RewriteRule (.*) http://voku-online.de/news-c4.html [R=301,L]

 

10.) Client aussperren

Man kann auch ein bestimmtes Betriebssysteme oder Browser aussperren z.B.:

 

10.1) Internet-Explorer aussperren

RewriteCond %{HTTP_USER_AGENT} ^MSIE.*
RewriteRule ^/.* - [forbidden]

 

10.2) Windows-Computer aussperren

RewriteCond %{HTTP_USER_AGENT} ^Windows.*
RewriteRule ^/.* - [forbidden]

 

10.3) Webseiten aussperren

RewriteCond %{HTTP_REFERER} badsite.com [NC,OR]
RewriteCond %{HTTP_REFERER} anotherbadsite.com
RewriteRule .* - [forbidden]

 

11.) Umleiten der Anfrage


11.1) Weiterleitungen zur Startseite

Alternativ könnte man auch mit folgendem Befehl, eine bestimmte Anfrage zu einer neue Domain umleiten.

Redirect /altes_Verzeichnis/alte_Seite.html http://meine_domain.de/

 

11.2) Weiterleitungen (301 Redirect)

Dies nutzt man, wenn man z.B. eine Domain umgezogen hat, so dass die Suchmaschinen nicht weiter die alte Webseite in Ihren Index aufnehmen.

Redirect permanent /seite.html http://www.neue-domain.de/seite.html

 

12.) Neue Index-Datei

Standardmäßig wird eine index.php oder wenn diese nicht vorhanden ist eine index.html Datei als erstes angezeigt, wenn man sich mit einem Browser ein Verzeichnis auf einem Webserver aufruft. Mit dem folgendem Befehl kannst du bestimmen, welche Dateien als erstes angezeigt werden sollen.

DirectoryIndex filename.html index.cgi index.pl default.htm

 

13.) Webseiten Zugriff schützen


13.1) Zugriff komplett sperren

Mit folgendem Inhalt in einer „.htaccess“-Datei ist der Zugriff auf dieses Verzeichnis (und Unterverzeichnisse) komplett gesperrt

order allow,deny
deny from all

Folgendes verhindert, dass die hier spezifizierte Datei .htaccess aufgerufen werden kann. An Stelle von .htaccess kann jede beliebige Seite/Datei/Dateityp einsetzen werden

order allow,deny
deny from all

oder man bannt ein bestimmte Domain

order allow,deny
deny from .domain.de
allow from all

 

13.2) Zugriff nur nach Authentifizierung

AuthUserFile /verzeichnise.../.htusers
AuthGroupFile /dev/null
AuthName "Authorization Required"
AuthType Basic
require valid-user

Der Pfad zu der „.htusers“-Datei muss komplett angegeben werden. z.B.:

AuthUserFile /var/www/web1/web/.htusers

um diese User-Datei anzulegen kann man folgendes Kommando verwenden

htpasswd -bc .htusers test_user geheimes_passwort

und um einen weiteren Benutzer hinzuzufügen

htpasswd -b .htusers tset_user_2 geheimes_passwort

 

13.3) Zugriff nur von einem bestimmten IP-Adressen-Bereich

order deny,allow
deny from all
allow from 192.168

Somit ist nur der Zugriff nur von folgenden IP-Adressen gestattet -> 192.168.X.X

! Wichtig ! – Du solltest deine Webseite nicht nur mit einem IP-Filter Schützen, da man mittels IP-Spoofing (gefälschten Header-Infos) dann unter Umständen doch noch darauf zugreifen kann.

 

13.4) Zugriff nicht von einem bestimmten IP-Adressen-Bereich

order allow,deny
allow from all
deny from 212.26.50.10

 

14.) ErrorSeite umleiten

Zudem könnten man auch die Fehlerseiten, welche dem Benutzer angezeigt werden, wenn dieser z.B. einen Pfad auf Ihren Webseren anspricht, welcher gar nicht existiert, erhält.

ErrorDocument 400 /errors/badrequest.html
ErrorDocument 401 /errors/authreqd.html
ErrorDocument 403 /errors/forbid.html
ErrorDocument 404 /errors/notfound.html
ErrorDocument 500 /errors/serverr.html

 

15.) Slash am Ende einer Datei entfernen

Ich hatte heute das Problem, dass einer meiner Blog-Einträge falsch verlinkt wurde und so einige Leute nicht den korrekten Inhalt zu sehen bekamen, dies habe ich nun umgangen, indem der Slash am Ende der URL entfernt wird, wenn es sich nicht um ein Verzeichnis handelt und es sich um eine „.php“ oder „.html“ Datei handelt.

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)(.php|.html)/$ /$1$2 [R=301,L]

 

16.) doppelten Slash in der URL entfernen

Wenn man doppelte Slashes in einer URL entfernen möchte …

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

 

17.) Dateien sperren


17.1) nur bestimmt Dateiendungen können heruntergeladen werden

ForceType application/octet-stream

oder man kann auch alle Dateien welche mit einen „.“ Punkt beginnen, verhindern von Webserver ausgeliefert zu werden

deny from all

 

18.) .htaccess umbenennen

Bei diesem Beispiel wird in allen Unterverzeichnissen die Datei .datei als htaccess-Datei angesehen

AccessFileName .datei

 

19.) Verzeichnisauflistung an/aus

Falls sich keine Index-Datei (Startdatei) in einem Verzeichnis befindet, kann man entweder einen Fehler zurückgeben oder den Inhalt anzeigen lassen

 

19.1) Inhalt ausgeben

Options +Indexes

 

19.2) Fehler ausgeben

Options -Indexes

 

20.) Fehlermeldungen (parse-errors) ausgeben

php_flag display_errors true

 

21.) SubDomain in einen Unterverzeichnis umleiten (ohne die URL (Path) zu ändern)

RewriteEngine On
RewriteCond %{HTTP_HOST} ^sub\.domain\.de$ [NC]
RewriteCond %{REQUEST_URI} !sub_domain_dir
RewriteRule ^(.*)$ sub_domain_dir/$1 [P]

 

weiter Infos:
de.selfhtml.org
httpd.apache.org