_________________________________________________________Introduzione
4
INTRODUZIONE
OBIETTIVI
Gli obiettivi del tirocinio svolto, e del presente documento, sono lo studio di un
insieme di protocolli per la progettazione di reti Peer-to-Peer e la creazione di un
middleware basato su di essi. Le librerie utilizzate appartengono al pacchetto JXTA,
sviluppato dai ricercatori della Sun Microsystem[1] e il linguaggio di
programmazione usato per la loro implementazione è JAVA.
Il middleware potrà essere ulteriormente sviluppato e utilizzato da applicativi futuri,
grazie alla sua portabilità, flessibilità e modularità. È possibile, infatti, estendere le
classi presenti per sviluppare applicativi che prevedono gli elementi essenziali del
modello Peer-to-Peer (condivisione di risorse, creazione di gruppi, ricerca e scambio
di messaggi).
ORGANIZZAZIONE DEL LAVORO
Il presente documento è suddiviso in cinque capitoli, ognuno dei quali si occupa di
uno specifico argomento.
Il primo capitolo presenta una panoramica generale sulle reti Peer-to-Peer; il primo
argomento trattato è rappresentato dalle problematiche del paradigma client/server:
viene dapprima data una descrizione generale sul funzionamento di questo modello
e, in seguito, ne si pongono in evidenza i limiti e i problemi; si sottolinea il fatto che
la causa di tali problemi è da ricercarsi nel vasto successo che il client/server ha
avuto negli ultimi anni e si introduce il paradigma Peer-to-Peer come modello
alternativo o complementare. Vengono definiti, in seguito, i concetti di base del
modello Peer-to-Peer e vengono descritte nel dettaglio le diverse topologie di reti;
per ciascuna, viene trattato il funzionamento del meccanismo di ricerca di una
risorsa. Tale argomento viene trattato, nel dettaglio, nella seconda parte del capitolo:
qui, infatti, vengono descritti diversi algoritmi di ricerca e per ciascuno se ne
sottolineano vantaggi e svantaggi, a seconda del criterio di valutazione utilizzato.
_________________________________________________________Introduzione
5
L’ultima parte del primo capitolo, infine, tratta brevemente l’argomento delle reti
semantiche, implementabili, in parte, dal progetto realizzato.
Il secondo capitolo descrive nel dettaglio il funzionamento del progetto JXTA. Dopo
un’introduzione generale in cui si spiegano gli obiettivi di questo progetto, si
descrive l’architettura di JXTA, la quale, come si vedrà è composta da tre livelli.
Successivamente vengono definiti e descritti nel dettaglio, i concetti fondamentali di
JXTA, i quali sono comuni a tutte le applicazioni P2P: peer, gruppi, messaggi e
servizi generici. La terza parte di questo capitolo si occupa di descrivere la struttura
della rete JXTA: vengono definite le varie tipologie di peer e per ciascuna di esse il
ruolo assunto nella rete. Sempre in questa parte, inoltre, viene illustrato un esempio
relativo alla trasmissione di una query. L’ultima parte, infine, tratta dei protocolli
JXTA; si vedrà, a tal proposito, che JXTA è composto da sei protocolli. Per ciascuno
di essi viene fornita un’accurata descrizione e gli esempi reali di utilizzo.
Il terzo capitolo è dedicato ad una parte importante del progetto realizzato:
l’implementazione vera e propria dei servizi. Tale capitolo è composto da due parti:
la prima parte mostra la struttura generale del progetto e l’organizzazione delle
classi. La seconda parte, invece, è a sua volta divisa in paragrafi: uno per ogni
servizio realizzato. Per ogni servizio viene descritta nel dettaglio la classe che lo
implementa: si parla del costruttore, delle strutture principali che la compongono, dei
metodi invocati e invocabili. Per aiutare la comprensione vengono fornite, nella
descrizione di parti piú complicate, pezzi di codice veri e propri opportunamente
descritti.
Il quarto capitolo definisce l’implementazione del peer vero e proprio. Si vedrà come
le classi spiegate nel terzo capitolo possono essere utilizzate, gestite e connesse tra
loro per fornire i servizi all’interno della rete JXTA.
L’ultimo capitolo, infine, descrive un esempio di applicazione sviluppata su questo
middleware. È stata, infatti, creata un’apposita interfaccia grafica (di fatto si tratta di
un prototipo) per permettere di utilizzare la piattaforma realizzata; tale capitolo
mostra proprio il funzionamento e l’utilizzo di questo applicativo.
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
6
CAPITOLO 1: DAL PARADIGMA C/S AL P2P
1.1 I PROBLEMI DEL MODELLO CLIENT/SERVER
Il paradigma client/server è alla base del funzionamento del Web. Secondo questo
modello giocano un ruolo fondamentale due elementi chiave: il client e il server. Il
primo è responsabile dell’inizio della comunicazione; può essere visto come l’utente
che cerca una pagina web o come un qualsiasi processo che necessita di una risorsa
presente in remoto. Il server, invece, rappresenta la macchina (o l’insieme di
macchine) che possiedono le risorse e le mettono a disposizione dei vari client.
Il server può essere visto come un processo sempre attivo che resta in ascolto delle
richieste e ad ogni richiesta ottenuta lancia l’azione per gestirla; quest’azione può
essere o semplicemente la restituzione di una risorsa statica (come ad esempio una
pagina web) oppure l’invocazione di ulteriori programmi (come accade con i cgi). Il
server, inoltre, è responsabile del mantenimento delle sessioni con i vari client e della
chiusura delle diverse connessioni aperte con esso.
Il protocollo HTTP (che è alla base di Internet) si basa proprio sul modello
client/server; la comunicazione, infatti, si compone di due azioni fondamentali:
l’HTTP Request e l’HTTP Response. La prima è utilizzata dal client per richiedere
una risorsa (nella sintassi è necessario inserire l’indirizzo del server a cui chiedere la
risorsa, la porta di comunicazione e la risorsa stessa), mentre la seconda è utilizzata
dal server per inviare le risposte (o, eventualmente, messaggi di errore); bisogna,
inoltre, sottolineare che prima che abbia luogo lo scambio di messaggi è necessario
che la connessione (TCP o UDP) venga “aperta”. Per aprire una connessione non è
sufficiente una richiesta del client, ma occorre che il server accetti la connessione e la
notifichi al client stesso.
Ricapitolando, quindi, ad ogni richiesta di una risorsa le operazioni che client e
server compiono sono molteplici:
1. Il client chiede al server una connessione (TCP o UDP)
2. Il server accetta la connessione e la notifica al client
3. Il client richiede la risorsa
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
7
4. Il server controlla la disponibilità della risorsa ed invia un’HTTP Response
5. Il client riceve una risposta e la parsifica per renderla visibile
6. La connessione viene chiusa
Se si considera che oltre a questo abbiamo anche la traduzione degli indirizzi da
simbolici a numerici (compito dei server DNS) e che il numero di queste operazioni
è estremamente grande (perché bisogna tenere conto del fatto che una pagina web
spesso è composta da contenuto multimediale), allora si può notare che il carico della
rete è molto elevato.
Oltre a questi elementi bisogna, inoltre, considerare la natura della risorsa richiesta.
Ci sono, infatti, due tipologie di applicazioni:
• Una tipologia in cui è fondamentale tenere conto dei tempi in cui le risorse
vengono trasmesse
• Un’altra tipologia in cui non si possono tollerare errori nella trasmissione
Esempi di applicazioni della prima famiglia sono tutte quelle multimediali o in real-
time: video-telefonate, video-conferenze o giochi interattivi i quali non possono
tollerare ritardi nella comunicazione (mentre sono tollerabili piccoli errori nella
trasmissione); esempi della seconda famiglia sono, invece, tutte quelle applicazioni
che richiedono lo scambio e la trasmissione di file nelle quali anche un solo byte
errato può portare alla perdita totale dell’informazione (mentre non sono
fondamentali i tempi). I server e le reti devono poter garantire anche questi servizi.
Il problema maggiore di questo tipo di architettura risiede principalmente
nell’enorme successo che ha avuto, e sta avendo tuttora, Internet. Fino a pochi anni
fa il numero di utenti collegati al Web era un numero tale da non risultare un
problema né per la rete, né tanto meno per i server. I problemi sono sorti nel
momento in cui si è passati dal Web publishing al Web-based information
system[2]: in passato il web veniva utilizzato come un canale aggiuntivo per
l’informazione; Internet veniva visto non come una fonte a sé stante di informazione,
ma come un “contorno” all’informazione già esistente. In questo modo, cercare una
risorsa su Internet non era vista come un’operazione fondamentale; gli stessi siti
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
8
venivano poco aggiornati e il carico di lavoro a cui venivano sottoposti i server erano
adatti alle proprie capacità.
Con il passare del tempo, tuttavia, il Web ha assunto sempre più importanza
diventando non solo una cornice alle informazioni, ma esso stesso una fonte.
Diventa, in questo modo, fondamentale l’aggiornamento e la presentazione dei siti; la
stessa informazione rappresentata non è più quella tradizionalmente composta da
immagini e testo, ma può contenere anche informazioni multimediali come audio,
filmati o animazioni. Le cause di questo importante cambiamento sono da
rintracciarsi nel vasto incremento, che si è avuto in questi anni, di utenti connessi ad
Internet: dal 1993 al 2002 tale numero è aumentato di circa 147 volte e sono occorsi
soltanto cinque anni per raggiungere i 50 milioni di utenti (a differenza dei 38 per la
radio o dei 13 per la televisione).
Un numero così vasto di utenti (oltre 150 milioni di host) ha portato non pochi
problemi ad una struttura basata sul paradigma client/server. La velocità dei
calcolatori è cresciuta molto negli ultimi anni, così come la larghezza di banda da
affidare a ciascuna comunicazione, ma tale crescita non è riuscita a tenere il passo
della diffusione di Internet. I problemi più grandi sono a carico dei server: ciascun
server, infatti, può essere collegato a migliaia di client ognuno dei quali effettua
richieste diverse e sempre più complesse, che non sempre possono essere soddisfatte.
Una soluzione adottata per cercare di risolvere questo tipo di problemi è stata quella
di avere un server principale (il Content provider) e una serie di altri server più o
meno secondari; ciascuno di questi server conserva al suo interno una copia dei dati
contenuti nel Content provider e, nel momento in cui un client chiede una risorsa,
questa sarà ceduta da uno dei server secondari (quello meno carico di lavoro). La
gerarchia di macchine può essere anche a molti livelli, distribuendole sia su una rete
locale sia su una geografica. Una simile struttura, tuttavia, comporta due svantaggi:
in primo luogo si ha una ridondanza di informazioni non indifferente poiché gli stessi
dati vengono copiati su macchine diverse. In secondo luogo occorre effettuare, ad
ogni richiesta, una scelta della specifica macchina che dovrà soddisfarla e questo
comporta un ulteriore carico di lavoro e dispendio di tempo.
Un'altra soluzione adottata è stata quella del Web Cluster: secondo questa struttura,
un unico server vene implementato da diverse macchine distribuite localmente in
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
9
un’area. In questo modo l’insieme di macchine che implementano lo stesso server,
faranno riferimento ad un unico indirizzo IP, mentre il proprio indirizzo sarà
mascherato; per garantire ciò occorre avere un Web Switch che conterrà l’indirizzo
del server visibile dall’esterno e che servirà ad instradare su ciascuna macchina le
richieste. Anche in questo caso, tuttavia, occorre tenere conto delle caratteristiche del
Web Switch che rappresenta una sorta di “collo di bottiglia” poiché è lui ad essere
collegato a molteplici client ed è lui a dover gestire l’instradamento verso le diverse
macchine.
Nella maggior parte dei casi queste due soluzioni vengono utilizzate in
contemporanea creando così dei server implementati come delle sottoreti.
Come già sottolineato, pensare ad un'unica macchina (che può essere anche un web
switch, piuttosto che un content provider) collegata a diversi server secondari è una
soluzione che non va più bene: se un numero grande di client si concentrano
contemporaneamente su una piccola area geografica, il server principale è troppo
carico di lavoro, non riuscendo più a gestire e a smistare le diverse richieste. Un
ulteriore problema di una simile architettura è, che le risorse vengono allocate in
maniera iniqua: con un’architettura client/server l’informazione è, infatti, concentrata
soltanto su poche macchine accessibili da tutti.
1.2 IL MODELLO PEER-TO-PEER
Per cercare una soluzione a tutti questi problemi, che stanno diventando, col passare
del tempo, sempre più seri, si può tentare di gestire in maniera diversa la struttura di
una rete. Il punto di partenza di questa nuova riflessione sta nel fatto che le risorse
impiegate in processo di scambio di dati non sono messe a disposizione solo dai
server, ma anche dagli stessi client; non dobbiamo, infatti, dimenticare, che il client
è, di fatto, una macchina con una propria memoria, una propria velocità di calcolo e
delle proprie risorse. Se il client potesse mettere a disposizione queste proprie
risorse, l’efficienza dello scambio di dati e della gestione dei servizi in generale,
sarebbe decisamente migliore.
Queste riflessioni, nel loro complesso, stanno di fatto alla base di un nuovo modello
di strutturazione della rete che può essere alternativo (o anche complementare) al
client/server: il paradigma Peer-to-Peer (P2P).
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
10
Secondo questo modello la rete è composta da un insieme di nodi (i peer) connessi
tra loro; ciascun peer si comporta contemporaneamente sia da client sia da server
mettendo a disposizione delle risorse e fruendo di altre messe a disposizione dagli
altri nodi. In questo modo l’informazione distribuita sulla rete non è più concentrata
su piccole aree geografiche, ma è estesa a tutta la rete stessa; in tal modo non c’è
rischio che una macchina subisca un carico di lavoro eccessivo. Non esistono nelle
reti P2P i cosiddetti “point of failure”
1
. La comunicazione e lo scambio di dati,
inoltre, è più fluido perché ciascun peer può utilizzare la banda del nodo con cui sta
comunicando.
Un ulteriore vantaggio del P2P sta nel fatto che se si spegne un nodo la rete continua
a vivere, a differenza di quanto accade nel modello client/server; in quest’ultimo,
infatti, se spegniamo il server, perdiamo tutti i servizi e le risorse che questo metteva
a disposizione, dando luogo a problemi per tutti i client connessi ad esso.
I servizi che si possono ottenere da una rete P2P sono molteplici: file sharing,
videoconferenze e, soprattutto, la condivisione delle risorse si calcolo; grazie a
questa topologia, infatti, un peer che deve svolgere complesse operazioni di calcolo o
di elaborazione di dati, può delegare questo compito ad altri peer. Ovviamente, per
garantire ciò, sono necessari diversi algoritmi di ricerca o di flooding: un peer,
infatti, deve poter conoscere gli altri nodi nella rete, deve poter trovare inoltrare le
query che riceve ad altri peer, qualora non possedesse la risorsa richiesta.
Si può immaginare una rete peer-to-peer come un grafo bidirezionale i cui vertici
corrispondono ai nodi e gli archi alle connessioni aperte tra due nodi; i messaggi
possono essere trasmessi in entrambe le direzioni. Dati due nodi A e B si definisce la
distanza tra A e B come il numero di hop necessari ad un messaggio per arrivare da A
a B (o viceversa).
1
In realtà l’assenza di “points of failure” è soltanto teorica, poichè esistono architetture come quella
descritta nel paragrafo 1.3.1 che soffrono di questo problema.
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
11
1.3 LE TOPOLOGIE DI RETI PEER-TO-PEER
La struttura di una rete P2P può essere di tre tipi[2]:
• Centralizzata
• Decentralizzata
• Ibrida
1.3.1 Struttura centralizzata
In una struttura centralizzata è presente un server principale che contiene, al suo
interno, una tabella che conserva le associazioni nome risorsa – indirizzo della
macchina. Nel momento in cui si richiede una risorsa, viene inviata la richiesta al
server; quest’ultimo scandisce la propria tabella e rintraccia gli indirizzi di tutti i peer
che la possiedono. La risposta da inviare al peer sarà l’insieme di tutti questi
indirizzi. A questo punto il peer deve effettuare la scelta del nodo a cui richiedere la
risorsa e questo può essere fatta in diversi modi:
• Si può scegliere il nodo che in quell’istante è soggetto ad un minor carico di
lavoro; questo, tuttavia, preclude che il server debba anche mandare le
informazioni sulle capacità di ciascun peer (l’operazione può anche essere
molto costosa e non sempre è affidabile)
• Si può effettuare una scelta casuale
• Si può scegliere il nodo più vicino
Una volta inviata la richiesta, il peer fruisce del servizio. Un’architettura di questo
tipo, tuttavia, si avvicina come topologia ad un modello client/server (a causa della
presenza del server principale); questo comporta la presenza di alcuni problemi tipici
delle strutture di questo tipo, come ad esempio le congestioni del server (causate, di
nuovo, da un numero massiccio di richieste contemporaneamente). Un esempio
importante di questo tipo di architettura è stato Napster, chiuso, tuttavia, nel 2001.
1.3.2 Struttura decentralizzata
In una rete P2P decentralizzata non è presente nessun server centrale e la ricerca di
risorse è affidata agli stessi peer. Quando un nodo chiede una risorsa, la sua richiesta
viene inviata, in broadcast, a tutti i peer con cui è connesso; ciascuno di questi peer
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
12
può contenere o meno la risorsa. In caso negativo questi reinstradano la query
ricevuta, nuovamente in broadcast, a tutti i peer con cui sono connessi (flooding).
Ovviamente maggiore è il numero di connessioni in un peer, minore sarà il numero
di hop effettuati (il numero, cioè, dei reinstradamenti della query), prima di reperire
la risorsa. Bisogna, inoltre, prestare attenzione a non occupare, con una sola richiesta,
tutta la rete: se, infatti, nessun peer può soddisfare la richiesta, la query teoricamente
viene spedita all’infinito verso tutti i nodi. Per risolvere questo problema si può
prima di tutto limitare il numero degli host a cui inoltrare le richieste ricevute e, in
secondo luogo, impostare un parametro nella query, il time-to-live (TTL), il quale
viene decrementato ad ogni hop; quando raggiunge il valore di zero, la query
smetterà di essere inoltrata. Un ulteriore raffinamento da compiere potrebbe essere
quello di impedire che un peer riceva più di una volta la stessa richiesta. I problemi
maggiori di una struttura decentralizzata stanno nell’inserimento e nella rimozione di
un nodo: ciascun peer, infatti, deve contenere una lista dei peer a cui è connesso e
ogni volta che un nodo “nasce” o “muore” diverse tabelle di questo tipo devono
essere aggiornate. Questo problema può essere limitato mettendo un server centrale
che contenga gli indirizzi IP di tutti i peer attivi; nel momento in cui un peer cerca di
inoltrare una query ad una macchina non più presente, questo scaricherà la nuova
lista di peer attivi nella rete e la salverà in una propria cache. Questa è la soluzione
adottata da Gnutella[3], un esempio di rete P2P. Un ultimo problema delle strutture
decentralizzate sta nel fatto che spesso nelle reti di questo tipo ci sono macchine che
utilizzano una larghezza di banda ristretta, diventando, talvolta, inutili per la ricerca
di risorse (i cosiddetti “buchi neri”).
1.3.3 Struttura ibrida
Le architetture ibride sono topologie di reti nelle quali non si ha un server centrale,
ma non si può nemmeno affermare che i peer stanno tutti allo stesso livello. Esistono,
infatti, strutture gerarchiche nelle quali ci sono dei nodi (i super-nodi o i rendez-vous
a seconda del protocollo utilizzato) che si preoccupano soltanto di fare flooding di
query, e altri che contengono e mettono a disposizione le risorse. Ciascun super-nodo
è connesso a diversi peer e ad altri super–nodi e può contenere una tabella con le
associazioni nome risorsa – indirizzo della macchina, dove la macchina è un peer
collegato ad esso. Nel momento in cui un peer effettua una richiesta, questa viene
___________________Capitolo 1 - Dal paradigma Client/Server al Peer-to-Peer
13
inoltrata dal super-nodo a tutti i super-nodi conosciuti; chi avrà nella propria tabella
un’occorrenza della risorsa cercata, risponderà al peer con l’indirizzo della machina
che possiede la risorsa. A questo punto sarà il peer ad occuparsi della comunicazione
con il possessore della risorsa e a fruirne. Un esempio di un’architettura di questo
tipo è Kazaa[4] che non è altro che la struttura adottata da Gnutella, ma con una
gerarchia di nodi e super-nodi.
1.4 IL PROBLEMA DELLA RICERCA
Negli ultimi anni il successo ottenuto dalle reti P2P è stato via via sempre più
crescente, portando alla necessità di cercare di risolvere nuove problematiche.
Il volume di dati condivisi ha raggiunto dimensioni enormi (nell’ordine dei
petabytes) e tali risultati sono stati possibili proprio per aver utilizzato una
condivisione di risorse non realizzabile con il paradigma C/S. Un problema, tuttavia,
che si presenta in queste condizioni, è quello della ricerca di un file: in una
moltitudine così immensa di informazione, può risultare difficile, se non impossibile,
trovare uno specifico dato, soprattutto se si considera il fatto che non è presente
nessuna struttura centralizzata a fornire un servizio di ricerca. Un ulteriore problema
che si presenta è quello del processamento delle query: se un nodo contiene un
numero elevato di memoria condivisa e deve rispondere a diverse richieste
contemporaneamente, può metterci diverso tempo prima di stabilire se possiede o
meno la risorsa e di inoltrare, eventualmente, la richiesta ai vicini.
Vediamo come funziona la gestione di una query: quando un peer fa partire una
richiesta, il suo nodo diventa la sorgente della query; ovviamente una sorgente S può
mandare una stessa richiesta a diversi nodi vicini, contemporaneamente (il numero di
vicini a cui inviare la query dipende dalle politiche di routing della sorgente ed è
molto importante ai fini della ricerca). Quando un nodo riceve tale richiesta,
controlla se ha a disposizione o meno la risorsa specificata nella query; in caso
affermativo invierà tale risorsa alla sorgente della query. È bene sottolineare che
esistono alcuni sistemi P2P, come Gnutella, in cui la query non possiede l’indirizzo
della sorgente, complicando l’operazione della risposta. Questo problema viene
risolto facendo memorizzare, alla query di richiesta, il percorso compiuto per arrivare
dalla sorgente alla destinazione e, durante la risposta, facendo percorrere lo stesso
percorso nel verso opposto. Nel caso in cui la risorsa non sia disponibile nel nodo