Der bekannte Webserver nginx, auf dem ca. 6% aller Webseiten des Internets laufen und der auch noch Reverse Proxy- und pop3/imap Proxyserver sein kann, hat noch eine andere, oft wenig beachtete Möglichkeit. Mit Hilfe seines Image Filters ist es möglich, ihn als lastverteilten Lieferanten für Bilder zu benutzen, die er on-the-fly in andere Größen skalieren kann.
1. Lastverteilung
Nginx kann von Haus aus Anfragen an andere Webserver verteilen. Hierzu definiert man zuerst einen Upstream Server.
upstream cache_group {
server :8888 weight=100;
server 127.0.0.1:8888 weight=1;
}
Im vhost der die ersten Anfragen annimmt, definiert man dass der Webserver zuerst schaut, ob er das optimierte Bild schon hat, bzw. wenn das Original gefordert wird dieses sofort ausliefert.
server {
listen 80;
server_name mein_Server;
location = /favicon.ico {
#empty_gif;
return 204;
}
location / {
root /var/www/images;
rewrite "^\/(50|100|150|200|250|300|350)\/(.*)\.(jpg|png)$" /$1/$2.$3 break;
rewrite "^\/(.*)\.(jpg|png)" /$1.$2 break;
error_page 404 = @cache;
}
location @cache {
internal;
proxy_pass http://cache_group;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /var/www/temp;
root /var/www/images;
}
}
Falls der Server das Bild nicht findet schaut er, statt die error_page 404 auszugeben, in der cache_group nach. Hier greift die bei Upstream eingerichtete Gewichtung der Server. Nginx wird 100mal so oft auf dem zweiten Image Server suchen wie auf sich selbst. Wenn das Bild auch auf dem anderen Server nicht gefunden wird, wird es dort generiert. Das sorgt natürlich dafür, dass der erste Server entlastet wird. Das Verzeichnis /var/www sollte ein gemeinsames Share sein, damit das generierte Bild auch beiden Servern zur Verfügung steht.
Die im vhost eingestellten rewrite Regeln sind nötig, um unterscheiden zu können, welche Größe des Bildes angefordert wird, bzw. ob einfach das Original benutzt wird. Ruft der Client http://mein_Server/300/testbild.jpg ab bekommt er das Bild aus /var/www/images/300/testbild.jpg. Bei http://mein_Server/testbild.jpg greift die untere rewrite Regel und er kommt auf /var/www/images/testbild.jpg
2. Bildoptimierung
Der vhost für den Cache sieht folgendermaßen aus:
server {
listen 8888;
server_name mein_Server;
location / {
root /var/www/images/;
error_page 404 = @local_image;
}
location @local_image {
internal;
proxy_pass http://local_group_image;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /var/www/temp;
root /var/www/images;
}
Von hier aus springt er, falls das Bild dort nicht finden kann in den Image teil.
Hierfür muss man zunächst noch einen Upstream angeben:
upstream local_group_image {
server 127.0.0.1:7777;
}
Und anschließend den vhost inklusive Imagefilter und Sicherheitscheck (es sollen nur die Größen erstellt werden, die wir vorher angeben) erstellen. Der Sicherheitscheck funktioniert durch den Regex in der Location Direktive.
server {
listen 7777;
server_name mein_Server;
location ~ "\/(50|100|150|200|250|300|350)\/.*\.(png|jpg)$" {
root /var/www/images/;
rewrite "^\/(50|100|150|200|250|300|350)\/(.*)\.(jpg|png)$" /$2.$3 break;
image_filter resize $1 $1;
image_filter_buffer 6M;
image_filter_jpeg_quality 95;
}
}
Jetzt sollte alles so funktionieren, wie wir uns das vorstellen. Das Konstrukt ist natürlich noch um weitere Server erweiterbar. Auch zusätzliche Aufgaben, wie z.B. SSL oder andere Bild Formate sind schnell integriert. Wen man so weit ist, wie hier beschrieben, hat man eine skalierbare, stabile und leicht gewichtige Lösung die mit ein wenig Mehrarbeit auch Ausfallsicher ist.
„Bild Konverter“ – Deppenleerzeichen!