Velocizzare Apache proxando i contenuti statici

Concludiamo questa prima carrellata di articoli sui web server con le istruzioni per utilizzare un vecchio sistema per velocizzare il servizio web.

Premettiamo una cosa: apache è un ottimo web server, ci si può fare anche il caffelatte, però è tutto tranne che “light”. Pensiamo solo a come funziona il metodo prefork: per servire un qualsiasi contenuto, ammettiamo una immagine gif di pochi kbytes, viene istanziato un processo che occupa svariati Mbytes di RAM! Oltre ad essere un sistema non proprio veloce, nel caso di siti molto visitati questo può arrivare a generare problemi di saturazione del server… e non è nemmeno troppo difficile arrivarci!
Visto che non tutto va bene per tutto, in questo articolo vedremo come configurare il proprio server in modo da servire i contenuti dinamici (script php ad esempio) attraverso apache e i contenuti statici attraverso nginx, che è un web server molto light e, quindi, molto veloce.

Il sistema che utilizzaremo è di far rispondere alle richieste dirette all’indirizzo IP esterno su porta 80 nginx, mentre apache lavorerà solo sull’indirizzo IP di loopback (127.0.0.1) su porta 80. Nginx si prenderà in carico qualsiasi richiesta è la soddisferà autonomamente nel caso in cui si tratti di contenuti statici (immagini, script javascript, css, ecc.) e la girerà al corrispondente virtualhost di apache nel caso in cui si tratti di contenuti dinamici.

Una volta installati i pacchetti, andiamo ad editare il file di configurazione di nginx.

<strong>/etc/nginx/nginx.conf</strong>
user www-data;
worker_processes  2;
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    access_log /var/log/nginx/access.log;
    server_names_hash_bucket_size 64;
    sendfile        on;
    tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    tcp_nodelay        on;
    gzip              on;
    gzip_comp_level   5;
    gzip_http_version 1.0;
    gzip_min_length   0;
    gzip_types        text/plain text/html text/css image/x-icon application/x-javascript;
    gzip_vary         on;

    server {
        listen       XXX.XXX.XXX.XXX:80 default;
        server_name  _;
        access_log /var/log/nginx/default.access.log main;

        location / {
            proxy_pass http://127.0.0.1:80;
            include /etc/nginx/conf.d/proxy.conf;
        }
    }

    include /etc/nginx/sites-enabled/*;




}

Attraverso questa configurazione, i file inviati direttamente da nginx saranno compressi con un fattore di 5. Più alto è questo valore, più alto sarà il carico di CPU e minore sarà la quantità di banda utilizzata; 5 mi sembra un buon compromesso.
La sezione server specifica un virtual host di default che sarà utilizzato nel caso in cui non venga trovato un virtual host specifico: in questo caso tutte le richieste saranno reindirizzare al web server apache che è in ascolto su localhost porta 80. Ovviamente sostiruite a xxx.xxx.xxx.xxx l’indirizzo IP del vostro server.
Attraverso l’ultima riga andremo ad includere tutti i file presenti nella directory /etc/nging/sites-enabled/ dove specificheremo tutti i virtual host del nostro server.
Andiamo ora ad editare la configurazione del proxy che sarà utilizzata da tutti i virtual host.

<code><strong>/etc/nginx/conf.d/proxy.conf </strong>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; client_max_body_size 10m; client_body_buffer_size 128k; client_header_buffer_size 64k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 16k; proxy_buffers 32 16k; proxy_busy_buffers_size 64k</code>

L’unica impostazione degna di nota il proxy_buffers e proxy_buffer_size a 16k: questo valore è piuttosto elevato in quanto, se settato più basso, potrebbero esserci problemi con i cookies, nel qual caso il server ritorna un errore 5xx.

Ecco infine il template per un file di virtualhost per il dominio dominio.tld da mettere nella directory /etc/nginx/sites-enabled:

server {
    listen XXX.XXX.XXX.XXX:80;
    server_name dominio.tld www.dominio.tld;

    location / {
        proxy_pass http://127.0.0.1:80;
        include /etc/nginx/proxy.conf;
    }

    location ~* ^.+.(jpe?g|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf|avi|mp3)$ {
        expires 30d;
        root /var/www/dominio.tld/htdocs;
    }
}

Anche in questo caso, ricordarsi di sostituire xxx.xxx.xxx.xxx con il proprio indirizzo IP. Il file di configurazione usa il proxy per tutti i contenuti, tranne quelli statici definiti nella seconda parte del file di configurazione. La root dei file del sito (/var/www/dominio.tld/htdocs) è comune a nginx e ad apache.

Passiamo ora alla configurazione di apache. Innanzi tutto bisogna far si che apache risponda solo alla porta 80 di localhost. In Ubuntu/Debian si setta in /etc/apache2/ports.conf:

Listen 127.0.0.1:80

Inoltre verificate che il file di configurazione dei VirtualHost di apache non includano l’indirizzo IP:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName foobar.com
...
</VirtualHost>

Ultima configurazione da fare in Apache riguarda i log. Difatti con la configurazione qui sopra, apache memorizzerà l’indirizzo IP locale nei file di log. Fortunatamente nginx invia ad apache l’header HTTP X-Forwarded-For: si tratta solo di far si che apache legga questo dato. In soccorso ci viene il modulo mod_rpaf di apache, la cui configurazione è la seguente:

<IfModule mod_rpaf.c>
 RPAFenable On
 RPAFsethostname On
 RPAFproxy_ips 127.0.0.1
</IfModule>