Lo strato applicativo di Internet
Mentre nel capitolo precedente ci siamo tendenzialmente limitati a descrivere ciò che è possibile fare servendoci dei soli strumenti di base del WWW, ossia dell'indirizzamento (URI), del trasporto (HTTP) e della formattazione (HTML) delle informazioni, vogliamo in questo capitolo approfondire gli aspetti relativi alla possibilità di utilizzare il WWW classico per accedere, oltre che a semplici oggetti, anche a servizi di elaborazione, ed a come questi possano arrivare a combinarsi per realizzare veri e propri sistemi distribuiti.
Siamo ora in grado di approfondire lo studio di ciò che avviene dal lato server dell'HTTP, e di mostrare come la tecnologia web si sia man mano arricchita di funzionalità in grado di offrire servizi sempre più evoluti, mediante una interfaccia di presentazione sempre più universale.
Il CGI è una modalità di eseguire un programma (chiamato anch'esso CGI) residente presso un server web, il cui nome è presente nel path della URI oggetto di una richiesta HTTP, e di visualizzare come risposta una pagina web, il cui contenuto è prodotto dal programma stesso. Pertanto, la pagina visualizzata non esiste in forma fisica, ma è stata generata dinamicamente per l'occasione.
Il meccanismo di comunicazione tra utente, server web, e programma CGI, sommariamente descritto dalla figura precedente, tratta da questo testo on-line, merita qualche commento di approfondimento:
Il diagramma temporale che segue, tenta di rappresentare in forma grafica i passaggi ora esposti:
La definizione formale di questa metodologia risale al 1993, e fu definita nell'ambito delle discussioni svolte tramite la mailing list a cui erano iscritti gli sviluppatori web di allora, e pubblicata (mirror) presso il sito dell'NCSA, che a quei tempi offriva la prima implementazione (a cura di Rob McCool) di server web universalmente diffusa. Da allora, solo nel 2004 si è arrivati ad una formalizzazione ufficiale della interfaccia CGI/1.1, con la RFC 3875.
Il termine Common Gateway Interface,
oltre a riferirsi alla interfaccia tra server web ed applicazione,
esprime bene il concetto che questa applicazione-CGI può costituire una
sorta di porta (comune) verso altri universi:
uno dei principali utilizzi della tecnica è infatti quello di
permettere l'interrogazione di DataBase,
formattando i risultati in modo facilmente leggibile, e idoneo a
generare ulteriori interrogazioni al database, in modo semplice.
La realizzazione di programmi CGI scritti utilizzando linguaggi di scripting, ed abbinati ai database, ha reso possibile lo sviluppo dei Content Managment Systems.
Come anticipato, in questo caso il server web comunica al CGI i parametri che gli giungono da parte del client mediante l'uso di variabili di ambiente, che il CGI può leggere, ed usare per i suoi scopi. Un esempio è fornito nelle esercitazioni, dove è proposto lo script perl che viene invocato dalla form del capitolo precedente, e che ci mostra le variabili di ambiente ricevute a seguito dell'invocazione del pulsante di inoltro. Un elenco di variabili di ambiente a cui il server Web può assegnare un valore, e di quali informazioni sono veicolate in tal modo, è riportato nella RFC 3875.
In particolare, la variabile QUERY_STRING riporta la parte di URI successiva al simbolo ?, ossia la sequenza di coppie variabile=valore associate ai campi della form, separate dal simbolo &. Inoltre, la variabile REQUEST_METHOD riporta il metodo indicato nell'attributo method dell'elemento HTML <form>, che può assumere i valori GET o POST.
Mentre nel caso precedente (metodo GET)
i campi della form sono trasmessi come parte
della URI, con il metodo POST
questi sono
invece passati nel body della richiesta
HTTP, ed il server web a sua volta, li passa al CGI mediante il canale
di standard input.
Per fare un esempio, replichiamo la form precedente, utilizzando questa volta il metodo POST, ed invocando una diversa action, modificando quindi rispetto a quel caso, solo la prima linea, che diventa
<form method="post" action="http://127.0.0.1/labint/secondocgi.cgi"> |
dando così luogo al modulo che segue
Come possiamo apprezzare dalla pagina di risposta inviata dallo script invocato nella action, i parametri della chiamata questa volta sono stati inviati nel body del messaggio di richiesta HTTP.
Se nel campo email delle form precedenti, immettiamo parole separate da spazi, o contenenti lettere accentate, possiamo osservare come questi caratteri siano sostituiti, dal lato del CGI che li riceve, dal carattere + (per lo spazio) oppure da codifiche esadecimali. Questa trasformazione (nota anche come percent encoding) è quella di default, che può essere resa esplicita aggiungendo nel tag dell'elemento form, un attributo enctype con valore application/x-www-form-urlencoded.
Osserviamo ora che, sebbene il body possa essere di lunghezza qualsiasi, e si possa pensare di aver risolto così il problema di avere strighe di opzioni troppo lunghe, restano ancora due questioni:
<form method="post"
action="http://127.0.0.1/labint/terzocgi.cgi"> <input name="ok" value="ordina in segreto" type="submit"> <input name="ordine" value="amatriciana" type="hidden"> <input name="email" value="alef@infocom.uniroma1.it" type="hidden"> </form> |
<form enctype="multipart/form-data"
method="post" action="http://127.0.0.1/labint/secondocgi.cgi"> <input name="ordine" value="pastiera" type="hidden"> <input name="email" value="alef@infocom.uniroma1.it" type="hidden"> Quale file vuoi inviare? <input name="file allegato" type="file"><br> <input name="ok" value="ordina multipart" type="submit"> </form> |
Il termine script, tradotto in italiano come linguaggio interpretato, tra origine dall'uso del termine script nel campo delle arti drammatiche, dove con questo termine, si intende il copione che deve poi essere (appunto) interpretato da un attore. La programmazione degli script, nasce dall'esigenza di abbreviare il ciclo di sviluppo del codice, che ne prevede l'edit, la compilazione, il linkaggio, il debug, e l'esecuzione. Omettendo la fase di compilazione e link, si può verificare immediatamente l'effetto di piccole modifiche apportate, integrando il debug con le fasi di edit e di esecuzione. L'uso dei linguaggi di scripting si è quindi affermato per lo sviluppo dei programmi CGI, che anche se possono essere scritti in qualunque linguaggio, compreso c e c++, beneficiano della adattabilità intrinseca derivante dall'uso degli script. Nel corso della storia del web, si sono accumulate notevoli quantità di librerie di codice già pronto per l'uso, rendendo possibile il rapido sviluppo sia di applicazioni CGI per compiti specifici, che di applicazioni più generali che ricadono nella categoria dei CMS, dei Blog e dei Wiki.
Acronimo di Practical Extraction and Report Language (anche se in effetti, è un retronimo), perl nasce nel 1987 su iniziativa di Larry Wall, ed oggi dispone di una miriade di moduli già pronti per l'uso. In particolare, la sezione dedicata alle applicazioni web ed allo sviluppo di applicazioni è particolamente nutrita e pronta a soddisfare quasi ogni esigenza. Allo stesso tempo, esiste un modulo opzionale di Apache, che incorpora in Apache stesso il compilatore-interprete perl, offrendo prestazioni superiori. Anche se Perl è in origine nato come un linguaggio interpretato, attualmente l'esecuzione di un programma Perl prevede una prima fase in cui viene prodotto un bytecode ed un grafo di flusso, che sono poi eseguiti da una virtual machine in stile java.
La sintassi di Perl può ricordare un pò quella del c, e subisce l'influenza di molti altri linguaggi, anche orientati agli oggetti. Può invocare in modo diretto la valutazione di espressioni regolari. Effettua automaticamente la conversione di tipo delle variabili (es indirizzo/intero/stringa/) in funzione del contesto in cui vengono usate, ed usa il primo carattere delle stesse per identificarne la dimensionalità: ad esempio, @var rappresenta un array di nome var, mentre %var individua un array associativo.
Nasce nel 1994 come un insieme di CGI scritti in c, per rimpiazzare degli script perl usati dall'autore per mantenere le proprie pagine personali. Da allora ha ricevuto i contributi di parecchi sviluppatori, ed ora è un potente linguaggio di alto livello, con una sintassi che ricorda il c, un buon supporto del paradigma di programmazione ad oggetti, e l'accesso diretto ai parametri ricevuti mediante l'uso dei controlli delle form. Il solo nucleo di base prevede più di 3000 funzioni, ed offre il supporto alla interrogazione di parecchi diversi tipi di DataBase, così come svariati wrapper verso altri linguaggi/applicazioni/protocolli/tecnologie, che sono raccolti in un deposito denominato PEAR. E' alla base dello sviluppo di diversi applicativi wiki o cms, come MediaWiki, su cui è basata Wikipedia. L'uso congiunto di Linux, Apache, MySQL e PHP (e/o Perl e/o Python), viene denominato server LAMP, e rappresenta la configurazione preferita per lo sviluppo di siti dinamici, costituendo un stack applicativo tutto Open Source, molto competitivo rispetto alle soluzioni commerciali.
Nasce alla fine degli anni 80, e quindi, a differenza di PHP, non per risolvere problematiche legate ai CGI. E' particolarmente sensibile alle esigenze di leggibilità del codice, consentendo di affrontare serenamente anche la stesura di progetti complessi. Permette di adottare altrettanto bene paradigmi di programmazione orientata agli oggetti, oppure strutturata, o funzionale.
Sebbene Java sia nato allo scopo di distribuire codice eseguibile su qualunque tipo di macchina client, in questo particolare caso è invece usato per realizzare codice da eseguire dal lato server, al punto che il termine originario applet si trasforma, in questo caso, in servlet. Le particolarità di Java hanno fatto si che, anziché adattarsi ad un server web preesistente, si sia preferito lo sviluppo di server scritti apposta, e denominati Servlet container.
Le Active Server Pages sono l'approccio di Microsoft allo sviluppo di applicazioni server-side, scritte in VB.NET, C# e J#, ed ha subito una graduale evoluzione fino alla attuale versione ASP.NET, che è integrata con la architettura .NET, nata a sua volta, in risposta a Java.
Una delle principali applicazioni dell'approccio-CGI è stato l'accesso ai dati mantenuti in un DBMS, ed alla presentazione dei risultati in pagine web scritte in modo da facilitare ulteriori richieste correlate alla prima. Mentre per DataBase si può intendere una semplice organizzazione indicizzata dei dati, tale da permetterne un accesso velocizzato rispetto alla ricerca sequenziale, un DBMS è una applicazione server che permette l'accesso, la modifica e la manutenzione degli indici dei dati, da parte di più applicazioni client che operano in modo concorrente. In buona sostanza, le applicazioni che fanno uso di un DBMS di fatto sostituiscono alle proprie variabili e strutture dati, quelle presenti nel database che viene usato, che rappresenta in tal senso una sorta di memoria a lungo termine dell'applicazione.
Lo Structured Query Language è un linguaggio definito appositamente per realizzare delle interrogazioni ai database relazionali (RDBMS), ed affonda le sue radici a cavallo tra gli anni 70 ed 80. I database relazionali organizzano i dati in tabelle, le cui righe rappresentano dei record che mettono in relazione tra loro i contenuti che compaiono nelle colonne, ed alcune colonne possono svolgere il ruolo di mettere in relazione tra loro i record presenti in tabelle differenti.
Nonostante sia ANSI che ISO abbiano partecipato ad un processo di standardizzazione di SQL, gli sviluppatori di DBMS non vi hanno mai aderito pienamente, cosicchè un programma CGI scritto in uno dei linguaggi fin qui discussi, deve in genere usare una diversa libreria di funzioni per ogni diverso RDBMS che intende usare. Ma nonostante ciò, le operazioni di base che è possibile eseguire hanno gli stessi nomi nei diversi casi, come ad esempio Select, Insert, Update, Delete. Per un confronto tra diversi RDBMS, si veda la tabella presso Wikipedia.
Anche Ruby è un linguaggio di scripting, di tipo interpretato, nato nel 1993 per opera di Yukihiro Matsumoto, e che segue un paradigma ad oggetti. Viene citato ora, anzichè alla sezione precedente, perchè il motivo della sua popolarità è legato allo sviluppo (2004) di un ambiente noto come Ruby on Rails, che consente lo sviluppo rapido di applicazioni Web basate su RDBMS. La rapidità si basa su di una filosofia di progetto che tende ad evitare la ripetizione di definizioni altrimenti deducibili, e la necessità di specificare solo ciò che si discosta delle convenzioni. Questo tipo di approccio è stato definito come scaffholding (impalcatura, o ponteggio) e consiste nell'usare strutture dati e relativi nomi di variabile direttamente ereditati a partire dalla struttura delle tabelle e relativa nomenclatura già definita nel database che si intende usare, senza doverla definire nuovamente. In definitiva, questo paradigma si traduce nella generazione automatica della interfaccia di programmazione, a partire dalla struttura del database soggiacente, e quindi nel suo utilizzo da parte della applicazione che si sta realizzando.
Abbiamo affermato fin dall'inizio che un server HTTP tratta tutte le richieste come indipendenti le une dalle altre, evitando accuratamente di memorizzare informazioni di stato, relative alla evoluzione della sessione che si sta svolgendo con un client che invii richieste ripetute. In tal modo, si permette l'attuazione di tecniche di bilanciamento del carico, come ad esempio nel caso in cui la richiesta HTTP sia inoltrata ad uno tra diversi server in batteria, che condividono gli stessi documenti da inviare, ma non l'informazione di stato relativa al client.
Per ovviare a questa situazione, e permettere ad esempio lo sviluppo di servizi di commercio elettronico, dove chi naviga mette nel carrello diversi acquisti, oppure per permettere la personalizzazione dell'aspetto di un sito, discutiamo di due soluzioni possibili, entrambe fondate sullo stratagemma di delegare al browser il compito di ricordare la storia della navigazione presso uno stesso sito.
Anche se letteralmente questo termine significa biscottino, ha il senso di un gettone, del tutto simile alla contromarca che ci viene consegnata dall'inserviente di un guardaroba, e che riconsegnamo per ri-ottenere il nostro cappotto. In origine, questo termine è stato usato nel contesto della autenticazione di utenti di sessioni video remote su macchine Unix. L'applicazione di questo concetto alla navigazione web è stato introdotto da un impiegato di Netscape, e poi è stato ri-definito formalmente nella RFC 2965. Il funzionamento si basa sulla presenza, nella risposta inviata da un server web, di una intestazione Set-Cookie, che specifica una stringa che viene memorizzata presso lo userAgent, e che codifica una serie di attributi, come
Successivamente, quando lo UserAgent effettua una nuova richiesta la cui URI corrisponde al dominio ed al percorso citati nel cookie, questo viene accluso alla richiesta, associandolo alla intestazione Cookie. Il valore del cookie rappresenta una codifica (eventualmente ottenuta con metodi crittografici) dello stato della sessione all'atto della richiesta che ha generato la risposta che ha prodotto la prima istanza del cookie, ed allegando tale codice anche nelle successive richieste, si ottiene che
Qualcuno si può chiedere: ma se l'HTTP è stateless, perché ora un server HTTP dovrebbe diventare stateful? In effetti, benchè nulla vieti di utilizzare un server web sviluppato apposta per saper gestire da sè i cookie, è perfettamente possibile utilizzare un server web tradizionale, che non tratta in nessun modo particolare l'header con cui il browser restituisce il valore del cookie memorizzato, ma se la URI richiesta individua un CGI, allora il valore del cookie viene passato a quest'ultimo con il meccanismo delle variabili di ambiente; a sua volta, il CGI provvederà a definire un nuovo valore per il cookie, da re-inviare al browser. Pertanto, pur rimanendo l'HTTP stateless, il comportamento stateful è ottenuto mediante l'operato dello strato applicativo incarnato dal CGI. I linguaggi per la scrittura di CGI prevedono apposite funzioni per la gestione dei cookie, come ad esempio CGI::Cookie di Perl.
I propositi di questa tecnica sono molteplici: oltre al caso già citato del commercio elettronico, è ad esempio possibile
Nonostante una serie di controindicazioni all'uso dei cookie, l'attuale navigazione web non sembra poterne fare a meno.
Una delle più valide alternative ai cookie, applicabile nel caso in cui le pagine di risposta siano sempre generate da un CGI, è quella di inserire nelle stesse, dei moduli (form) contenenti dei controlli nascosti, i cui valori rappresentano le informazioni di stato relative alla navigazione svolta fino al momento della generazione della pagina contenente i controlli nascosti. Inoltre, nel caso in cui la navigazione prosegua utilizzando il metodo POST, questi valori non compaiono nella URI, ottenendo prestazioni del tutto equivalenti a quelle dei cookie, al prezzo di ri-generare ogni volta la pagina di risposta.
La differenza sostanziale tra l'uso dei cookie e quello delle variabili nascoste, è che mentre i primi sopravvivono fino alla loro data di scadenza, permettendo di conservare l'informazione di stato anche tra visite distanti nel tempo, le variabili nascoste possono invece accumulare informazioni di stato, solo nel caso in cui si continui a visitare sempre lo stesso sito, in modo che le variabili presenti nella nuova pagina, dipendano dalle scelte operate alla pagina precedente.
Si tratta della possibilità di ospitare su di un medesimo server web, più siti corrispondenti ognuno ad un diverso dominio, ed un diverso intestatario. Questo può essere ottenuto in due modi. Il primo, consiste nel dotare il computer che ospita il sito web di più indirizzi IP (possibilità indicata con il termine multihoming), ognuno corrispondente ad un diverso dominio, e consente di discriminare le richieste in base all'IP di destinazione del socket. Il secondo metodo consiste nell'utilizzo di un unico IP, su cui il DNS risolve tutti i domini associati ai siti (che sono quindi alias di un unico CNAME), e nel differenziare le richieste in base alla intestazione Host presente nella richiesta, che appunto riferisce a riguardo del dominio che compare nella URI di richiesta. Un esempio di configurazione di server virtuale è trattato nelle esercitazioni nel contesto della attivazione di un sito sicuro.
I file di log del server web contengono molte informazioni relative alle pagine che sono richieste, all'orario, al codice di risposta, allo user agent, al referente della pagina visitata, e sono tipicamente esaminati una volta al giorno, da parte di programmi appositi, allo scopo di generare dei report (accessibili via web) che caratterizzano le modalità di fruizione dei contenuti del sito. L'interesse per questi report può essere di semplice curiosità, o rivestire un fine più concreto, come il monitoraggio dell'esito di una campagna di marketing. Due di queste applicazioni open source sono Webalizer e Awstats, il primo scritto in c, ed il secondo in perl.
Una diversa tecnica di analisi si basa sul page tagging, e consiste nell'inserire nelle pagine un riferimento ad un oggetto, oppure del codice javascript, tale da produrre un accesso ad un server remoto (tipicamente, di terza parte) che memorizzarà la URI che lo ha referenziato, e che altrettanto tipicamente, consegnerà al visitatore un cookie per riconoscerlo le volte successive. In questo blog troviamo un confronto di diverse metodologie di analisi. Un servizio molto diffuso, forse anche perché gratuito, è quello offerto da Google Analytics (video).
La filosofia del CMS nasce al difuori del web, come una metodologia di lavoro collaborativo basato sullo scambio e sulla redazione partecipata di documenti. Un approccio simile si è quindi naturalmente fuso con le possibilità offerte dal web, non ultima quella del telelavoro; inoltre, mettere un CMS su web significa anche rendere i propri risultati editoriali direttamente disponibili alla fruizione del grande pubblico. Si può pensare che il CMS sia una delle pietre angolari di ciò che viene denominato come Web 2.0 (video).
Un CMS web è tipicamente realizzato come una applicazione CGI abbastanza articolata, che consente l'editing dei contenuti senza richiedere la conoscenza di HTML, CSS, SQL, e dei linguaggi di scripting, la cui presenza viene nascosta da una funzione di interfaccia utente realizzata sempre via web. L'aspetto delle pagine erogate da un CMS-web risulta in genere omogeneo, mentre i contenuti sono coerenti anche se presentati sotto viste differenti, questo grazie alla adozione di fogli di stile in comune alle diverse sezioni, ed alla generazione dinamica delle diverse pagine a partire dalle informazioni memorizzate in unico database. Per contro, la manutenzione di un CMS-web necessita la definizione di ruoli editoriali precisi, attribuendo ai singoli individui la gestione di singoli aspetti e/o componenti, nonché dei ruoli di supervisione ed editoriali rispetto ai contenuti che possono anche essere incorporati a partire da fonti esterne. Nella sezione specifica dei riferimenti, possiamo trovare i link ai principali CMS esistenti, ed ai siti che li mettono a confronto. Tra questi, i più diffusi/famosi sono joomla, plone, drupal, wordpress (lista completa).
A partire dal concetto generale di CMS e dai principi su cui si fonda, nel tempo si sono sviluppate applicazioni particolari della tecnologia, orientate alla gestione di problemi specifici, e che offrono supporto ad esigenze particolari. Vediamone alcune.
Il termine Blog è una contrazione di web log, a sua volta parafrasi di travel log, o libro di bordo. Infatti, un blog è un CMS, in cui un singolo individuo espone pensieri, riflessioni, punti di vista e sensazioni, accludendo al sito contenuti di vario genere, link ad altri siti, e permettendo in genere ai visitatori di arricchire l'esperienza di interazione collettiva mediante l'inserimento di commenti individuali, trasformando ogni editoriale immesso nello spunto di discussione per un forum telematico, con il risultato di misurare il polso dei frequentatori del sito.
Chi voglia dar vita al proprio blog, può rivolgersi a fornitori di questo servizio specifico, che ospitano siti-blog gratuitamente, come ad es. Blogger (poi acquisito da Google e rinominato blogspot), o Wordpress, od uno di questi; oppure installare presso un provider che offre hosting, o su di una propria macchina in rete, un applicativo apposito, come ad esempio Wordpress, di cui abbiamo anche un video.
Il
termine è una parola polinesiana che significa veloce,
e chi lo usò
per la prima volta per descrivere una modalità di editing di pagine
web, attuata mediante il web stesso, lo fece in seguito al fascino che
ebbe su di lui l'autobus dell'areoporto di Honolulu, che appunto per la
sua velocità, era chiamato wiki-wiki.
Sebbene un wiki potrebbe esser fatto ricadere sotto la categoria più generale dei CMS, possiede alcune caratteristiche particolari, che lo differenziano in modo unico.
A queste caratteristiche se ne aggiungono altre, come
Al di là dell'approccio collaborativo, le caratteristiche esposte sono ben utili anche nel caso in cui il sito sia mantenuto da una persona sola, oppure da un gruppo di persone che sono coinvolte in un progetto comune, come ad esempio lo sviluppo di un software open source (es con trac), per il quale non valga la pena di progettare un nuovo sito ad-hoc.
Chi voglia sviluppare il proprio wiki può infine rivolgersi ad una wiki farm (es: wikia) che offre ospitalità, oppure installare in proprio uno dei motori esistenti.
Si tratta in questo caso di siti orientati alla compravendita di beni, o che comunque prevedono transazioni finanziarie, come ad es. nel caso dell'home-banking. In linea di principio si possono far ricadere questi casi in quello del CMS, a cui si aggiunge l'utilizzo di connessioni sicure, al fine di garantire il navigante relativamente all'identità del soggetto che eroga il servizio. Nel caso del commercio elettronico vengono tipicamente utilizzati dei cookies allo scopo di autenticare il navigante, e mantenere per tutta la durata delle sessione l'informazione di stato rappresentata dalla metafora dal carrello.
Al momento del pagamento però tipicamente subentra un soggetto diverso dal mercante, ed il controllo della transazione passa alla banca on-line che gestisce il meccanismo di pagamento elettronico. Nel caso dell'home-banking infine, a fronte dei potenziali rischi legati al pieno controllo telematico di un intero conto corrente, spesso i meccanismi di autenticazione basati su di una tradizionale password non sono considerati sufficientemente sicuri, e viene allora richiesta una seconda password usa e getta, pre-distribuita direttamente al cliente, od inviatagli mediante un SMS contemporaneo.
In questa incarnazione di CMS, un aspetto particolarmente rilevante è la progettazione del DataBase che memorizza le diverse personalizzazioni e condivisioni di ogni appartenente alla comunità, e le relazioni che intercorrono tra essi. Si fa anche qui ampio uso di cookies, e di soluzioni basate su Ajax e su Flash, così come sull'uso di CDN, in modo da allegerire il server del carico ad esso altrimenti riservato.
Attualmente (nella versione 2.0) RSS è l'acronimo di Really Simple Syndacation, anche se in tempi non troppo lontani, ha avuto anche il significato di Rich Site Summary (ver 0.91) e RDF Site Summary (ver 0.9 ed 1.0). Consiste in un dialetto dell'XML, orientato alla descrizione dei contenuti di un sito web, e da questo punto di vista deve molto alle sue origini, legate alle definizione di metadata e RDF. Un esempio di RSS 2.0 è fornito da wikipedia, ed è riportato appresso:
<?xml version="1.0"?> <rss version="2.0"> <channel> <title>Liftoff News</title> <link>http://liftoff.msfc.nasa.gov/</link> <description>Liftoff to Space Exploration.</description> <language>en-us</language> <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate> <lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate> <docs>http://blogs.law.harvard.edu/tech/rss</docs> <generator>Weblog Editor 2.0</generator> <managingEditor>editor@example.com</managingEditor> <webMaster>webmaster@example.com</webMaster> <item> <title>Star City</title> <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link> <description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's Star City.</description> <pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate> <guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid> </item> <item> <title>Space Exploration</title> <link>http://liftoff.msfc.nasa.gov/</link> <description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a partial eclipse of the Sun on Saturday, May 31st.</description> <pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate> <guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid> </item> <item> <title>The Engine That Does More</title> <link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link> <description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly. The proposed VASIMR engine would do that.</description> <pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate> <guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid> </item> </channel> </rss> |
Come si vede, l'XML di un RSS è strutturato in modo da racchiudere, nel contesto di un <channel>, caratterizzato da un insieme di elementi validi per tutti i diversi contenuti di un canale, le descrizioni associate a diversi <item>, fornendo per ciascuno di essi, un'altra serie di elementi che permettono sia di accedere alla pagina web dove è effettivamente esposto l'argomento, sia di descrivere il contenuto in forma sintetica, in modo da permettere a chi legge, di valutare il suo interesse.
I documenti XML che descrivono un feed
RSS sono prelevabili (con Mime-Type application/rss+xml)
da siti
web (es Repubblica,
Punto
Informatico) che espongono il logo mostrato a lato, da parte di
programmi detti feed
reader,
che consentono di tenere sott'occhio (prelevandoli dalle rispettive
fonti) in modo uniforme i feed RSS di diversa provenienza (video).
La
funzione di feed reader viene ad oggi svolta anche da client email e
browsers, e questi ultimi riescono ad accorgersi
autonomamente
della presenza nelle pagine ricevute della URI del feed RSS, nel qual
caso ne evidenziano il logo all'interno della propria barra degli
indirizzi.
Un approccio simile (ma diverso) è quello degli aggregatori, che pure raccolgono i feed RSS provenienti da fonti diverse, ma li compongono a formare una nuova pagina web, i cui contenuti hanno origine a partire dai diversi feed a cui l'aggregatore è iscritto. La pagina web contenente l'aggregatore, può essere personalizzata in associazione all'identità di un utente autenticato del sito web, come ad esempio accade con Bloglines, MyYahoo, YourLiveWire, Google Reader, ovvero quelli riportati da newsonfeed.
Un diverso formato di feed RSS è denominato Atom, che gode del riconoscimento ufficiale della RFC 4287 di IETF, e che nasce a seguito dell'insoddisfazione relativa ai diversi formati incompatibili esistenti per RSS. Una ulteriore RFC 5023 definisce poi l'Atom Publishing Protocol, basato su HTTP, che stabilisce le modalità di pubblicazione e recupero degli oggetti Atom. D'altra parte, la formalizzazione di meccanismi di descrizione sommaria dei contenuti accessibili via web, è altrettanto utile ai fini della indicizzazione di siti strutturati da parte di motori di ricerca: a tale scopo, si è verificata la convergenza su di un insieme di tag XML definiti per questo scopo, ed identificati come sitemap.
Questo termine nasce dalla contrazione (o dalla sinergia?) tra l'iPod di Apple, ed il broadcasting, anche se ha ben poco a che vedere con entrambi. Si tratta della ricezione in differita di contenuti multimediali (audio, video) preregistrati, ed annunciati per mezzo di feed RSS o Atom. Chi si iscrive al feed, lascia che il suo podcast-reader (come iTunes) verifichi se ci sono novità, ed in tal caso le scarichi, permettendo di ascoltare/vedere i nuovi contenuti in un secondo tempo.
In RSS 2.0 il podcast è abilitato dalla definizione dell'elemento <enclosure>, che consente di specificare la URI del contenuto multimediale, la sua dimensione in byte, ed il MIME-Type associato al file. In Atom, viene usato allo stesso scopo il termine enclosure, come possibile valore dell'attributo rel (che sta per relazione) dell'elemento link.
Da citare infine l'esistenza di programmi applicativi (es. Miro e Boxee) che, facendo anche uso di feed podcast, consentono di trasformare il computer in una sorta di WebTV mediante la quale realizzare una scaletta di contenuti multimediali da fruire sequenzialmente, come avviene con il normale apparecchio televisivo.
Questo termine può essere tradotto come rete di consegna dei contenuti, e descrive una filosofia che si discosta dal tradizionale approccio client-server, e utilizza la rete Internet come una infrastruttura globale su cui edificare una rete sovrapposta di elementi di replica, ognuno in grado di offrire gli stessi contenuti disponibili su di un server specifico. In questo modo, il client potrà recuperare la copia dell'oggetto richiesto direttamente presso l'elemento di replica a lui più prossimo, evitando di sovraccaricare la rete internazionale di transito con richieste spesso uguali, e provenienti da client topologicamente vicini tra loro.
Sebbene questa illustrata possa sembrare la classica funzione da far svolgere ad un elemento proxy, in questo caso i contenuti da replicare in prossimità del client non sono qualsiasi, ma sono solo quelli per i quali è previsto il servizio. Questa esigenza è particolarmente sentita nel caso di contenuti per i quali si può sviluppare un volume di richieste molto elevata, concentrata in un periodo di tempo molto breve, come nel caso, ad esempio, di un lancio pubblicitario televisivo, oppure per contenuti audio-video erogati in diretta.
Un esempio di CDN è l'insieme dei mirror proposti come siti alternativi da cui scaricare un determinato contenuto, e predisposti da organizzazioni come Sourceforge. Nella sua forma più basilare, al client che richiede il download di un contenuto viene visualizzata una pagina, in cui si offre di scegliere tra un elenco di siti alternativi per il download. Attualmente, si tende ad evitare che l'umano seduto davanti al browser debba scegliere di sua iniziativa, proponendo direttamente una scelta determinata dall'esito di servizi di geolocalizzazione basati su di una mappatura approssimata associata all'indirizzo da cui proviene la richiesta, come ad esempio quelli offerti da Maxmind, usati ad esempio da FlagFox.
Come
fatto già notare, delegare a dei dispositivi di replica la consegna
dell'oggetto richiesto all'utente finale è molto simile a quanto
ottenibile mediante un proxy, che intercetta
la richiesta originaria perché si trova sul suo stesso percorso, oppure
che è esplicitamente designato dal client a svolgere il ruolo di proxy.
In una CDN, invece, si tenta di instradare la
richiesta stessa del client, verso l'elemento di replica più
idoneo (ossia più prossimo al client), che si occuperà quindi di
servirla.
Mentre presso wikipedia troviamo una breve panoramica della problematica, la RFC 3568 illustra alcuni metodi comunemente in uso, e presso globule troviamo una trattazione assai più approfondita. Ma in linea di massima, il funzionamento di una CDN può essere decomposto nelle seguenti parti:
E' il sistema di instradamento
della richiesta adottato (più o meno) da Akamai,
che gestisce un nutrito insieme di surrogati,
dispiegati per i quattro angoli del pianeta, e che rivende
l'uso del servizio a chi intende farne uso. Il suo utilizzo si basa
nell'identificare la URI dell'oggetto da distribuire con un nome a
dominio per il quale la stessa Akamai è autorevole. Quando un client ne
farà richiesta, il DNS autorevole di Akamai risolve l'indirizzo
applicativo dell'oggetto con l'indirizzo IP associato all'elemento di
replica più prossimo al client, in base alla conoscenza dell'indirizzo
IP del DNS a cui il client ha inoltrato la richiesta di risoluzione
originaria, e che per effettuare la ricorsione, ha contattato il DNS di
Akamai. Ognuno dei surrogati, quindi, dovrà identificare la copia
dell'oggetto mediante la medesima sezione path
della URI che lo identifica.
In questo caso, l'instradamento della richiesta è attuato dal portale a cui si rivolge il client, in base all'indirizzo IP del client stesso, noto al portale al momento della ricezione della richiesta. Dopo aver inoltrato questa informazione alla entità di gestione della CDN, in modo che questa individui il nodo di replica più idoneo per quel client, il portale risponde alla richiesta, indicando la URI relativa alla copia dell'oggetto localizzata presso il surrogato indicato dall'entità di controllo.
Un esempio in cui la realizzazione di un servizio non può prescindere dalla esistenza di una adeguata CDN progettata allo scopo, è quello della distribuzione su scala globale (a più centinaia di milioni di fruitori) di un contenuto multimediale mediante Live Streaming, ossia dell'equivalente di una diretta TV, per il quale è materialmente impossibile replicare il contenuto, che viene generato in tempo reale a partire da una sorgente multimediale.
In tal caso se ci fosse un solo e unico server ad erogare i contenuti verso tutti i player, questo inevitabilmente dopo qualche migliaio di connessioni saturerebbe la propria banda di uscita, rendendo matematicamente impossibile raggiungere bacini di audience dell'ordine dei milioni di persone, come è invece possibile con le trasmissioni radio.
Una soluzione a questo problema in realtà esisterebbe, ed è quella basata sulla modalità di istradamento multicast, che potrebbe realizzare un albero di distribuzione dei contenuti basato sulla replica da parte dei router di Internet dei pacchetti in arrivo, verso ognuna delle diverse destinazioni (reti) in uscita, presso le quali è noto che ci siano ricevitori attivi. Alcune considerazioni hanno ostacolato l'interconnessione dei protocolli di routing multicast tra ISP differenti, e reso non percorribile questo approccio.
Volendo
illustrare in due parole (superficiali, approssimate) il funzionamento
del multicast, si può dire che si basa sull'uso di un particolare
gruppo di indirizzi IP (accomunati dal prefisso 224.0.0.0/8) non
assegnabili a singoli computer. Invece, una applicazione può aprire un
socket in ascolto su di un indirizzo
multicast (ora chiamato gruppo), provocando
l'effetto che il kernel invii pacchetti IGMP
diretti verso il proprio default gateway, con i quali gli notifica l'intenzione di ricevere i
pacchetti IP destinati a quel gruppo. Quindi, un protocollo
di
routing
(se abilitato) provvede a propagare tra i router di Internet
l'informazione che qualcuno è in ascolto per quel gruppo, in modo che i
router memorizzino, per ogni gruppo, su quali interfacce si è
manifestato interesse per la ricezione. Per un approfondimento, vedi l'appendice.
A questo punto, se un computer inizia a trasmettere pacchetti che hanno il gruppo (ossia l'indirizzo IP multicast) come destinazione, questi vengono inviati dal default gateway usato dalla sorgente (se partecipante al routing multicast) verso le interfacce di uscita dalle quali è arrivata la notizia che più giù qualcuno li vuole: lo stesso avviene anche per gli altri ruoter, e voilà! si realizza così un diverso albero di distribuzione, per ogni sorgente attiva. Notiamo ora due cose:
Dato che i nodi di replica di una CDN sono sparsi in giro per Internet, e che i contenuti possono essere distribuiti tra gli stessi, quel che si ottiene è una sorta di rete sovrapposta (Overlay Network), che sfrutta i collegamenti di Internet per permettere lo scambio dei contenuti tra i nodi dell'Overlay. Dato che il risultato finale, più o meno, può permettere di realizzare ciò che il multicast ha promesso ma non mantenuto, questa architettura viene spesso indicata come Application Level Multicast, od Overlay Multicast.
La differenza tra questi ultimi due termini risiede nel fatto che con ALM si indica il caso in cui i nodi dell'Overlay sono realizzati dagli stessi computer situati presso gli utenti finali: per questo motivo, un ALM viene anche indicato come End Sytems Multicast. Il risultato è che la distribuzione ottenibile è caratterizzata da una topologia spesso molto lontana dal caso ideale, nel senso che uno stesso link può esssere attraversato più volte dallo stesso traffico; inoltre, anche con le attuali conessioni ADSL a banda larga, la velocità dell'UpLink è in generale molto ridotta, al punto da porre un serio limite al numero di flussi uscenti da uno stesso nodo. Al contrario, il termine Overlay Multicast è usato per identificare il caso in cui i nodi dell'overlay sono disposti direttamente nella core network, dunque sotto il coordinamento degli stessi ISP, permettendo di realizzare un albero di distribuzione molto più efficente, anche per merito di un maggior fan-out di uscita per ogni nodo, in modo da limitarne di molto la profondità.
Data l'importanza dell'argomento per lo sviluppo di internet in campo telemediale, si è formato un gruppo di lavoro IRTF, SAMRG (Scalable Adaptive Multicast Research Group), nei cui atti del 66o meeting IETF, troviamo una interessante survey sull'argomento, mentre è in corso di perfezionamento un primo draft sull'argomento..
Un caso particolare di Overlay Network è quello realizzato da molte applicazioni di file sharing cosiddette peer-to-peer (p2p), così denominate perché mettono tutti i partecipanti su di uno stesso piano (video). Durante l'anno accademico 2006-2007, alcuni studenti di questo corso si sono impegnati nello svolgere delle tesine al riguardo; probabilmente però, può essere più utile approfondire gli aspetti delle diverse architetture, leggendo direttamente i riferimenti più o meno ufficiali, raggiungibili a partire da una tabella comparativa di protocolli ed applicazioni esistenti. In termini molto generali, le reti p2p sono caratterizzate dalla adozione di un metodo di indirizzamento di strato applicativo autonomo e indipendente dal DNS, e si distinguono tra loro in base ai metodi utilizzati per risolvere una serie di problemi:
Relativamente agli ultimi due punti, spesso gli oggetti da condividere sono suddivisi in sotto-parti dette chunks, consentendo a chi li richiede di scaricarli in contemporanea dai diversi altri peer che ne hanno annunciato la disponibilità. In questo modo, all'aumentare della popolarità di un oggetto, aumenta il numero di peer che lo detengono (non fosse altro perché lo stanno scaricando anch'essi), e dunque aumenta la facilità con cui può essere ottenuto.
Le reti peer to peer possono inoltre essere classificate in base alla loro topologia, come
E' il nome di un protocollo peer to peer nato per consentire il download contemporaneo di uno stesso file da parte di un numero molto elevato di clients, senza per questo sovraccaricare il sito di origine, in quanto tutti i clients cooperano nello scambiarsi tra di loro parti di file già scaricati, senza doverle richiedere di nuovo alla sorgente. Il file è suddiviso in parti di dimensione ridotta per facilitare le operazioni di scambio tra i peer.
Ogni peer inizia la sessione contattando una entità speciale denominata tracker, a cui comunica il proprio indirizzo (IP,porta), una stringa di 20 bytes che lo identifica, la quantità di bytes già ricevuti ed inviati, quanti ne mancano per completare la ricezione richiesta, ed un codice di evento che può essere started, completed o stopped in funzione dello stato in cui si trova. Il tracker quindi risponde inviando una lista contenente gli indirizzi (IP,porta) di un sotto-insieme (tipicamente, 50) di peer noti e che partecipano allo stesso scaricamento, permettendo così ai nuovi peer di conoscere con chi cooperare. Inizialmente, deve essere presente almeno un peer (detto seed) che detiene una copia completa del file. Con il passare del tempo, aumenta il numero di peer che hanno già completato lo scaricamento complessivo, per questo detti seeders, ovvero leechers qualora non lo abbiano ancora completato.
Non occorre che il tracker abbia una copia del file, anzi può essere un tracker pubblico che si presta a coordinare la distribuzione di files generici offerti da terze parti. L'indirizzo del tracker viene acquisito dai peer a seguito della visita di un sito web (o torrent index) da cui si ottiene via HTTP un file con estensione .torrent, detto anche file metainfo, a cui viene associato il MIME-Type application/x-bittorrent, e che contiene (tra le altre) le informazioni
Il tipo MIME del .torrent ricevuto fa si che il browser esegua la helper application ad esso associata, che identifichiamo con il peer stesso, e che implementa i successivi passi previsti da protocollo, iniziando dal contattare il tracker. Quindi, mediante le fingerprint dei singoli pezzi (chunks) i peer possono verificare che le copie ricevute dagli altri corrispondano a quanto annunciato dal .torrent, e non siano altri contenuti contraffatti. Un .torrent può descrivere anche più di un file (anzi, spesso è così), e le informazioni che contiene sono serializzate mediante una codifica detta Bencode, che permette l'annidamento di strutture dati come avviene per l'XML, ma con un notevole risparmio di caratteri.
Dopo aver contattato il tracker, e ricevuta la lista parziale degli altri peer, il nostro peer effettua delle connessioni TCP bidirezionali con gli altri, all'inizio della quale sono scambiate le informazioni relative a quali pezzi di file siano in loro possesso (mediante un bitfield), e quali no; d'altra parte, ogni peer contattato ha già svolto lo stesso colloquio con tutti gli altri suoi peer. A questo punto ogni peer prova a richiedere i pezzi mancanti a chi li ha, ma dato per mantenere efficienti i meccanismi di controllo di flusso e congestione del TCP non è previsto di mantenere più di 4 connessioni attive in contemporanea, molte richieste vengono rifiutate (dette anche choked, ossia soffocate): cionostante, chi ha rifiutato una richiesta, ne mantiene memoria, ed eventualmente lo stesso peer verrà successivamente unchoked, iniziando così un nuovo rapporto.
In base agli annunci di disponibilità dei singoli chunk da parte dei propri peer, un client preferisce richiedere per primi quelli che risultano più rari, che successivamente sarà lui stesso in grado di redistribuire, aumentandone perciò la disponibilità. Una eccezione a questa regola si ha subito dopo la partenza di un peer, quando invece la scelta di quale chunk richiedere per primo avviene in modo casuale, in modo da procurarsi velocemente qualcosa da poter scambiare, dato che i pezzi rari verrebbero molto probabilmente scaricati più lentamente proprio perché disponibili solo da parte di pochi peers.
Un peer può decidere di chokarne un altro ad es. perché questo, anzichè collaborare nello scambio, si limita a scaricare chunk senza inviarne nessuno; questa strategia prende il nome di tit for tat (o ritorsione corrispondente). Di tanto in tanto, un peer effettua un unchoking ottimistico, scegliendo a caso un peer con cui iniziare un nuovo rapporto di collaborazione, alla scoperta di peer con maggiore banda di uscita, e dando così una seconda opportunità ai peer precedentemente choked.
Si tratta di una rete p2p di tipo centralizzato tuttora impiegata da alcune applicazioni, sebbene i creatori, in seguito ad un accordo con l'RIAA, abbiano ritirato i programmi inizialmente sviluppati. I files che si intendono condividere sono identificati in base alla somma hash di 128 bit ottenuta a partire dal loro contenuto, e che quindi risulta la stessa anche se il file è rinominato. Per l'esattezza, il file è suddiviso in segmenti di 9.28 MB, su ognuno dei quali è calcolato un hash, e da tutti questi si calcola un ulteriore hash, che è quello che identifica il file. Gli identificatori (o link ed2k) vengono quindi registrati dai peer presso un server centralizzato assieme al nome del file, in modo che altri peer che lo cercano possano, citando le parole che compaiono nel nome, ricevere dal server una lista di files che hanno quelle parole nel titolo, assieme ai link ed2k, ed al socket (indirizzo IP e porta) presso cui contattare i peer che ne hanno annunciato il possesso. Quando un peer sceglie di scaricare il file indicato da uno dei link ricevuti, contatta i peer che lo detengono, i quali provvedono a gestire delle code d'attesa per ogni richiesta ricevuta.
Evidentemente la presenza dei server centralizzati costitusce un elemento di vulnerabilità del sistema, sia dal punto di vista della affidabilità che da quello di possibili controversie legali. Per questo il protocollo originale venne affiancato da un altro decentralizzato (Overnet), mentre l'applicazione peer tuttora più diffusa (emule) ha adottato allo stesso stesso scopo Kademlia.
Si tratta di un modo di realizzare una Tabella Hash Distribuita (o DHT), e svolgere in modo decentralizzato la ricerca del nodo dell'overlay che detiene un determinato file, mentre il download dello stesso avviene come previsto da Edonkey2000. Il nodo intenzionato a condividere un proprio file ne calcola una somma hash SHA-1 di 160 bit con la stessa procedura di edonkey, ed usa questo hash come chiave key con cui memorizzare nella DHT Kad il valore value costituito dal socket (IP, porta) su cui ascolta il nodo, più il suo identificativo (nodeID). La DHT Kad può quindi essere interrogata usando l'hash del file come key, permettendo di rintracciare il (o i) peer che lo detengono. La stessa rete kad è utilizzata anche per conoscere l'hash a partire dal nome del file, o di sue componenti, in modo che non occorra alcuna entità centralizzata, dato che la conoscenza di chi offre cosa è distribuita tra i peer che fanno parte della rete.
Distanza tra le chiavi - La modalità di instradamento dei messaggi che i nodi dell'overlay indirizzano verso il nodo responsabile di key, è direttamente legata al particolare schema di partizionamento delle chiavi, che deriva dal calcolo di un valore di distanza d(key1,key2) tra coppie di chiavi, basato sull'operazione di OR esclusivo (EXOR) eseguita tra le rappresentazioni binarie delle stesse. Esprimendo il nodeID dei nodi con lo stesso numero di bit usato per le chiavi, la medesima funzione di distanza calcola anche la distanza tra coppie di nodi. Ad esempio, l'ex-or di due chiavi 0110101100 e 0011011011 risulta pari a 0101110111 ovvero 375 in notazione decimale. Come evidente, la posizione del primo bit differente partendo da sinistra dà il maggior contributo al valore di distanza tra le chiavi. Una distanza così definita, seppur non euclidea, gode di proprietà del tutto simili a quelle della distanza geometrica, come: a) la distanza tra un nodo o se stesso è zero; b) sussiste la propretà di simmetria in quanto d(A,B) = d(B,A); c) sussiste la diseguaglianza triangolare, ovvero d(A,C) <= d(A,B) + d(B,C).
Albero
di partizionamento - La
figura a lato mostra un esempio in cui lo spazio delle chiavi è
descritto da tre soli bit, che identificano anche i 7 nodi presenti (manca
il
nodo 011), rappresentati dai
cerchietti disegnati in basso. Dal punto di vista di un nodo particolare
(ad es. 110,
disegnato in nero) il resto dei peer può essere suddiviso in 3 insiemi
(le aree grigie), ognuno dei quali raggruppa tutti i nodi con l'i-esimo
bit diverso dal proprio identificatore: quindi nella primo insieme
compaiono i nodi 000, 001 e 010
che hanno il primo bit diverso da 110,
e per questo risultano i più lontani
da 110. Nella seconda lista
compaiono 100 e 101,
con il secondo bit diverso, mentre la terza contiene solo 111,
che differisce da 110 solo
per l'ultimo bit, e dunque è il più
vicino.
La conoscenza degli altri - Un generico nodo non ha una conoscenza completa dell'identità di tutti gli altri nodi presenti, ma ne conosce solo alcuni, e organizza questa informazione in N liste (ossia pari al numero di bit del nodeID) di k elementi ciascuna (es. k=20) dette k-liste. In ogni lista si possono includere un massimo di k nodi, mentre l'i-esima k-lista può ospitare solo quei nodeID i cui i-1 bit più significativi sono uguali a quelli del nodeID che memorizza la lista. In pratica quindi le k-liste rappresentano sotto-insiemi delle partizioni descritte sopra; ad esempio la prima lista potrebbe contenere la metà dei nodi (quelli con il primo bit diverso), mentre l'ultima lista potrà contenere un solo nodo (quello con l'ultimo bit diverso). Ma dato che il massino numero di nodi per lista è k, ne consegue che la conoscenza degli altri sarà più specifica per i nodi vicini, e vaga per quelli più lontani. Le liste vengono popolate man mano che i nodi si scambiano messaggi, venendo così a conoscenza l'uno dell'altro; quando si totalizzano k elementi in una lista, e si viene a conoscenza di un nuovo nodo, questo viene aggiunto al posto di quello inattivo da più tempo, ma solo se quest'ultimo risulta non più raggiungibile.
Messaggi - il funzionamento di Kademlia si basa su quattro tipi di messaggi che i nodi possono scambiarsi:Creazione dell'overlay - Quando un nodo entra nella rete per la prima volta, sceglie per se stesso un nodeID casuale di 160 bit, e contatta un nodo di bootstrap, di cui conosce il socket per altre vie, come ad es. un elenco scaricato a parte, oppure una diversa rete p2p, come la stessa edonkey2000. Emette quindi un messaggio FIND_NODE diretto al nodo di bootstrap, in cui specifica come chiave il proprio nodeID, sia per scoprire se è già usato, sia per popolare le liste in cui memorizza i riferimenti dei nodi che conosce. Il nodo di bootstrap, dopo aver memorizzato i dati del nuovo arrivato, ne usa il nodeID per calcolarne la distanza rispetto agli ID presenti nelle proprie k-liste, e da questi sceglie un massimo di k nodeID come i più vicini di se stesso al nodeID del nuovo arrivato. I contatti (nodeID, IP, porta) dei nodi così selezionati sono quindi comunicati al richiedente, che a sua volta li colloca nelle proprie k-liste. Dato che la distanza-EXOR tra l'ID del richiedente e quello dei nodi ricevuti in risposta è minore di quella tra il richiedente ed il nodo di bootstrap, saranno aggiornate solo le k-liste a destra (nell'albero binario) dell'ID del nodo di bootstrap. A questo punto il nuovo nodo può reiterare la richiesta FIND_NODE di stesso verso i nuovi nodi di cui è venuto a conoscenza, i modo da annunciarsi presso di loro, e migliorare la conoscenza della regione a esso vicina. Infine, può reiterare la richiesta (verso un qualsiasi nodo conosciuto) chiedendo questa volta di localizzare degli ID scelti a caso ma dislocati nell'albero binario alla propria sinistra, in modo da migliorare la conoscenza della regione di rete più distante.
Instradamento - Per inviare un messaggio STORE (key,value) o FIND_VALUE (key) si ricorre ad una procedura iterativa, ad ogni passo della quale il mittente viene a conoscenza dei socket dei nodi con un nodeID sempre più vicino alla chiave richiesta, interrompendo la ricerca quando la risposta non contiene più nodi sconosciuti. In tal caso, il nodo con ID più vicino alla chiave cercata sarà quello desiderato. Analizziamo più in dettaglio come si precede:
Memorizzazione e recupero di un dato - In entrambi i casi si procede inviando un messaggio FIND_NODE (key) ad un nodo di cui si conosce il socket ed il cui ID è il più vicino alla chiave: questo risponderà con i riferimenti ad un insieme di k nodi a lui noti, ancor più vicini alla chiave indicata. Lo stesso messaggio FIND_NODE (key) può essere inviato in parallelo a più di un nodo. Le risposte ricevute sono quindi usate per reiterare la richiesta indirizzandola ai nodi più vicini alla chiave, finché non se ne trova uno a distanza zero, oppure non se ne trovano più di ancor più vicini. Per la memorizzazione si termina il processo inviando un messaggio STORE (key,value) al nodo la cui ID è la più vicina alla chiave. Per il recupero del messaggio, si può invece inviare fin dall'inizio il messaggio FIND_VALUE (key) anziché FIND_NODE, reiterando come sopra la richiesta verso nodi sempre più vicini al target, per terminare le iterazioni quando uno dei nodi interrogati restituisce, anziché nodi più vicini alla chiave, direttamente il valore cercato.
Scalabilità dell'overlay - La rapidità di ricerca può migliorare se si provvede a memorizzare i valori non solo presso il nodo più vicino alla chiave, ma anche presso quelli ad esso limitrofi, ottenendo anche il vantaggio che qualora qualcuno di essi si sconnetta, il valore è ancora reperibile. Nel caso di valori molto richiesti, può essere vantaggioso replicarli anche presso nodi ancor più distanti, in modo da evitare concentrazioni di traffico presso il nodeID più vicino alla sua chiave.
Variabilità della popolazione di peer - I nodi che memorizzano un valore vi applicano anche un timeout, scaduto il quale il valore è cancellato, in modo che qualora il nodo che lo ha pubblicato per primo esca dalla rete, l'informazione associata decada. Se al contrario il nodo rimane, è suo compito rinfrescare periodicamente la memorizzazione dei propri dati. In particolare, se nel frattempo ha fatto il suo ingresso qualche nodeID ancor più vicino alla chiave, dopo un transitorio legato all'evoluzione della propria connettività con l'overlay, sarà presto raggiunto da un messaggio STORE (key,value).
Indicizzazione e ricerca - Come già descritto, il nodo che intende condividere un file prima calcola l'hash del suo contenuto, e quindi lo usa come chiave per memorizzare il proprio socket, presso cui essere contattato per distribuire il file. D'altra parte chi cerca il file, lo fa a partire dal suo nome, o da parti di esso, come ad es. nel caso di files musicali, il titolo, l'autore, o parti di queste stringhe. Il nodo che condivide il file quindi calcola anche gli hash delle parole che compaiono nel nome del file, e li usa come chiavi per memorizzare un valore costituito dall'hash del contenuto del file e dal suo nome. In questo modo, chi ricerca una parola interroga la rete Kad utilizzando come chiave l'hash di tale parola, e ottiene i nomi dei file disponibili che la contengono, assieme ai rispettivi hash dei contenuti dei file. Viene quindi inviata una seconda richiesta, usando questa volta come chiave l'hash del file scelto in base al suo nome.
E' il nome dato ad una metodologia di esecuzione di applicazioni remote, che fa uso di HTTP come strato di trasporto per il recapito delle invocazioni, per il passaggio dei parametri, e per la ricezione dei risultati. Benchè l'invocazione di applicazioni remote non contenga assolutamente nulla di nuovo (vedi appendice sulla elaborazione distribuita), i Web Service hanno dalla loro la possibilità di far tesoro delle esperienze preesistenti, possiedono una minore cripticità dovuta al formato testuale delle comunicazioni, e godono di una universalità di accesso, legata all'uso della porta 80, riuscendo in tal modo a scavalcare i problemi legati ai firewall. Per certi versi, si tratta di una evoluzione della logica dei CGI, a cui è stata aggiunta una formalizzazione più stringente per quanto riguarda il meccanismo di passaggio dei parametri, e dei meccanismi di auto-documentazione dei servizi offerti. Inoltre, mentre i CGI sono pensati per essere invocati da parte di un interattore umano che opera dietro la finestra di un browser web, i Web Service sono pensati per essere utilizzati da parte di procedure software.
Il Simple Object Access Protocol è un framework che permette l'invocazione di procedure remote mediante lo scambio di messaggi in formato XML, trasportati tipicamente su connessioni HTTP. La struttura dei messaggi segue il paradigma Head-Body, in cui gli Header contengono meta-informazioni riguardanti il routing, la sicurezza e le transazioni, mentre il Body trasporta il contenuto informativo.
I protocolli degli Web Sevices,
oltre a prevedere SOAP come meccanismo per inviare i messaggi di
esecuzione remota, prevedono l'esistenza di altri protocolli, come il Web Services Description Language (WSDL),
che
descrive come interagire con un determinato servizio, indicando i metodi
messi a disposizione, i suoi vincoli
(protocollo, formato dei parametri di
ingresso e delle risposte), ed il suo punto di
accesso, ovvero l'URI del Web Service. Come mostrato in figura,
il fornitore del servizio pubblica presso un Service
Broker (strutturato in accordo a UDDI)
la descrizione della propria offerta, in modo che questo possa essere
successivamente interrogato da un potenziale richiedente, che individua
così chi offre il servizio di cui ha bisogno, e quindi lo istanzia per
mezzo di messaggi SOAP. Presso wikipedia, è mostrato un semplice esempio
di
transazione SOAP.
Prima che venisse definito SOAP, WSDL e UDDI, un certo Dave Winer (sì, lo stesso che ha definito l'RSS 2.0) aveva già completato la definizione di una specifica, chiamata XML-RPC, per svolgere né più né meno la funzione di invocare l'esecuzione remota di una applicazione, incapsulando la richiesta in HTTP, esprimendo parametri comunque complessi mediante una rappresentazione XML, e ricevendo in risposta strutture dati egualmente complesse. In effetti, fu proprio questa specifica, che poi diede il via ai lavori di definizione di SOAP.
Nel caso in cui, molto semplicemente, sussista unicamente l'esigenza di invocare delle procedure remote, e non ci si voglia stare a preoccupare molto di definire un nuovo protocollo per gestire il passaggio dei parametri, la soluzione di utilizzare una delle tante librerie che si occupano della serializzazione dei dati in XML, del loro invio in HTTP, e della formattazione inversa dall'altro lato del collegamento, sembra essere quella meno impegnativa.
Presso wikipedia, possiamo trovare una tabella riassuntiva della
formattazione necessaria ai diversi tipi
di dato,
assieme ad alcuni esempi di transazione
XML-RPC. Una valida alternativa si è rivelata JSON-RPC,
in cui le chiamate a procedura remota e relativo scambio dati sono
realizzati con l'ausilio della serializzazione definita come JSON.
Mentre questo termine, nella musica hip-hop,
individua un brano realizzato ri-mixando
assieme diversi brani preesistenti, nel Web un Mashup
è una applicazione distribuita che utilizza informazioni raccolte da
siti diversi, per combinarle assieme e realizzare così un nuovo
servizio (video).
Le informazioni possono essere raccolte ad es. mediante feed RSS, Web
Services, API pubbliche. Il codice software (scritto, ad es., in javascript)
che realizza il mashup viene tipicamente distribuito tramite il sito
che ospita il servizio, ed eseguito presso il browser dell'utente, come
ad esempio è il caso di Twittervision,
che usa le API di Twitter e
di Google Maps,
per localizzare in diretta la provenienza degli inserimenti su Twitter.
Presso programmableweb sono
presenti tutti i riferimenti alle API offerte ed ai mashup fin qui
sviluppati dai fornitori più disparati.
La modalità con cui un mashup recupera le informazioni remote in base alle quali realizzare il nuovo servizio può ricadere in uno dei tre casi del titolo, che ora descriviamo meglio.
La modalità RESTful (lett. riposante) deriva da REpresentational State Transfer (REST), un termine usato per descrivere l'accesso (state transfer) ad una rappresentazione di un oggetto, individuato per mezzo di un identificatore univoco (la URI), e recuperato mediante un protocollo universale (l'HTTP). Una applicazione interagisce con una risorsa senza curarsi di eventuali elementi intermedi con ruoli di cache, finché questi si comportano in modalità stateless; inoltre, deve essere in grado di gestire il formato restituito, tipicamente un documento HTML, XML, RSS o JSON, ma potrebbe essere anche un'immagine o qualsiasi altro contenuto, come espresso mediante l'intestazione Content-Type. Quando un server HTTP riceve una richiesta REST, sa cosa fare in base al path della URI, ed al metodo HTTP. Ad esempio, una tradizionale URI di richiesta HTTP da soddisfare mediante un CGI avrebbe la forma
http://www.myonlineshop.com/getProduct?productID=12345 |
mentre la stessa richiesta in modalità RESTful ha invece una URI con sintassi
http://www.myonlineshop.com/product/12345 |
in cui al posto del verbo getProduct è usato il sostantivo product. Dal punto di vista del server, agendo sulla configurazione di Apache la seconda forma viene internamente ri-scritta nella prima, e la risorsa ancora acceduta per mezzo di un CGI. Inoltre, il metodo HTTP è usato per indicare un'azione equivalente ad una transazione di database CRUD (Create, Read, Update or Delete) in accordo alla tabella
|
in cui anche stavolta la configurazione di Apache può associare ai diversi metodi, diversi CGI. Infine, nel caso in cui l'invocazione del metodo sulla URI dia luogo ad una condizione di errore, questo è comunicato al client mediante i codici di errore previsti per le risposte HTTP.
La modalità SOA (Service
Oriented
Architecture)
individua le modalità di sviluppo delle applicazioni in forma di
servizi interoperabili, ossia funzioni ben definite realizzate da
componenti software riutilizzabili per scopi diversi. Sebbene ciò possa
essere realizzato anche basandosi sulle tecniche RESTful, SOA prevede
sia di arricchire la semantica di
invocazione delle chiamate remote come ad es. permesso da XML-RPC e
SOAP, sia di facilitare la scoperta e la descrizione delle API offerte,
come realizzato mediante WSDL. Tuttavia, proprio questa ricchezza
espressiva ha determinato una maggiore difficoltà realizzativa. Ad
esempio, in SOAP richieste e risposte sono nascoste
nel body di HTTP, e devono essere interpretate
quando ricevute per determinare l'operazione da svolgere e gli
argomenti da utilizzare. Inoltre, SOAP non permette il caching delle
risposte, e gli stessi codici di errore sono annidati
nel body HTTP. In definitiva, le API destinate ad un pubblico più vasto
sono generalmente realizzate in modalità REST, mentre quelle che
concorrono ad un risultato più complesso e più controllato, in modalità
SOA.
La modalità Web Scraping infine è quella adottata nei confronti di fonti informative non collaborative, i cui contenuti cioè non sono resi accessibili mediante API ben definite, ma unicamente offerti nella forma di semplici pagine web. L'applicazione che intende estrarre da tali pagine le informazioni necessarie ai propri fini, implementa quindi uno User Agent HTTP mediante il quale richiedere le pagine, che sono poi analizzate mediante strumenti di DOM parsing e Regular expression matching.
Si tratta di un movimento che ha molte analogie con altri come Open Access e Open Source, e caratterizza un contenuto od un dato come aperto "se chiunque è in grado di utilizzarlo, ri-utilizzarlo e ridistribuirlo, soggetto, al massimo, alla richiesta di attribuzione e condivisione allo stesso modo". Quando ci si ispira ai principi dell'Open Government, ci si riferisce ai dati prodotti dalle amministrazioni pubbliche, in quanto finanziati da denaro pubblico, e che devono ritornare ai contribuenti sotto forma di dati aperti e universalmente disponibili. Più in generale si può trattare di cartografia, genetica, composti chimici, formule matematiche e scientifiche, dati delle bioscienze, dati anagrafici, dati governativi, ecc. Oppure i dati andrebbero trattati come beni comuni, in quanto ad es. appartengono al genere umano, come i genomi, i dati medici, ambientali e meteorologici. Infatti, restrizioni sui dati e sul loro riutilizzo limitano lo sviluppo della comunità, così come in campo scientifico il tasso di scoperta è accelerato da un migliore accesso ai dati.
Un dato può dirsi aperto quando è reso disponibile mediante un formato aperto, ossia standardizzato e facilmente accessibile mediante una applicazione informatica non specifica, e deve essere rilasciato attraverso licenze libere che non ne impediscano la diffusione e il riutilizzo da parte di tutti i soggetti interessati. Anche se questi concetti sono ben consolidati da anni, con "open data" si individua l'accezione piuttosto recente e legata a Internet come canale principale di diffusione dei dati stessi.
Esistono iniziative che collezionano fonti di open data, come CKAN, DatiOpen.it, dati.gov.it, ed istituzioni che permettono l'accesso in modo aperto ai risultati delle proprie elaborazioni come Istat.
Il Web tradizionale non prende in considerazione la struttura ed il significato del contenuto delle pagine servite: ad esempio, per un qualsiasi motore di ricerca, non esistono differenze tra il termine Rossi nel contesto Il Sig. Rossi ed il termine Rossi nel contesto Capelli Rossi. Per strutturare meglio i contenuti, sono allora stati definiti alcuni linguaggi, quali Resource Description Framework (RDF) e Web Ontology Language (OWL), entrambi basati su XML, che consentono di esprimere le relazioni tra le informazioni rifacendosi alla logica dei predicati mutuata dall'intelligenza artificiale.
Come accennato, il desiderio di definire un metodo che permetta a programmi in esecuzione su computer differenti, con sistemi operativi differenti, di cooperare, ripartendosi il carico computazionale, ed offrendo ognuno la propria tipologia particolare di servizi, nasce assieme ai computer ed alle reti dati.
In linea generale, l'elaborazione distribuita è realizzata dopo aver definito un protocollo di comunicazione tra chi usa e chi offre il servizio, con una sua propria sintassi, una sua macchina a stati, una porta ben definita su cui comunicare, un metodo di codifica dei dati indipendente dalla architettura delle entità coinvolte... tutte problematiche analizzate e discusse, praticamente fin dall'inizio del corso. La differenza maggiore è che, mentre le soluzioni trattate finora miravano ognuna a risolvere un particolare problema, una architettura di elaborazione distribuita vuole permettere l'invocazione di programmi qualunque.
Le soluzioni a questa esigenza sono a volte indicate con il temine di middleware, intendendo dire che si tratta di funzioni che giacciono tra il livello applicativo e quello di rete. Nel corso della storia precedente e/o parallela al web, si sono succedute diverse iniziative in tal senso, tra cui possiamo citare:
Il termine Remote Procedure Call rende bene l'idea di ciò che si vorrebbe ottenere, ed il suo primo uso risale al 1976, quando fu menzionato nella RFC 707. L'implementazione più celebre di RPC è stata quella della Sun, chiamata ONC RPC: è basata sullo scambio di messaggi, serializza i dati mediante XDR, utilizza sia UDP che TCP, ed è alla base del metodo di condivisione files NFS. L'accesso ai servizi offerti via RPC è attuato attraverso un demone port mapper, che si pone in ascolto sulla porta ben nota 111 (TCP e UDP), e svolge il ruolo di multiplare le diverse richieste di esecuzione remota per mezzo del numero di programma, contenuto nella invocazione per identificare il servizio remoto richiesto, e per il quale (numero), il programma (es. NFS) che intende offrire quel servizio, si registra presso il portmapper. L'uso di RPC ed NFS è tuttora molto diffuso, prevalentemente in ambito di rete locale.
La Common Object Request Broker Architecture è definita dall'Object Management Group come un metodo che abilita alcuni componenti software scritti in linguaggi diversi, in esecuzione su computer diversi, a lavorare assieme. Si basa sul concetto di interface definition language (IDL), che specifica le interfacce che gli oggetti presentano al mondo, in quanto CORBA realizza un mapping da IDL ai diversi specifici linguaggi di programmazione. Nonostante la sua definizione risalga ai primi anni '90, a tutt'oggi non è riuscito ad affermarsi, ed alcune critiche alla sua impostazione non hanno trovato risposta.
La Remote Method Invocation pone l'accento sulla filosofia ad oggetti (in opposizione a quella di chiamata a procedura di RPC), che determina l'interazione con oggetti remoti mediante l'invocazione di metodi. La RMI consente ad un codice Java (a cui è indissolubilmente legata) di invocare l'esecuzione di un metodo offerto da un oggetto remoto, quasi come se fosse locale.
Una implementazione alternativa ad RPC, è stata il Network Computing System (NCS) da parte di Apollo Computer, che venne successivamente usato come la base per il DCE/RPC nel Distributed Computing Environment di OSF. Un decennio più tardi, Microsoft adotta DCE/RPC come base per il suo MSRPC, su cui fonda DCOM. Quest'ultima è stata la risposta di Microsoft a CORBA, anche se attualmente, gli stessi scopi sono invece perseguiti con l'architettura .NET.
Sono le due tecnologie con cui Microsoft risponde alle esigenze di elaborazione distribuita, tranne che... non sono aperte ad architetture differenti!
Tra i diversi metodi proposti per realizzare il multicast, il PIM-SM è definito dalla RFC 4601 (PIM-SM), che descriviamo affidandoci alle immagini prelevate dall'ottimo tutorial di Paolo Danesi. Innanzitutto, per ogni gruppo multicast deve essere stato configurato un Router particolare, denominato Randez Vous Point (RP, ovvero luogo di incontro), il quale comunica questo suo ruolo a tutti i ruoter di Internet (!) mediante uno dei modi descritti in questo tutorial. La presenza del RP, oltre a garantire una forma di controllo sulla diffusione multicast, permette la creazione di alberi di distribuzione (shortest path tree) da ciascuna delle sorgenti verso tutti i ricevitori, senza che questi conoscano a priori la reciproca esistenza.
Allorquando un aspirante ricevitore apre un socket in ascolto per il
gruppo G, il suo default gateway (o meglio il designated
router della LAN), a
seguito della ricezione del IGMP join,
inoltra verso l'RP il
messaggio unicast PIM join (*G),
segnalando a questo l'interesse a ricevere il traffico multicast
diretto verso G e prodotto da qualunque sorgente; ciò determina che in
ogni router attraversato sia aggiunta una riga alla tabella di routing
multicast (detta MRIB, Multicast
Routing Information Base)
in modo da inoltrare il traffico multicast ricevuto da chiunque e
diretto verso G, anche verso l'interfaccia di uscita da cui il router ha
ricevuto il join.
Dato che i join provenienti dai diversi ricevitori e diretti verso il
RP prima o poi convergono in qualche router di transito, le modifiche i
diversi MRIB coinvolti determinano l'esistenza di un unico albero
condiviso (shared tree)
mediante il quale il traffico multicast è distribuito dal RP verso
tutti i ricevitori.
Per quanto riguarda le sorgenti,
non appena il loro designated router
avverte traffico
(1) diretto verso un
gruppo multicast G, incapsula
questi pacchetti all'interno di messaggi
di
registrazione
(2) previsti da PIM, e li invia in unicast
verso il RP designato per quel
gruppo. Da parte sua, RP scapsula
i pacchetti ricevuti dalla
sorgente, e li inoltra (3) tramite lo shared
tree(in
multicast) verso tutti i ricevitori interessati al gruppo. Nel caso in
cui una sorgente inizi a trasmettere prima che ci siano ricevitori, le due
fasi sono temporalmente invertite.
Il funzionamento potrebbe esaurirsi qui, ma nel caso in cui sorgente e ricevitore siano topologicamente vicini, ed il RP sia in tuttaltra regione della rete, l'uso di un unico shared tree si rivela inefficiente. Interviene allora la modalità sparse mode di PIM, che consente di realizzare un diverso albero di distribuzione per ogni sorgente, con radice questa volta sulla sorgente stessa, chiamato Shortest Path tree. A tale scopo, RP inizia ad inviare messaggi PIM (4) di join(S,G) verso il router (R5) da cui riceve i register in unicast, e questi join determinano l'aggiunta nei MRIB dei router attraversati di una riga che stabilisce l'inoltro del traffico diretto verso G e proveniente da S, verso l'interfaccia da cui è stato ricevuto il join. Pertanto, anche il RP si qualifica ora come un ricevitore multicast, e l'effetto dei suoi join (S,G) diretti verso la sorgente è quello di iniziare la costruzione di un albero di distribuzione di tipo shortest tree.
Ricevendo il join(S,G), R5
pur
continuando ad inviare verso RP il traffico incapsulato, inizia ad
inviarlo anche in multicast (5) (in effetti, sono le MRIB (S,G) dei
router che ne determinano l'inoltro), che arriva anche al RP; in questa
fase il RP riceve dunque il traffico
duplicato, sia via multicast che via unicast; la versione unicast viene
ora scartata, mentre qualla nativamente multicast segue lo shared
tree verso i
ricevitori. Il RP quindi provvede ad
inviare verso il router della sorgente (R5) un messaggio register
stop (6) che determina
l'interruzione dei messaggi register.
La transizione (switchover)
verso la creazione dello shortest
tree con radice nella sorgente avviene su iniziativa dei designated
router
dei ricevitori (R1 nell'esempio): questi iniziano ad
inviare a loro volta dei join(S,G)
(7)
verso la sorgente S che produce il traffico multicast (la cui identità
è ora nota in virtù del traffico istradato via RP), e mediante
questi messaggi i router intermedi (nell'esempio R2 e R3)
alterano la MRIB e aderiscono allo shortest
tree tra sorgente S e ricevitore, che viene
quindi attraversato dal traffico multicast (8) generato da S per
raggiungere il
ricevitore. Alcuni router (ad es, R2)
possono ora appartenere ad
entrambi gli alberi (shared e shortest) e dunque ricevere il
traffico multicast duplicato. Gli ultimi passi di PIM-SM sono quindi
quelli di smatellare lo shared
tree tra RP e ricevitore,
mediante i messaggi prune(S,G)
(9) inviati dal designated router del ricevitore verso il RP.
Ovviamente, ogni volta che si attiva un nuovo ricevitore, così come una nuova sorgente, l'intero processo è ripetuto! In realtà, finché il RP continua a ricevere il multicast dalle sorgenti già attive, la fase della registrazione della sorgente viene omessa. Infine, qualora non vi siano più ricevitori e/o sorgenti (che devono ribadire periodicamente la loro presenza mediante dei keep-alive) il RP provvede a smantellare anche lo shortest tree tra sorgente e RP, ad opera dei prune(S,G) (10) inviati dal RP verso il designated router della sorgente.
Si tratta di una classe di sistemi distribuiti decentralizzati che permettono l'accesso rapido ad un valore V, a partire da una informazione K detta chiave che lo identifica, e che memorizzano le coppie (K,V) su di un insieme variabile di elementi dislocati in rete. Per meglio definire il problema e la sua soluzione procediamo andando per gradi, considerando come esempio il caso in cui K sia un nome e cognome di persona, e V siano altre informazioni come indirizzo, telefono, email, etc., ed illustrando prima le due alternative dell'array lineare e della tabella hash non distribuita.
In questo caso possiamo pensare di memorizzare le coppie (K,V) in una tabella, o array lineare, con i valori di K nella prima colonna, memorizzati in ordine alfabetico, ed i valori V nella seconda colonna. In tal caso l'accesso ai dati associati ad una determinata K può avvenire esaminando sequenzialmente le n chiavi memorizzate con complessità O(n/2), oppure mediante una ricerca dicotomica con complessità O(log2n); in entrambi i casi, ogni volta che si inserisce o rimuove un elemento, occorre spostare buona parte di tutti gli altri. Nel caso in cui anziché un array si utilizzi una struttura dati a lista collegata, si semplificano le operazioni di inserimento e rimozione, mentre si complicano quelle di ricerca/accesso/cancellazione.
Le
tabelle hash usano K per calcolare
(mediante una funzione hash)
una quantità intermedia, che è usata come indice
per accedere ai contenuti di un array lineare, in cui sono memorizzati i
valori V associati all'indice
(ed alla chiave); allo stesso modo, il successivo recupero di
V avviene calcolando prima
l'hash di K, e quindi accedendo
alla corrispondnete riga della tabella. In questo caso l'accesso al dato
è immediato, con complessità
O(1), e l'inserimento/rimozione
di un nuovo elemento risulta una operazione semplice, almeno finchè non
avviene una collisione, ossia
due
diverse chiavi danno luogo allo stesso hash, e dunque allo stesso indice,
nel qual caso esistono diverse
soluzioni.
Dato che il fenomeno della collisione avviene con maggior probabilità
quando il numero di diverse chiavi diviene comparabile con la
dimensione dell'array, all'aumentare delle prime si può modificare la
dimensione dell'array e ridefinire la funzione hash, riposizionando di
conseguenza gli elementi già presenti.
Le Distributed
Hash Table prevedono che la memorizzazione delle coppie (K,V)
sia distribuita su di un insieme di elementi (o peers)
distribuiti in rete, ognuno dei quali si prende cura di conservare i
valori associati ad una o più delle possibili chiavi, e rispondere alle
richieste di recupero. Inoltre, l'ingresso e la fuoriuscita dei nodi
peer comporta la riorganizzazione di un loro numero molto ridotto, in
modo che la DHT possa mantenersi operativa anche in condizioni
fortemente dinamiche e con popolazioni molto numerose. Notiamo infine
come una DHT esegua la sua funzione in modo autonomo e privo un
coordinamento centralizzato, e come l'insieme dei partecipanti realizzi
una Overlay Network in cui ogni
peer
si mantiene in contatto con un numero ridotto di nodi, tipicamente
log2n.
L'insieme delle possibili chiavi individua un keyspace (ad es., l'insieme dei numeri binari di 160 bit), mentre uno schema di partizionamento dello stesso ripartisce le chiavi tra i peer presenti al momento. Per memorizzare (ad es.) un nome_file assieme al file stesso, viene calcolato l'hash (ad es. SHA-1) del nome_file, ottenendo i 160 bit della chiave k; quindi, viene inviato un messaggio del tipo put(k,file) verso un peer della DHT, che inizia ad instradarlo verso il peer responsabile per la chiave k. Il messaggio arriva a destinazione per il tramite dei peer che hanno preso parte all'instradamento, ed infine il peer responsabile di k memorizza file. Il recupero del file avviene invece mediante un messaggio del tipo get(k), che pure viene instradato allo stesso modo finché non raggiunge il nodo responsabile, che fornisce il file cercato.
Sono stati proposti diversi modi di realizzare la DHT, che si differenziano per come sono realizzati il partizionamento del keyspace e l'overlay network, come ad esempio CAN, Chord, Pastry, Tapestry, Kademlia, su cui possono basarsi applicazioni di condivisione file, caching, risoluzione di nomi, messaggistica, multicast e content distribution. Un elemento comune a questi sistemi è il metodo di partizionamento del keyspace che si basa su di una funzione d(k1,k2) di distanza astratta tra le chiavi k1 e k2 (indipendente dalla reale distanza tra i peer responsabili per tali chiavi), mediante la quale si realizza la tecnica nota come consistent hashing, che permette di limitare il numero di aggiornamenti quando l'insieme dei peer cambia. Se ad es. identifichiamo ogni peer con lo stesso numero di bit usato per le chiavi, un peer kp può essere responsabile delle chiavi k per cui d(kp,k) è la minima tra tutti i kp presenti: in tal modo se un peer abbandona l'overlay, le chiavi di cui era responsabile dovranno essere riassegnate ai peer vicini, mentre gli altri non saranno coinvolti.
Un secondo elemento comune alle diverse DHT consiste nella limitata
conoscenza che ogni peer ha degli altri peer dell'overlay, che tipicamente
non
supera il numero di O(log2n) su n
peer totali. Come conseguenza sul processo di instradamento, se un
generico peer kp
non è responsabile di una determinata chiave k,
deve conoscere almeno un altro peer kq per il quale la cui distanza d(kq,k)
è minore di d(kp,k),
in modo tale che ad ogni inoltro
il messaggio arrivi sempre più vicino al peer responsabile.
Infine, se un peer non conosce
suoi pari più vicini ad una
determinata chiave, allora significa che è lui a doverne diventare
responsabile. I metodi di scoperta dei peer più o meno prossimi sono
opzioni peculiari delle diverse tecniche realizzative, e non vengono
qui approfonditi.
Dal TCP al VoIP, dal DNS all'Email alla crittografia, tutto ciò che accade
dietro le quinte di Internet, completo di cattura del traffico.
Scopri
come effettuare il download,
ricevere gli aggiornamenti,
e contribuire!