|
||
Specifiche:Progetto:Struttura di un server generico Gestore del server per rete con topologia ad anello Gestione locale del name server Gestione globale del name server Inserimento di una nuova associazione Cancellazione di una associazione Comando di lista file nei server Gestore per l'inserimento di nuovi nodi nella rete |
||
Descrizione del sistemaSi vuole creare un file server distribuito di piccole dimensioni, ovvero un sistema costituito da processi residenti su nodi diversi che cooperano tra loro al fine di rendere disponibile ad un utente esterno l'insieme dei files locali ad ognuno. I diversi server sono connessi alla rete Internet, non si fanno quindi ipotesi su quale sia la topologia di connessione a livello di rete, ma a livello di applicazione si definisce una struttura ad anello virtuale: ognuno ha un predecessore ed un successore. Questa scelta è giustificata dal piccolo numero di partecipanti. Si vuole che i diversi server comunichino tra loro in modo affidabile, si collegano quindi tramite connessioni permanenti che usinoTCP come trasporto. |
||
Interazione degli utenti esterni con il sistemaLe operazioni possibili per gli utenti sono la richiesta di download di un file e la richiesta della lista completa dei file scaribili dal server. La sintassi dei comandi è la seguente: E' previsto che il server risponda con codice di errore nel caso in cui si verifichi una delle seguenti situazioni: |
||
Evento |
Codice |
|
File non presente |
1500 |
|
Comando inesistente |
1200 |
|
Nome logico scorretto* |
1300 |
|
Sintassi comando scorretta |
1400 |
|
Anche il codice di errore viene inviato usando una comunicazione non affidabile, non vi è dunque certezza che il cliente lo riceva, ma di questo non ci si preoccupa. Per il trasferimento delle informazioni da server a client si usano connessioni TCP che vengono create appositamente; per il trasferimento di ogni file la connessione viene creata e poi distrutta ( connessione by-need ); per semplicità si dispone che il client utilizzi lo stesso numero di porta sia per la socket usata per l'invio della richiesta (porta UDP) che per la socket di ricezione del file (porta TCP): così facendo il server quando riceve la richiesta conosce la porta cui è agganciato il processo che aspetta il download. *: è possibile definire la grammatica da cui devono essere generati i nomi dei file inseriti: nella versione implementata l'unica caratteristica che si è imposta è che i nomi non superino i 50 caratteri. |
||
Inserimento di nuovi serverSi suppone che sia possibile aggiungere nuovi nodial sistema mentre questo è funzionante:i nuovi server che vogliono accedervi fanno una richiesta ad uno dei server che già vi appartengono. Il punto di inserimento del nuovo server viene negoziato tra quelli già presenti: viene prescelto come predecessore il nodo che dista da questo il minor numero di passi. |
||
Ipotesi di guastoCome ipotesi di guasto sulla caduta dei nodi si assume che non possano cadere contemporaneamente due nodi consecutivi nell'anello virtuale. A seguito della caduta di un nodo si ha la perdita di tutti i messaggi che questo ha ricevuto, ma che non è riuscito a ritrasmettere: questa possibilità dovrà essere tenuta in considerazione nella progettazione dei protocolli che regolano le diverse attività del sistema. |
||
Struttura del sistemaVolendo andare verso al riusabilità del software e l'estendibilità, si è cercata una soluzione che non fosse cablata sulle specifiche del problema, ma che fosse possibile, previa specializzazione, utilizzare in tutta una classe di problemi (in questo caso problemi che coinvolgano la collaborazione di diversi server). |
||
|
||
La figura riportata sopra indica come si è pensato di realizzare il sistema strutturandolo su più livelli: ogni livello sfrutta le funzionalità fornite dal precedente e ve ne aggiunge delle nuove che rende disponibili a quelli successivi. Struttura di un server genericoSi è realizzata per i server una struttura indipendente sia dalla topologia della rete ( intesa a livello applicativo ) su cui andranno ad operare che dalle politiche con cui questa verrà gestita: in tale struttura i singoli server hanno solo il compito di ricevere, mettere in esecuzione e spedire dei comandi. |
||
|
||
Breve descrizione dei componenti:Name Server:è previsto che ogni server abbia un name server; è stato implementato come una tabella di coppie ( nome fisico, nome logico ) e su cui sono definite tutte le operazioni per operarvi. Gestore del server: è il componente che coordina tutti i rimanenti ed in cui, nelle versioni specializzate, andranno inserite le politiche di gestione del server. Trasmettitore di comandi: si occupa della trasmissione di un comando su tutte le socket di uscita. Nel caso in cui una delle socket su cui deve scrivere cada, notifica l'evento al gestore del server inviandogli anche il comando che non è riuscito a trasmettere: sarà questo che, in funzione della politica che implementa, deciderà come comportarsi. |
||
Ricevitore di comandi dalla rete dei Server: ogni socket di ingresso ha un thread di ascolto che si occupa della ricezione dei comandi e dell'avvio dell'esecuzione di questi. Nel caso di caduta di una delle socket, notifica l'evento al gestore del server. Ricevitore di comandi dal client: ha una struttura diversa dal precedente in quanto dal client si ricevono linee di comando in formato testo, non oggetti di tipo comando; è composto quindi da un piccolo interprete che, una volta riconosciuto un comando lecito, genera il corrispondente comando in forma interna (ovvero crea una nuova istanza della classe comando associata alla richiesta ricevuta), e lo mette in esecuzione. |
||
Oss: anche la struttura di questo piccolo interprete è stata progettata in modo tale da non essere cablata sull'insieme di comandi fino ad ora gestiti. L'unica ipotesi di progetto è che i comandi siano identificati da un codice numerico. Si è creata una tabella in cui ad ogni codice numerico è stato associato il riferimento alla procedura che deve stabilire la correttezza del comando ed eventualmente metterlo in esecuzione. L'interprete quindi, una volta ricevuto il comando ne estrae il codice numerico, ricerca nella tabella la procedura corrispondente e la mette in esecuzione passando ad essa come parametro la stringa contenente il resto del comando. E' quindi sufficiente modificare la tabella ed aggiungere o togliere procedure di gestione per modificare l'insieme dei comandi gestibili. |
||
Gestore del server per rete con topologia ad anello:Volendo realizzare un anello virtuale, si definise che ogni server abbia un solo successore ed un solo predecessore. |
||
Al fine di ottenere questo, quando un nodo si accorge che il successore è caduto, instaura una connessione con il suo successore di secondo livello. |
||
Si dispone poi che al momento del riavvio del nodo caduto, questo si vada a reinserire nell'anello, ripristinando le connessioni, esattamente dietro il nodo che conosce come proprio successore. Il reinserimento avviene seguendo il seguente protocollo: |
||
Quando un nodo caduto si riavvia, instaura una connessione con il nodo che era suo successore prima del crash. |
||
Il successore riconosce che il nuovo nodo è il predecessore caduto, rompe quindi la connessione che era stata instaurata con il predecessore di secondo livello. |
||
Il predecessore del nodo riavviato sentendo che il proprio successore di secondo livello ha chiuso la connessione capisce che il proprio successore è tornato e crea quindi una nuova connessione con questo |
||
La rete ha quindi nuovamente assunto la struttura originale. Quando il nodo successore cade, prima del ripristino dell' anello, il trasmettitore di comandi si trova impossibilitato ad effettuare gli invii e notifica questo al gestore del server. |
||
Gestore del name serverOgni nodo possiede una name server che è costituito da una tabella in cui sono presenti le associazioni tra nome fisico e nome logico di ognuno dei file scaricabili dal File Server. |
||
Gestione locale del name server.E' necessario garantire che gli inserimenti e le cancellazioni eseguiti su un name server siano persistenti, ovvero non sia possibile che a causa di un crash del sistema vengano persi. Nome logico da inserire Nome fisico da inserire Valore booleano ( true = inserimento dell'associazione, false = cancellazione ) |
||
Gestione globale del name serverLe diverse operazioni di inserimento e cancellazione che si vogliono fare in un nodo, devono essere comunicate anche a tutti gli altri prima di poter divenire effettive (ovvero riconosciute valide in tutti i nodi). Questa comunicazione avviene tramite la trasmissione ai diversi nodi di richieste che hanno lo stesso formato delle registrazioni che si fanno sul log file. |
||
Inserimento di una nuova associazioneE' necessario garantire la coerenza dei diversi name server a seguito di inserimenti. Vista la possibilità di perdita di messaggi, nel nodo che inserisce la richiesta viene fissato un time-out: se alla scadenza di questo la richiesta non ha ancora fatto un giro, viene nuovamente inoltrata. Considerando le caratteristiche della rete creata, non si pone limite al numero di ritrasmissioni, questo in base alle seguenti considerazioni. la perdita del messaggio un ritardo nel tempo di consegna a causa della congestione della rete ( sia dell'anello virtuale che della rete fisica su questo si appoggia ); Un messaggio viene perso solo se cade il nodo che in quel momento lo ha ricevuto: è poco probabile che nelle diverse ritrasmissioni cadano sempre i nodi che hanno quel messaggio, quindi, ragionevolmente, questo protocollo si concluderà in un tempo finito. Bisogna considerare anche l'eventualità che il nodo proponente cada: per evitare che la sua richiesta continui a girare per l'anello (nessun altro nodo la riconosce come propria e quindi continua a propagarla), si impone che ogni nodo faccia un controllo aggiuntivo: chi riceve una richiesta inoltrata dal proprio precessore in quel momento caduto, la scarta. |
||
ProblemiE' possibile che due nodi cerchino di inserire "contemporaneamente" lo stesso nome logico (entrambi mettono sulla rete la richiesta prima che arrivi la notifica dell'altro): bisogna quindi fare in modo che solo la richiesta di uno dei due abbia successo. La richiesta del nodo Y arriva al nodo X prima che la richiesta di questo compia un intero giro: il nodo X si accorge quindi che un altro nodo sta tentando il suo stesso inserimento, a questo punto deve decidere quale delle richieste scartare. La richiesta del nodo Y arriva al nodo X dopo che la richiesta di questo ha già compiuto un intero giro (può accadere a causa di ritardi dovuti alla perdita della richiesta di Y ed alla caduta di Y stesso). In questo caso si decide di mantenere un comportamento analogo al precedente: si avrà f(X)<f(Y) e quindi si toglie la corrispondenza già presente e si inserisce la nuova. Questa politica può dare luogo a problemi se durante la finestra temporale che separa il primo aggiornamento del name server dal secondo, un cliente ha richiesto di scaricare proprio quel file: se lo chiedesse nuovamente dopo il secondo aggiornamento, otterrebbe un file diverso. |
||
Cancellazione di una associazioneAnche in questo caso si utilizza una soluzione analoga alla precedente, ma questa volta la cancellazione dal name server del nodo proponente, viene eseguita subito, prima della propagazione della richiesta (il nodo non vuole più rendere disponibile un file da subito). Esattamente come prima si fissa un time-out sul nodo che fa la cancellazione allo scadere del quale avviene la ritrasmissione. ProblemiIn questo caso non si hanno i problemi visti prima per 2 nodi che facciano 2 cancellazioni contemporanee, siccome solo chi possiede un file localmente può proporre la cancellazione del nome logico, ma si può avere un problema diverso dovuto alla possibile perdita del messaggio di cancellazione. |
||
Aggiornamento del name server di un nodo dopo la cadutaE' necessario che un nodo caduto, al momento del riavvio aggiorni il proprio name server rendendolo coerente con quello degli altri prima di ritornare ad essere operativo. Per fare questo, quando un nodo si accorge della caduta del suo successore, deve creare una tabella in cui inserire tutte le richieste di inserimento e cancellazione che riceve, ovvero tutte le richieste relative ad operazioni che cambino lo stato del name server. Al momento del ritorno del successore, questa tabella viene ad esso inviata ed esso elabora ordinatamente le richieste come avrebbe fatto normalmente, evitando però la propagazione( sono tutte richieste che sono state già propagate grazie al meccanismo di ripristino dell'anello a seguito della caduta di un nodo). |
||
Comando di downloadQuando un server riceve una richiesta di dowload, controlla che il nome logico richiesto appartenga al name server; nel caso in cui questo non accada, lo notifica immediatamente al cliente specificando il codice di ritorno. Altrimenti, controlla che il nome fisico associato sia ad esso locale: se ciò accade crea una connessione con il client ed invia un messaggio di 50 byte contenente il nome logico richiesto e di seguito il file, in caso contrario passa la richiesta al proprio successore.. |
||
Comando di lista file nel serverPer come è stato strutturato il name server, il comando di lista viene risolto in modo molto semplice: il server a cui viene inoltrato apre una connessione con il client e gli invia la lista dei nomi logici contenuti nel proprio name server. |
||
Gestore per l'inserimento di nuovi nodi nella reteE' necessario inserire un componente per l'ascolto delle richieste dei nuovi server. Si è usato un interprete con la stessa struttura dell'interprete per comandi client. Un server che si vuole inserire nell'anello deve segnalarlo ad uno qualsiasi dei server già presenti; questo si occupa di inviare sulla rete una richiesta con cui determinare il miglior punto di inserimento per il nuovo server. |
||
Solo i server che saranno in visibilità con il nuovo dovranno variare la loro conoscenza della rete, si è quindi ritenuto più efficiente, invece di sfruttare l'anello per la comunicazione dei messaggi del protocollo di inserimento, costruire una struttura a lato. |
||
Dopo aver segnalato la volontà di entrare nell'anello, il nuovo server si mette in attesa di venire "contattato" dal server che si è determinato essere il migliore predecessore: questo si occuperà di renderlo operativo inviandogli tutte le informazioni di cui necessita, ovvero, una copia aggiornata del name server, le tabelle che gli permetteranno di aggiornare il proprio successore, se caduto, e tutte le informazioni che permettano ad esso di avere una corretta visione della parte di rete che deve conoscere. |
||
E' sempre su iniziativa di questo nodo che il resto della rete viene aggiornato in modo corretto, si incarica cioè di comunicare ai nodi interessati (quelli per i quali il nuovo server deve essere in 'visibità') i cambiamenti da effettuare. |
||
Quindi, avendo aggiornato lo stato della rete, rompe il collegamento con il vecchio successore e comunica al nuovo server che il resto della rete è pronta per il suo inserimento: grazie al meccanismo di ripristino dell'anello si costituisce la nuova struttura. |
||
Il protocollo definito si vuole tenga presente la possibilità di caduta di nodi; si sono considerati i seguenti casi: |
||
Caduta del nuovo server prima dell'inizio della procedura di inserimento:Il nodo predecessore se ne accorge e l'operazione viene abortita. Una volta riavviato il nuovo server dovrà cominciare nuovamente la procedura di ingresso(segnalando la volontà di entrare nell'anello). |
||
Caduta del nodo di affaccio della richiestaCi si accorge che la richiesta ha compiuto un intero giro dell'anello quando raggiunge il successore del nodo di affaccio: questo riconosce che il mittente della richiesta è il suo predecessore e che questo è caduto; si incarica quindi di contattare il miglior predecessore. |
||
Caduta di uno dei nodi che saranno in visibilità con il nuovo serverIl problema in questo caso è fare in modo che al momento del ripristino del nodo caduto avvenga un aggiornamento della sua visione della rete che comprenda il nuovo server. Si sfrutta la coda dei comandi inserita per evitare di perdere messaggi durante il ripristino dell'anello: si mette il comando di aggiornamento della rete in cima a questa così al momento del reinserimento del nodo verrà trasmesso. |
||
Caduta del nodo prescelto come predecessoreCi si comporta come se il miglior predecessore fosse il predecessore del nodo in realtà prescelto (questo deve essere presente per le ipotesi di guasto fatte). |
||
TestPer monitare l'esecuzione dei diversi componenti, si è utilizzato il metodo dell'instrumentation code, ovvero si sono inserite nel codice delle istruzioni di stampa. |
||
Analisi delle prestazioniSi sono fatte delle rilevazioni per vedere l'andamento del ritardo della risposta dei server al crescere del numero di clienti contemporaneamente presenti ( si sono considerati 5, 10, 15, 20 e 25 clienti; ogni cliente ha compiuto 10 richieste ), con anelli costituiti da 3, 4 e 5 server. |
||
Dall'analisi dei risultati si può notare che nel range considerato la crescita del tempo di risposta è lineare rispetto alla crescita del numero di clienti. Oss: per le rilevazioni si sono utilizzati dei PC del Lab3, collegati su lan, quindi con condizioni di rete quasi ideali; i dati raccolti non hanno quindi una valenza per quanto riguarda le prestazioni reali del sistema ma vogliono solo fornire una indicazione. |