Proponiamo un ciclo di articoli dedicato a sviluppatori che vogliono approfondire l’uso della tecnologia cloud e il concetto di scalabilità orizzontale: vediamo come passare da un’applicazione tradizionale ad un’applicazione cloud-oriented.
Clicca qui per leggere l’introduzione!
Nell’ultimo articolo abbiamo introdotto il concetto di Object Storage.
In questo articolo analizziamo lo step, successivo all’introduzione dell’Object Storage, necessario a portare un’applicazione tradizionale in cloud. Nello specifico, parliamo di come rendere l’applicazione scalabile orizzontalmente.
Qualora abbia necessità di aggiungere risorse alla mia applicazione, posso eseguire uno Scaling Verticale e aumentare le risorse del server su cui l’applicazione è installata. Si tratta della modalità di scaling più diffusa: raddoppiando le risorse del server raddoppiano quelle a disposizione dell’applicazione.
L’adozione delle tecnologie di virtualizzazione e, in seguito, delle tecnologie cloud ha aperto un’altra possibilità: lo Scaling Orizzontale. In poche parole, si tratta di “duplicare” il server applicativo e distribuire il carico di lavoro bilanciando tra i due server.
Analogamente a quanto posso fare con uno scaling verticale, lo scaling orizzontale raddoppia le risorse a disposizione della mia applicazione, ma introduce al contempo importanti benefici.
Ad esempio:
Lo scaling orizzontale introduce però alcune complessità dovute alla moltiplicazione dei server, tra cui:
La gestione dei file è facilitata dall’introduzione dell'Object Storage nel nostro applicativo (vedi articolo precedente): quando il server B deve gestire la richiesta di un file precedentemente caricato tramite il server A, la richiesta va comunque a buon fine, perchè il file in questione viene richiesto all’Object Storage.
Agli albori dello scaling orizzontale, il problema principale legato ai file era la gestione della sessione utenti. La sessione utenti veniva salvata nel file system e nemmeno l’object storage sopperiva a questo problema: dato che tipicamente una sessione utente è presente in ogni richiesta applicativa, i tempi necessari a reperire la sessione mediante l’Object Storage erano troppo alti. Oggi è difficile imbattersi in questo problema, perché la maggior parte dei framework che usano il concetto di sessione la salvano in un cookie lato client o nel database.
Il deploy richiede un’installazione simultanea sui due o più server - funzione ormai inclusa in qualsiasi sistema di deploy. Infatti, la complessità del deploy è un’altra: è sempre possibile avere due versioni del mio applicativo che girano in contemporanea (la nuova versione e la precedente). Si tratta di un dettaglio importante di cui si deve tenere conto in fase di sviluppo, che ci permetterà di evitare breaking changes fra versioni successive.
Proviamo spiegarlo con un esempio classico:
Se devo rinominare una colonna di una tabella, devo farlo in 2 versioni, non in una. La versione 0 ha la colonna X, la versione 1 deve smettere di usare la colonna x e usare la colonna y, la versione 2 deve eliminare la colonna X.
In questo modo la versione 0 e 1 possono lavorare in contemporanea senza che una generi errori e lo stesso vale per le versioni 1 e 2.
Come abbiamo detto, le richieste devono essere bilanciate fra i server.
Per fare questo, le richieste devono prima passare attraverso un load balancer. In Amazon Web Services il load balancer si chiama ELB (Elastic Load Balancer) ed è un servizio concettualmente semplice: le richieste arrivano dai client (siano questi applicazioni mobile, browser web o altro) e vengono inoltrate ai server di backend in base alle impostazioni del balancer.
È necessario andare su cloud per impostare il nostro applicativo in questo modo? Assolutamente no: possiamo predisporre un server tramite un servizio di proxypass come Nginx (se parliamo di HTTP) o come l’intramontabile HAProxy ( se abbiamo bisogno di scendere a livello di TCP/UDP).
La differenza sostanziale è che il nostro proxy in ambiente on-premise sarà probabilmente un server, e quindi un SPOF (Single Point Of Failure), mentre ELB è un servizio bilanciato e ridondante a sua volta.
L’applicativo deve essere stateless: tutte le informazioni di cui necessito devono arrivare dal client o persistere all’esterno (Object Storage, Database, ecc.). Di conseguenza, non posso usare la RAM del mio server per persistere informazioni fra richieste, devo invece inserirle in un database (nel senso ampio del termine).
Infine, ricordiamo di prestare attenzione a chi lancia le migrazioni sul database: deve essere solo uno dei due server applicativi.
Resta aggiornato su tutte le novità di Nosco, i nostri eventi ed i nuovi articoli del blog.