Programmazione distribuita
Di Offertucci Mario
Introduzione
I sistemi distribuiti
Un sistema distribuito consiste in un insieme di macchine, ognuna gestita in maniera autonoma, con la propria password di root, connesse attraverso una rete. Non c’è una persona che conosce tutte le password di root di tutte le macchine. Ogni nodo del sistema esegue un insieme di componenti che permettono di coordinare il lavoro attraverso uno strato software detto middleware, in maniera che l’utente, o anche in maniera limitata, il programmatore e il progettista, percepiscano il sistema come un’unica entità integrata.
I sistemi distribuiti rispondono a motivazioni sia di natura economica che di natura tecnologica. Di natura economica perché permettono di integrare più sistemi diversi tra di loro, per esempio nel caso in cui due aziende vogliono fondersi in una ma ognuna ha il proprio sistema informativo, che ovviamente non può essere cambiato. Cambiare un sistema informativo di un’azienda comporta molti problemi, bisognerebbe poi cambiare tutti i sistemi integrati con quello centrale, e ciò comporta molte spese. Perciò i due sistemi vengono integrati per fare in modo che funzionino insieme. Allo stesso modo un’azienda può dividersi in vari sottogruppi che possono interagire tra di loro.
I sistemi distribuiti ci permettono inoltre di avere un time to market (cioè il tempo necessario per poter arrivare al prodotto finale) quanto più breve possibile. Sia per l’evoluzione continua, sia perché le richieste dei clienti variano significativamente in poco tempo. Sistemi che devono offrire funzionalità complesse sono tipicamente assemblati utilizzando componenti preesistenti (i cosiddetti off the shelf) che però, spesso, hanno requisiti hardware e software diversi che necessitano di un ambiente distribuito per poter comunicare.
Infine la diffusione di internet e la sua evoluzione fa sì che i servizi possano essere raggiunti da un numero smisurato di utenti. Questo enorme afflusso può portare a far cadere il sito. I sistemi distribuiti riescono a risolvere questo problema distribuendo gli utenti su più server diversi. Il sito principale viene copiato su altri server e gli utenti navigano sul sito accedendo a server diversi.
Dal punto di vista tecnologico le tecnologie corrono, vanno avanti, ed è importante riuscire ad integrare le nuove tecnologie nei sistemi che sono già esistenti. Ci sono diverse leggi nell’informatica che fanno previsioni sul suo andamento, per esempio:
- Legge di Moore: La legge di Moore afferma che la densità di transistor nei processori si raddoppia ogni 18 mesi. Cioè che la potenza di calcolo raddoppia ogni 18 mesi.
- La legge di Gilder: La legge di Gilder afferma che la capacità di trasmissione si raddoppia ogni anno, così come il traffico di internet.
- La legge di Shugard: La legge di Shugard suggerisce che la capacità di memorizzazione aumenta ogni 4 anni di un fattore 10.
Alcune recenti ricerche, affermano che lo sviluppo di internet segua anch’esso la legge di Moore. Il modo migliore per poter utilizzare le nuove tecnologie hardware è quello di utilizzare i sistemi distribuiti. Ci sono però notevoli problemi, riguardanti i malfunzionamenti, la latenza, l’accesso concorrente alle risorse e l’ottimizzazione del carico che arriva sul nodo.
Oltre questi problemi ci sono quelli di retrocompatibilità con sistemi molto vecchi, i quali spesso non hanno strumenti di debugging evoluti o si basano su approcci NON orientati agli oggetti, che non favoriscono il riutilizzo del codice e l’estendibilità dei sistemi. La riusabilità e l’integrazione rappresenta un problema importante, non sempre è necessario “reinventare la ruota”, e la possibilità di poter integrare soluzioni pre-esistenti, nonostante le tecniche di progettazione diverse, è una priorità importante per gli ambienti di sviluppo per sistemi distribuiti.
Un modello di riferimento: Open Distributed Processing
Per progettare un sistema distribuito occorre un modello comune che serva come astrazione per produttori, sviluppatori e progettisti in modo da essere indipendente dalla specifica implementazione tecnologica. Uno sforzo importante è stato fatto dall’ISO/IEC per proporre un modello formale delle architetture dei sistemi distribuiti. Questa specifica, realizzata in 4 documenti (22, 23, 24, 25), si chiama “The Reference Model of Open Distributed Processing” (RM-ODP).
Il modello RM-ODP si basa ed integra il modello tradizionale di rete proposto da ISO/OSI su sette layer. Il modello RM-ODP non si limita, come ISO/OSI, a trattare con i problemi di comunicazione tra sistemi eterogenei, ma punta ad astrarre e standardizzare il concetto di portabilità e di trasparenza all’interno di un sistema distribuito.
Le caratteristiche di un sistema distribuito
I sistemi distribuiti si caratterizzano per un discreto numero di aspetti, che vengono utilizzati per permettere di utilizzare a pieno il loro potenziale ed assicurare l’alta disponibilità dei servizi offerti. Possiamo identificare queste caratteristiche attraverso una serie di keywords:
- Remoto: Le componenti di un sistema distribuito devono poter essere locali o remote, quindi anche potenzialmente localizzate su macchine diverse;
- Concorrenza: Un sistema distribuito è per sua stessa natura concorrente, nel senso che possono esserci in esecuzione diverse istruzioni contemporaneamente, e non esistono strumenti come lock o semafori per la sincronizzazione;
- Assenza di uno stato globale: Nei sistemi singoli è possibile fare uno snapshot del sistema per verificare lo stato della macchina in quel preciso momento, nei sistemi distribuiti ciò non è possibile perché le varie parti del sistema sono divise su diverse macchine e non è possibile definire con certezza lo stato in cui si trova ciascun nodo;
- Malfunzionamenti parziali: Ogni componente di un sistema distribuito può smettere di funzionare correttamente, in maniera indipendente dalle altre componenti, e il malfunzionamento non deve danneggiare il funzionamento di altre procedure su altri sistemi;
- Eterogeneità: Un sistema distribuito, per sua stessa definizione è eterogeneo, sia per software che hardware. L’eterogeneità si realizza in tutti i contesti: hardware, sistema operativo, rete, comunicazione, protocolli di rete, linguaggi di programmazione, applicazioni ecc. Questo perché l’informatica scorre, va avanti veloce e quindi spendendo la stessa somma di denaro di un nodo già esistente, posso crearne uno migliore, con più RAM, un processore migliore ecc, perché la tecnologia è andata avanti;
- Autonomia: Un sistema distribuito non ha un singolo punto dal quale può essere controllato, coordinato e gestito. La collaborazione va ottenuta mediando le richieste del sistema distribuito con quelle del sistema che gestisce ogni singolo nodo tramite politiche di condivisione e di accesso specificate e rigidamente applicate;
- Mobilità: I nodi devono essere mobili, cosa vuol dire? Vuol dire che i dati devono poter essere scambiati tra un nodo e l’altro in modo da poter adattare al meglio le prestazioni del sistema;
Requisiti non funzionali
La realizzazione di un sistema distribuito non è semplice e comporta la necessità di considerare vari aspetti generali e globali dell’architettura, standardizzati in modo tale che possano servire da specifica per i vari fornitori di piattaforme hardware e software con lo scopo di poter fornire strumenti adeguati per rendere più agevole la progettazione, implementazione e manutenzione di un sistema distribuito. Questi aspetti non hanno a che fare con le funzionalità del sistema, cioè non fanno parte dei requisiti funzionali identificati durante la fase di analisi dei requisiti che precede la fase di analisi, progettazione e implementazione.
Hanno invece a che fare con i cosiddetti requisiti non funzionali, che indicano la qualità del sistema e non sono identificabili in una specifica parte del sistema, ma sono globali e vanno considerati come fattori che hanno un impatto significativo sull’architettura. Questi requisiti non funzionali specificano che la progettazione deve puntare a realizzare sistemi distribuiti che:
- Siano aperti, in modo da far collaborare insieme diverse componenti del software attraverso interfacce e servizi ben documentati e aderenti a standard noti e ben riconosciuti. Questo aspetto è importante per far evolvere il sistema, per poterlo integrare in altri sistemi, o anche per non restare legati ad un singolo fornitore, avendo la possibilità di affidarsi ad un altro fornitore senza rischi per l’architettura;
- Siano integrati, così da incorporare al loro interno sistemi e risorse differenti senza dover utilizzare strumenti ad-hoc. Questo permette di trattare in maniera efficiente con il problema dell’eterogeneità hardware, software e di applicazioni;
- Siano flessibili, per poter evolvere e far evolvere i sistemi distribuiti in maniera da integrare i sistemi legacy al proprio interno. Un sistema distribuito dovrebbe prevedere l’opportunità di essere modificato durante l’esecuzione in modo da poter accomodare cambi a run-time, riconfigurandosi dinamicamente;
- Siano modulari, in modo da permettere ad ogni componente di essere autonoma ma con un grado di interdipendenza verso il resto del sistema;
- Supportino la federazione di sistemi, in modo da unire diversi sistemi, dal punto di vista amministrativo oltre che architetturale, per lavorare e fornire servizi in maniera congiunta;
- Siano facilmente gestibili, per permettere il controllo, la gestione e la manutenzione per configurare i servizi, la loro qualità e le politiche di accesso;
- Forniscano supporto per la qualità del servizio (Quality of service), cioè poter funzionare anche in caso di malfunzionamenti. In questi casi un sistema centralizzato non funzionerebbe perché tutto il sistema è guasto, nei sistemi distribuiti invece il sistema continua a funzionare anche se un nodo è danneggiato. Ovviamente le funzionalità che gestiva quel nodo non sono accessibili, però il resto del sistema continua a funzionare. Se ci sono funzionalità cruciali, come per esempio il login, in questo caso devono essere previsti più nodi che si occupano di queste funzionalità, in modo tale che se il nodo che si occupa del login cade gli utenti possono comunque utilizzare il servizio contattando un altro server che copre il nodo caduto;
- Siano scalabili, perché qualsiasi sistema distribuito accessibile ad internet può essere soggetto a picchi di carico non prevedibili e deve essere in grado di gestirli. Se ci sono picchi di carico il sistema può duplicare la pagina sovraccaricata e indirizzare gli utenti per il 50% sulla pagina originale e per il 50% sulla copia. Inoltre si deve prevedere l’evoluzione del sistema per accomodare evoluzioni del contesto aziendale che può crescere velocemente, aumentando notevolmente la platea di utenti che accedono ai servizi forniti dal sistema;
- Siano sicuri, così che utenti non autorizzati non possano accedere a dati sensibili;
- Offrano trasparenza, mascherando i dettagli e le differenze dell’architettura sottostante che assicura la distribuzione dei servizi. Il progettista/programmatore deve avere un certo grado di indipendenza dai dettagli della distribuzione dell’architettura. È però vero che questa trasparenza non deve essere completa, e che progettisti/programmatori debbano essere coscienti della natura distribuita di alcune caratteristiche (maggiori informazioni al riguardo verranno trattate più avanti).
La trasparenza di un sistema distribuito
La definizione di sistema distribuito che abbiamo dato sottolinea un aspetto importante: i dettagli del sistema che offre le funzionalità operative sono nascosti agli utenti. In questo modo il sistema viene identificato come un’unica entità. La trasparenza permette al progettista/sviluppatore di lavorare in un ambiente che non fornisce informazioni specifiche sull’architettura del sistema. Il progettista/sviluppatore ignora l’eterogeneità dei nodi, il fatto che il sistema sia diviso su più nodi o che ci siano diversi nodi che offrono le stesse funzionalità.
La trasparenza permette uno sviluppo migliore, perché lo sviluppatore deve concentrarsi solo su ciò che sta creando. Inoltre permette il riutilizzo delle applicazioni sviluppate. Perché visto che sono state sviluppate nella totale trasparenza dei dettagli sottostanti, possono essere riutilizzate in contesti diversi su sistemi diversi.
La trasparenza che viene fornita da un sistema distribuito ricade in diverse tipologie, strettamente collegate e dipendenti l’una dall’altra.
Trasparenza di accesso
La trasparenza di accesso nasconde le differenze tra la rappresentazione dei dati e il meccanismo di invocazione che permette l’interoperabilità tra gli oggetti. Cioè noi non sappiamo se l’accesso agli oggetti viene fatto in locale o in remoto. In questo modo un oggetto può essere spostato da un nodo all’altro a run-time. In genere questo tipo di trasparenza viene fornito di default dai sistemi.
Trasparenza di locazione
La trasparenza di locazione non permette di utilizzare le informazioni circa la posizione del nodo. Devono infatti essere utilizzati sistemi di naming per disaccoppiare il nome del nodo con la sua reale posizione. Un nodo potrebbe essere spostato e il suo indirizzo potrebbe cambiare, in tal modo basterebbe aggiornare la tabella di naming per risolvere tutti i problemi. Senza questa trasparenza non si potrebbero spostare gli oggetti da un nodo all’altro.
Trasparenza di migrazione
Questa trasparenza nasconde la possibilità di spostare i dati da un nodo all’altro, per migliorare le prestazioni in base alla posizione, per effettuare operazioni di bilanciamento del carico oppure per eseguire la manutenzione di un nodo. La trasparenza di migrazione dipende alla trasparenza di accesso (che permette di accedere ad un oggetto, anche se locale, tramite la propria interfaccia che viene usata da remoto) e dalla trasparenza di locazione (che nasconde la locazione fisica di un oggetto, permettendo l’accesso attraverso un sistema di naming logico fornito dal sistema).
Trasparenza di replica
Con questo tipo di trasparenza, il sistema maschera il fatto che una singola componente venga replicata da un certo numero di copie (dette repliche) che vengono posizionate su diversi nodi del sistema. Ovviamente si deve stare attenti a mantenere assolutamente coerente lo stato del sistema e aggiornare le repliche in base alla componente originale. Anche questo tipo di trasparenza dipende da quella di accesso e di locazione. Le repliche vengono utilizzate per diversi scopi:
- Per le prestazioni, replicando le componenti che hanno un maggior carico, in modo da minimizzare la latenza.
- Oppure per far scalare il sistema in presenza di un aumento del carico di lavoro.
Trasparenza alle transazioni
La trasparenza alle transazioni nasconde all’utente le attività di coordinamento che vengono svolte per garantire l’interoperabilità del sistema. Se per esempio un utente interrompe un’operazione a metà del suo svolgimento chiudendo il browser, il sistema deve rimuovere le eventuali informazioni aggiornate fino a quel momento. Questa trasparenza garantisce l’atomicità delle operazioni in modo che il progettista/sviluppatore non se ne preoccupi. È una funzionalità cruciale per far sì che in presenza di malfunzionamenti una risorsa non si trovi in uno stato incoerente.
Trasparenza alla persistenza
Questo tipo di trasparenza scherma l’utente dalle operazioni che compie il sistema per rendere persistente un oggetto durante una fase di non utilizzo. Per ottimizzare le prestazioni del sistema, gli oggetti di utilizzo raro non vengono mantenuti attivi nella memoria principale, ma vengono de-attivati e salvati in memoria secondaria. Quando serviranno verranno riattivati, spostati in memoria primaria e utilizzati. Questa trasparenza dipende dalla trasparenza di locazione perché l’oggetto può fisicamente trovarsi su un altro nodo e può essere attivato da un nodo diverso da quello su cui era stato de-attivato.
Trasparenza alla scalabilità
La scalabilità è uno dei principali vantaggi dei sistemi distribuiti. Un sistema distribuito è scalabile perché permette di gestire picchi di carico che possono incrementare improvvisamente, senza dover modificare la propria architettura e organizzazione. Oggigiorno è necessario avere un sistema scalabile, dato che la platea di utenti ai quali un servizio è offerto è smisurata. Un servizio deve poter scalare dalle poche decine alle centinaia di migliaia di utenti, senza che ciò comporti la riprogettazione del sistema. Si potranno inserire nuove risorse, ma senza apportare modifiche sostanziali. La trasparenza alla scalabilità fa sì che il progettista non si preoccupi di come il proprio servizio scalerà all’aumentare delle richieste. Sarà il sistema che si occuperà della migrazione dei dati e della loro replica. Per questo motivo su basa sulla trasparenza di migrazione e di replica.
Trasparenza alle prestazioni
Il sistema distribuito assicura che questo tipo di trasparenza renda il progettista/sviluppatore ignaro dei meccanismi che vengono utilizzati per migliorare le prestazioni del sistema:
- Bilanciamento del carico: Il carico viene spostato da nodi sovraccarichi a nodi che non stanno eseguendo operazioni;
- Ottimizzazione della latenza: I dati vengono copiati su nodi più vicini ai luoghi dove vengono usati più frequentemente.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Programmazione distribuita - Fondamenti
-
Programmazione Distribuita - Serverless Computing
-
Programmazione Distribuita - Java EE
-
Programmazione Distribuita - Cloud Computing