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
2. 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
3. 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)
4. 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
5. Funzionamento della sessione HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x a1b2c3d…scelta=x scelta2=y GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ………
6. 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).
7. 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
8. 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.
9. Problema del bilanciatore HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta2=y
10. 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
11. Problema del bilanciatore A HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x scelta2=y GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ……… B A) “SESSID=a1b2c3d..”
12. 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
13. 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)
14. Possibile soluzione 2 Concentrazione dei dati I dati di sessione vengono accentrati in un unico storage condiviso che può essere file sharing, DB, memcache
15. Esempio di sessioni accentrate HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ……… scelta2=y
17. 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)
18. 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
19. 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.inies:[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
20. 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
21. Possibile soluzione 3 Innanzitutto cambiamo un pochino le classiche caratteristiche di una macchina bilanciata: Non è tenuta a sapere di esserlo Sa 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
22. 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
23. 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
24. Esempio sessioni distribuite A HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x scelta2=y GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ……… B
25. 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
26. Svantaggi Occorre introdurre codice PHP per la gestione della sessione, ma come detto, con la direttiva auto_prepend si può fare in modo trasparente
27. 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
28. Batteria di webserver e memcache server A HTTP 200 OK Set-cookie: SESSID=a1b2c3d.. ……… a1b2c3d…scelta=x scelta2=y GET index.php?scelta=x HTTP/1.1 ……… GET index.php?scelta2=y HTTP/1.1 Cookie: SESSID=a1b2c3d.. ……… B
29. 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_closeo termine dello script) Close: Chiusura della sessione (seconda fase di session_write_closeo termine dello script) Destroy: Distruzione dei dati della sessione (session_destroy) GC: Pulizia delle sessioni scadute eventualmente invocata durante il session_start