Se vi  trovate ad amministrare, per lavoro o per hobby, infrastrutture informatiche che forniscono servizi web, vi sarà capitato di dover affrontare problematiche relative alle performance.Per mitigare il problema di web-server con le code piene o database in “too many connection”, esiste una soluzione che s’implementa molto velocemente e, se approfondita, può portare non solo ad un mitigamento dei problemi ma ad un notevole incremento delle performance.Questa soluzione si chiama Varnish.

Varnish è in sostanza un reverse proxy, un reverse proxy è un demone che intercetta le richieste dirette al webserver, eventualmente le elabora, le rigira al webserver e ne restituisce la risposta al client.I reverse proxy trovano spazio in diverse applicazioni, ad esempio la sicurezza, nel nostro caso andremo ad analizzarne 2: il bilanciamento del carico e il caching.Varnish è un particolare reverse proxy pensato per effettuare questi 2 compiti.

Prima di continuare è opportuno uno sguardo all’hardware necessario ed a come i vari componenti andranno posizionati nella rete.

Saranno coinvolte essenzialmente 3 entità: i web-server, il server Varnish ed i client.Quando un client effettua una richiesta “www.miosito.it “avremo configurato il dns per rispondere con un ip w.x.y.z, questo sarà l’ ip pubblico del nostro varnish.Varnish riceve la richiesta e controlla se ha in memoria una risposta valida per quella particolare richiesta. Se la trova la restituisce al client altrimenti chiama in causa il o i webserver, che in questo caso assume il ruolo di backend, ne memorizza la risposta per un uso futuro e la inoltra al client.Il bilanciamento del del carico viene effettuato inoltrando le richieste non presenti in cache a più di un web-server distribuendole su di essi.

Cominciando dal server su cui facciamo girare varnish analizziamone le risorse richieste.

  • La cpu non è cruciale!!Varnish calcola l’hash delle richieste(in base alla URL, cookie o altri parametri che analizzeremo quando vedremo la configurazione) ed usa il valore ottenuto per effettuare le ricerche nella cache. Il calcolo di un hash ha la peculiarità di essere eseguita in un tempo θ(1) (si legge Theta di uno) ,così come la ricerca in una tabella hash, che significa che cercare una risposta nella cache impiega sempre lo stesso tempo a prescindere dal numero di elementi memorizzati.Non ci addentreremo nella teoria degli algoritmi, ci basti sapere che questo tipo di operazione è molto veloce e non richiede grosse capacità di calcolo. A fine articolo metterò un po di statistiche su di un caso di produzione reale.
  • La memoria RAM è il vero punto cruciale, varnish può essere configurato per memorizzare le risposte su disco oppure in memoria(ma non su entrambe contemporaneamente, quindi una scelta esclude l’altra) la RAM ha tempi di accesso di un paio di ordini di grandezza inferiori anche rispetto ai dischi più veloci ed è quindi il metodo da preferirsi.Ma di quanta RAM stiamo parlando?Oggi macchine con a bordo 36 se non 48 Gigabyte di RAM hanno prezzi abbordabili.Con queste capacità possiamo tranquillamente fare il caching d’ interi siti web.
  • Un’ultima cosa da prendere sono le interfacce di rete(NIC). L’ideale sarebbe averne 2, una che si affaccia su internet e l’altra usata per le comunicazioni con i webserver(4 se vogliamo implementare il failover).Con pochi euro in più possiamo dotare le nostre NIC della funzionalità “TCP offload checksum” in pratica un chip a bordo di esse calcola il cheksum dei pacchetti TCP (Usato per identificare eventuali errori di trasmissione) scaricando il sistema operativo da questo compito, considerando che queste interfacce sono il punto dove si aggrega tutto il traffico non è un’eventualità da trascurare.

Installazione

L’installazione è specifica per la distribuzione, fate riferimento alla documentazione ufficiale per la procedura adatta alla vostra distribuzione http://www.varnish-cache.org/docs

Configurazione VCL (Varnish-Configuration-Language)

Arriviamo alla parte divertente, configuriamo il nostro varnish per adattarlo alle nostre specifiche esigenze.Come ogni buon programma linux, la configurazione viene fatta mediante un file di testo con una sintassi chiamata VCL molto simile a quella del C (anche perché varnish traduce la configurazione in codice C, lo compila come shred object e lo linka dinamicamente al demone in esecuzione). Come in C abbiamo a disposizione le istruzioni di test (if-then-else)e la possibilità di definire subroutine(senza argomenti e senza valori di ritorno), non possiamo creare loop(for o while per intenderci) ne dichiarare variabili(come vedremo possiamo in realtà dichiarare dei campi e valorizzarli in alcuni “oggetti” predefiniti).Il programma definito dal VCL viene eseguito ad ogni richiesta ricevuta dal nostro server.

Come distinguiamo le richieste e decidiamo come cachare.

Varnish alla ricezione della richiesta prende in considerazione la Request url, e gli header Http: Host, Coockie, Set-Cookie e Vary. Con la URL, Host e Vary ci calcola l’hash e lo usa per indirizzare la entry nella struttura dati della cache, mentre, per default, request e response contenenti Coockie o Set-Coockie vengono by-passate dalla cache.
In questo modo le richieste che contengono Coockie (per identificare presumibilmente gli utenti) vengono trattate come diverse anche se url e host sono i medesimi.

Il Workflow

Alla ricezione di una richiesta, varnish chiama una serie di subroutine predefinite per soddisfare la richiesta stessa.Andiamo ad analizzare questo workflow, un’immagine può essere utile per capire meglio la logica di funzionamento.

Varnish-State-Machines

I rettangoli con le scritte in rosso rappresentano le funzioni (il cui comportamento è definito all’interno del nostro file di configurazione) che vengono chiamate da varnish nelle varie fasi dell’elaborazione della richiesta.
Ogni funzione può terminare con la keyword return(arg), dove arg è il nome di una funzione direttamente collegata, ad esempio recv può richiamare pass,pipe,lookup(passando per hash) o error.
Prima di andare ad analizzarle, uno sguardo alla definizione dei back-end.

backend web01{
.host = “192.168.0.1″;
.port = “80″;
.connect_timeout = 2s;
.probe = {.url = “/probe/web01.active”;}
}

backend web02{
.host = “192.168.0.2″;
.port = “80″;
.connect_timeout = 2s;
.probe = {.url = “/probe/web02.active”;}
}

backend static01{
.host = “192.168.0.11″;
.port = “80″;
.connect_timeout = 2s;
.probe = {.url = “/probe/static01.active”;}
}

backend static02{
.host = “192.168.0.12″;
.port = “80″;
.connect_timeout = 2s;
.probe = {.url = “/probe/static02.active”;}
}

director web random{
{.backend = web01; .weight = 1;}
{.backend = web02; .weight = 1;}
}

director static random{
{.backend = static01; .weight = 1;}
{.backend = static02; .weight = 1;}
}

In questo esempio abbiamo definito 2 back-end per i contenuti dinamici(web01 e web02) e 2 per i contenuti statici (static01 e static02), questa distinzione non è obbligatoria, però così facendo possiamo separare le richieste e scegliere di usare, per i contenuti statici, webserver più performanti del solito apache (nginx, lighttpd, ecc…).

Abbiamo poi definito 2 director (web e static) che raccolgono tutti i back-end e distribuiscono il carico su di essi.

recv

è la prima funzione che viene chiamata alla ricezione della richiesta, quì possiamo manipolare la richiesta prima di andare a verificare se la richiesta è presente in cache oppure se è una richiesta che non è cachabile, decidiamo inoltre il backend al quale inoltrare le richiesta.

pass

Questa funzione la chiamiamo se vogliamo che la cache della richiesta venga rinfrescata.Chiamando pass effettuiamo una richiesta ai webserver anche se la risposta è presente in cache ed è valida.

pipe

Una call a pipe by-passa varnish e rigira as-is la richiesta al web-server.

lookup

Con una lookup chiediamo a varnish di verificare se la risposta è presente e valida in cache.

fetch

Questa funzione viene chiamata dopo il recupero del contenuto dal back-end invocato da una pass o una miss.

hit/miss

Chiamate automaticamente da varnish dopo lo lookup, una hit causerà la chiamata a deliver e la risposta verrà spedita al client, una miss causerà la chiamata a fetch che recupera la risposta dal web-server e poi ancora deliver per spedirla al client.

error

Questa funzione viene chiamata automaticamente da varnish quando nessun back-end è disponibile per soddisfare la richiesta, possiamo anche chiamarla all’interno di qualunque funzione nel caso intercettassimo condizioni di errore.

Esempio di configurazione

Trattandosi di un vero e proprio linguaggio di programmazione, la configurazione di varnish può essere particolarmente complessa e fatta ad-hoc per uno specifico sito. In questo paragrafo cercherò di fare degli esempi generali che andranno poi adattati alle specifiche realtà.
Possiamo decidere che tutte le immagini, i css e i javascript sono uguali per tutti gli utenti, per distinguere gli utenti il protocollo HTTP metta a disposizione i cookie, dobbiamo quindi eliminarli. Inoltre, come spiegato nella parte relativa ai back-end mandiamo i contenuti statici a dei web-server e quelli dinamici ad altri.La nostra recv diventa quindi:
sub vcl_recv{

if(req.url ~ “*\.(jpg|gif|png|css|js)”{
set req.backend = static;
unset req.http.coockie;

unset req.http.Vary;

return(lookup);
}

set req.backend = web;
}

Con questa istruzione nella recv chiediamo a varnish di by-passare la cache in caso di utenti autenticati (riconosciuti dalla presenza del coockie sessid) o utenti diretti all’admin

if(req.http.Coockie ~ “sessid” || req.url ~ “/admin”){return(pipe);}

Nella vcl_fetch specifichiamo il tempo di validità della cache

if(req.request == “GET” && req.url ~ “\.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|img|tga|wmf)$”) {
set beresp.ttl = 5d;
}
else {set beresp.ttl = 2h;}

Vista la versatilità del linguaggio di configurazione, non è possibile esplorare tutte le possibilità, in futuro potranno esserci articoli più specifici che trattano dei casi più tipici.

Varnish è un software disponibile per linux, ma dopo aver visto il suo ruolo all’interno della rete dovrebbe essere chiaro che può essere usato anche davanti a web server Windows o Mac, l’importante è avere a disposizione un’installazione di linux sulla quale far girare varnish.

Lascia un Commento

Devi aver fatto il login per inviare un commento

Page 1 of 11