Distribuzione delle sessioni in PHP in caso di load balancing su più server

33
Distribuzione delle sessioni in PHP di Gianluca GIMIGLIANO [email protected]

description

La distribuzione delle sessioni è un problema che riguarda la scalabilità dei siti web su più server, in particolare per PHP che di norma salva le sessioni su file system del singolo server. In questo talk vedremo alcune strategie di risoluzione del problema (load balancing mirato, accentramento delle sessioni) e ci soffermeremo su una personale soluzione che prevede delle sessioni distribuite su più macchine contemporaneamente creando un’architettura a maglia attraverso l’uso di memcache

Transcript of Distribuzione delle sessioni in PHP in caso di load balancing su più server

Page 1: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Distribuzione delle sessioni in PHP

diGianluca GIMIGLIANO

[email protected]

Page 2: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Perché le sessioni?

• Perché il protocollo HTTP è statelessness, ossia non è in grado di veicolare informazioni su eventuali scelte pregresse quindi:– Ogni richiesta del client fa storia a sé e non ha

memoria del passato– Non è possibile associare delle variabili di stato

ad un determinato client

Page 3: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Utilizzo tipico delle sessioni

• Tenere memoria dell’avvenuta autenticazione in un’area riservata

• Mantenere la traccia di scelte effettuate dal navigatore in pagine diverse del sito (es. carrelli)

Page 4: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Come PHP gestisce le sessioni

Quando un client si connette per la prima volta,

il motore delle sessioni del PHP genera un id univoco e crea un file nel quale verranno salvate le “variabili di sessione” e che ha per nome quello stesso id. Insieme alla risposta al al client viene inviato un “cookie di sessione” che ha per valore quell’id.

In questo modo, ogni volta che un client presenterà una richiesta con quel cookie, il PHP saprà in quale file sono contenute la variabili relative a quella sessione ripristinandole

Page 5: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Funzionamento della sessione

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=x

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

a1b2c3d…scelta=xscelta2=y

Page 6: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Scalare un sito su più server

All’aumentare delle richieste un solo server (virtuale o fisico che sia) può non essere più sufficiente e nasce quindi la necessità di mettere più macchine in batteria.La scelta di quale macchina risponderà ad una determinata richiesta viene fatta da un’apposita apparecchiatura di rete: il “bilanciatore” che garantisce la distribuzione delle richieste secondo politiche definite dall’utente (es. equa distribuzione del carico su tutte le macchine).

Page 7: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Generalmente una macchina bilanciata

• Non è tenuta a sapere di esserlo• E’ configurata esattamente come tutte le

altre• Produce risposte che, sia nel protocollo che

nel contenuto, sono indistinguibili dalle risposte generate da un’altra macchina bilanciata

Page 8: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Il problema delle sessioni con bilanciamento

• Poiché il cookie viene generato da una delle macchine bilanciate ed il file con le variabili si trova su di essa, quando il bilanciatore andrà a instradare una richiesta con il cookie di sessione su un’altra macchina questa non avrà a disposizione memoria del passato della sessione.

• Tale memoria tornerà “misteriosamente” disponibile quando le richieste torneranno sulla macchina che ha generato inizialmente la sessione.

Page 9: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Problema del bilanciatore

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=x

a1b2c3d…scelta2=y

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

Page 10: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Possibile soluzione 1

• Bilanciamento mirato– Il bilanciatore entra nel merito del protocollo,

riconosce la presenza del cookie di sessione nella risposta del server, e da quel momento tutte le richieste con quel cookie verranno assegnate a quel server

Page 11: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Problema del bilanciatore

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=xscelta2=y

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

A

BA) “SESSID=a1b2c3d..”

Page 12: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Vantaggi

• Non necessita di modifiche sia negli applicativi che nelle configurazioni dei server

• Veloce, la tabella con le assegnazioni dei cookie ai server è gestita in RAM dal bilanciatore con SW integrato nel firmware

Page 13: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Svantaggi

• Occorre programmare il bilanciatore• Applicazioni diverse potrebbero usare cookie di

sessione con nome diverso ed il bilanciatore deve tenerne conto

• Il bilanciatore non può sapere il peso ed il numero di transazioni che genererà un client a cui assegna una macchina quindi il carico potrebbe risultare paradossalmente sbilanciato (specie se l’algoritmo di distribuzione è pesato per difformità nelle prestazioni delle macchine)

Page 14: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Possibile soluzione 2

• Concentrazione dei dati– I dati di sessione vengono accentrati in un unico

storage condiviso che può essere file sharing, DB, memcache

Page 15: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Esempio di sessioni accentrate

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=xscelta2=y

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

Page 16: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Vantaggi e svantaggi

• Dipendono dal tipo di storage

Page 17: Distribuzione delle sessioni in PHP in caso di load balancing su più server

File sharing

• Vantaggi– Di facile utilizzazione, basta cambiare la direttiva session.save_path del PHP.ini impostando il percorso della cartella condivisa

– Non prevede nessuna modifica al codice degli script• Svantaggi

– Sicuramente dal punto di vista prestazionale non garantisce risultati eccellenti a meno di investire in apparecchiature dedicate (e costose)

Page 18: Distribuzione delle sessioni in PHP in caso di load balancing su più server

DB

• Vantaggi– Permette di monitorare in tempo reale lo stato delle varie

sessioni tramite SQL– Prestazioni elevate

• Svantaggi– Occorre introdurre codice PHP per la gestione della sessione

(vedremo poi come) che eventualmente si può includere in modo trasparente impostando il parametro auto_prepend_file del PHP.ini

– Se il DB è lo stesso usato per i dati delle applicazioni occorre però verificarne la capacità sopportare entrambi i carichi di lavoro

Page 19: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Memcache

• Vantaggi– Decisamente più veloce di tutti in quanto è un

servizio di RAM condivisa– Non occorre introdurre codice PHP, basta

modificare i parametri del PHP.ini es:[Session]session.save_handler = memcachesession.save_path= "tcp://storage:11211"

• Svantaggi– Le sessioni non hanno un lock di scrittura … ….ma non è detto che sia uno svantaggio

Page 20: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Allora, abbiamo una soluzione?

• Teoricamente Si, ma in realtà tutte le soluzioni proposte hanno una debolezza architetturale:– Se lo storage smette di funzionare nessuna

sessione funziona più e quindi niente più login o carrelli

Page 21: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Possibile soluzione 3

Innanzitutto cambiamo un pochino le classiche caratteristiche di una macchina bilanciata:Non è tenuta a sapere di esserloSa di esserlo e conosce gli IP di tutte le altre macchine bilanciate

Produce risposte che, sia nel protocollo che nel contenuto, sono indistinguibili dalle risposte generate da un’altra macchina bilanciata

Il valore del cookie di sessione è in grado di veicolare informazioni sulla macchina che ha generato la sessione

E’ configurata esattamente come tutte le altre

Page 22: Distribuzione delle sessioni in PHP in caso di load balancing su più server

I presupposti

• Installare una memcache su ogni macchina che fungerà da storage per le sessioni di quel singolo server

• Ad ogni server è assegnata una lettera • Ogni macchina conosce le lettere di tutte le altre

ed è in grado di ricavare l’IP da una data lettera• L’Id di sessione generato da ogni server inizia

sempre con la lettera associata a quella macchina

Page 23: Distribuzione delle sessioni in PHP in caso di load balancing su più server

L’idea

• Quando un server riceve una richiesta per la prima volta genera una sessione nella memcache locale facendo iniziare il cookie di sessione con la propria lettera

• Ogni volta che un server riceve una richiesta con cookie di sessione estrae la prima lettera e, se è la propria usa la sessione locale, altrimenti si connetterà alla memcache del server che ha generato quella sessione

Page 24: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Esempio sessioni distribuite

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=xscelta2=y

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

A

B

Page 25: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Vantaggi

• Robustezza, tra i server si genera una connettività a “maglia”, in questo modo se un server cade tutti gli altre continuano ad operare salvo il ripristino delle sessioni dei client ”orfani”

• Velocità, derivante dall’uso di memcache

Page 26: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Svantaggi

• Occorre introdurre codice PHP per la gestione della sessione, ma come detto, con la direttiva auto_prepend si può fare in modo trasparente

Page 27: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Ulteriori migliorie

• Fare in modo che il dialogo tra i server avvenga su una rete diversa rispetto a quella sulla quale viaggia il traffico web (ma questa è una regola d’oro per tutte le soluzioni proposte)

• Mettere le memcache su server diversi da quelli che fanno da webserver, in questo modo la lettera si riferirà ad una batteria di server memcache

Page 28: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Batteria di webserver e memcache server

GET index.php?scelta=x HTTP/1.1………

a1b2c3d…scelta=xscelta2=y

HTTP 200 OKSet-cookie: SESSID=a1b2c3d..………

GET index.php?scelta2=y HTTP/1.1Cookie: SESSID=a1b2c3d..………

A

B

Page 29: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Come costruire un gestore di sessioni

• Attraverso la funzione session_set_save_handler è possibile sostituire le operazioni native con quelle personalizzate che vengono generate sugli eventi:– Open: Apertura sella sessione (prima fase di session_start)– Read: Lettura dei dati di sessione dallo storage (seconda fase di

session_start)– Write: Scrittura dei dati nello storage (prima fase di

session_write_close o termine dello script)– Close: Chiusura della sessione (seconda fase di session_write_close

o termine dello script)– Destroy: Distruzione dei dati della sessione (session_destroy)– GC: Pulizia delle sessioni scadute eventualmente invocata durante il

session_start

Page 30: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Una generica classe astratta di gestione sessioni

Page 31: Distribuzione delle sessioni in PHP in caso di load balancing su più server

L’implementazione I° parte

Page 32: Distribuzione delle sessioni in PHP in caso di load balancing su più server

L’implementazione II° parte

Page 33: Distribuzione delle sessioni in PHP in caso di load balancing su più server

Un esempio pratico