Middleware vari - LIA · 2012. 2. 17. · Middleware vari 2 Col termine middleware si indica tutto...
Transcript of Middleware vari - LIA · 2012. 2. 17. · Middleware vari 2 Col termine middleware si indica tutto...
Middleware vari
2
Col termine middleware si indica tutto ciò che è in mezzo tra l'utente e tutte le risorse locali di
sistema operativo e di tecnologie di scelte locali.
In realtà il termine middleware è un termine molto vecchio, 1968, nasce difatti con la NATO come
idea di avere un infrastruttura tra utente e risorse di base: idea appena abbozzata a quei tempi perché
i middleware diventano sensati solo quando si parlerà, in seguito, di sistema distribuito, sistemi
quindi con una serie di nodi partecipanti e, tipicamente, fortemente eterogenei.
L'obbiettivo quindi è quello di fornire dei servizi con qualità!
3
Si parla di risorse eterogenee: difatti un middleware tipicamente non è un infrastruttura di supporto
che gestisce un architettura tutta uguale, bensì un middleware deve superare problemi di differenze e
rendere omogenee risorse eterogenee per poterci fare delle cose.
I middleware hanno quindi ancor più evidenziato l'esigenza di avere una serie di funzionalità che
consentano di gestire e controllare le risorse stesse. Non solo uso delle risorse (piano utente), ma
anche piano di gestione. Quest'ultima parte, e quindi l'aspetto dinamico, sono molto importanti per
avere una buona qualità: non devo solo erogare il servizio ma devo anche controllare che le cose
vadano bene.
I primi middleware sono i middleware RPC: difatti corrispondono, in parte, a ciò che abbiamo
appena detto: macchine distribuite ed eterogenee, possibilità da remoto di ottenere il controllo delle
operazioni e le operazioni stesse.
NOTA: In realtà RMI non è un ambiente middleware in quanto è fortemente dipendente dal
linguaggio, e un middleware non lo deve assolutamente essere.
I middleware lavorano per un utente che ha richiesto un servizio, quindi sono dei B2C (Business to
Consumer), in realtà i middleware sono dei B2B (Business to Business), in quanto danno
funzionalità ad altri che devono realizzare funzionalità, magari, poi per l'utente finale. I middleware
sono tipicamente pensati per la realizzazione di nuovi servizi: vi è un idea molto forte di servizi per
servizi (che poi verranno utilizzati magari dall'utente finale).
4
Ci si trovava in un mondo eterogeneo, in cui tutte le architetture vincenti di quel tempo avevano
curato una forte capacità di integrazione solo nell'ambito di quella architettura: questa cosa era vera
sia per la parte di distribuzione ma anche per la parte applicativa: presenza di soluzioni non
interoperabili tra loro.
Ciò non vuol dire che non vi era presente alcun tipo di soluzione: si potevano fare funzioni di
conversione custom (bridge), si poteva usare di un wrapper il quale permette di avvicinare il servizio
al mio modo di lavorare, o anche determinare un protocollo comune per far funzionare bene le cose.
Lo scenario è uno scenario molto ampio in cui ogni soluzione era studiata ad-hoc per fare avvenire
l'interoperabilità di certe funzionalità.
Reti di Calcolatori LM 125
5
Pertanto i middleware si cominciano a proporre e a diffondere per aggredire in modo sistematico il
problema: se avessi in mezzo qualcuno che si mettesse al di sotto delle applicazioni e fornisse tutta
una serie di funzionalità che rendono invisibile tutta la piattaforma locale e le sue specificità,
ovviamente lo sviluppo delle applicazioni (e del supporto) può essere molto semplificato: se
accettiamo il middleware come soluzione, possiamo quindi scrivere delle applicazioni interoperabili
e non specifiche per una singola architettura di soluzione.
Difatti, i middleware, come strato software, in alcuni casi situato anche molto in basso, permettono
di creare disaccoppiamento tra i livelli di sistema, con l'obbiettivo di fornire delle funzionalità
importanti per l'applicazione ed anche per il supporto (fornire comunicazione omogenea, riservare
banda, e poi andando a livello applicativo: un supporto per la persistenza, per progettare interfacce
utente, …); pertanto lo sviluppo della parte applicativa e del supporto risulta essere semplificato.
NOTA: più cose ci sono dentro un middleware, più quest'ultimo è ricco; più è ricco un middleware
più è attraente: l'utente non deve riprogettare niente perché può direttamente usarli dal middleware
stesso!
6
Di sotto si possono avere dei protocolli molto vari, di sotto ancora vari sistemi operativi....
dopodiché di sopra ci possono essere un po' di protocolli di comunicazione, al livello di sopra vi
sono le applicazioni (orizzontali, verticali ...): quello che c'è in mezzo è middleware.
I middleware hanno avuto successo perché han teso a dare una risposta vicino all'utenza:
1. ad esempio perché han potuto integrare sistemi legacy preesistenti e necessari alla logica del
contesto in cui si trovano.
126 Stefano Di Monte
2. Ha dato delle garanzie di durabilità: l'utente deve farci affidamento, difatti se è uno standard
meglio ancora: un middleware ha successo se ha una comunità di utilizzatori che si fida di lui e lo
utilizzano.
7
Il settore dei middleware è un settore in cui ci sono degli investimenti molto forti.
8
Un middleware come già detto sta in mezzo, e per far ciò deve avere funzionalità di due tipi:
1. cose che deve offrire:
� delle interfacce comuni: devono dare le API per la comunicazione (funzionalità utente)
� dei servizi di base già fatti, usabili direttamente (interfacce che consentono di ottenere
servizi a vari livelli non solo comunicazione).
2. cose che deve nascondere:
� di sicuro un middleware nasconde la distribuzione, il che vuol dire che le risorse
vengono viste come se fossero locali, e ciò viene fatto per ampliare la fascia di utenza.
� L'eterogeneità della risorsa: gli utilizzatori che utilizzano il middleware non si accorgono
dell'eterogeneità che vi è sotto.
9
In questa slide è presente una lista di possibili funzionalità che ci si possono aspettare da un
middleware (queste sono definizioni degli anni '90 poi incarnate nei diversi middleware):
• servizi di presentazione: servizi di interfaccia: prima cosa implementata dai middleware per
essere accettati
• computazione: intesa in termini molto applicativi: procedure di internazionalizzazione,
servizi che consentono di non dover intervenire sulle singole specificità locali... …
• servizi di persistenza
• funzioni di comunicazione
• controllo: quanti processi ci sono?, come sono generati?, come sono gestiti?, scheduling ..
• System Management: parte di gestione, di controllo delle risorse … …
Le ultime tre sono le funzionalità più vicine all'idea di gestione del sistema, le altre sono più a
livello applicativo.
Ovviamente, guardando middleware diversi si potrebbe avere una copertura diversa delle
funzionalità appena citate: alcuni potrebbero coprire solo la parte di gestione e tralasciare l'altra o
viceversa, o coprirle tutte, o coprirne solo alcune. Resta comunque che, più funzionalità copre un
middleware, più esso è ricco, ma più è ricco un middleware più overhead crea.
10
Prima divisione a livelli per una prima classificazione dei middleware.
Sicuramente quando si parla di middleware, ci situiamo al di sopra dell'hardware e del sistema
operativo, per arrivare alle applicazioni.
Reti di Calcolatori LM 127
Tra le applicazioni e il sistema operativo+l'hardware ci possono essere 4 livelli, non è detto che ci
siano tutti ma sicuramente i primi due (a partire dal basso) sono sempre presenti.
In generale:
0. Applicazione
1. Domain-specific Middleware Service
2. Common Middleware Services
3. Distribution Middleware
4. Host Infrastructure Middleware
5. Sistema Operativo
6. Hardware
In particolare, partendo dal basso:
11
Host Infrastructure Middleware
E' un infrastruttura che lavora sui singoli host locali e cerca di creare dove è possibile un interfaccia
di integrazione, la quale, tipicamente, è pensata per nascondere la distribuzione e facilitare la
comunicazione.
L'esempio nella slide è l'esempio di Java. Altro esempio potrebbe essere .NET.
12
Distribution Middleware
Comincia ad integrare la comunicazione disponibile e la visione a risorse, in un unico scenario che
dovrebbe consentire realmente di fare della programmazione distribuita (magari in alcuni casi
trasparente) senza occuparci troppo di ciò che c'è sotto.
In altri termini: in questo livello abbiamo delle risorse distribuite e molto spesso non ci accorgiamo
delle singole risorse, in quanto i middleware ci danno un modello di tale risorse.
Alcuni esempi sono: RPC, CORBA, DCOM
Questo livello ha un insieme di funzionalità di base per lavorare sulle risorse che non sono
necessariamente locali ma che sono disponibili sul sistema intero. Ci saranno quindi delle API (si
intende con API che sono invocabili senza essere ascrivibili ad un linguaggio di programmazione
specifico -difatti i middleware non sono monolinguaggio-), una serie di servizi disponibili (servizi
di nomi di discovery, …).
128 Stefano Di Monte
13
Common Middleware Services
Tale livello è un insieme di servizi specifici che vanno di più verso l'applicazione, come ad esempio
il naming service, l'interazione c/s per un ambiente come CORBA che funziona ad oggetti,
l'interazione pub/sub ossia un interazione 1-a-molti... …
La parte di Common è molto ampia: ci possono essere dei servizi ad eventi, dei servizi di streaming,
di tolleranza ai guasti, di gestione, di logging, di servizi, in generale, molto orizzontali in quanto
possono servire a tutte le applicazioni.
14
Domain-specific Middleware Service
Questi rappresentano i servizi di domini, ossia i servizi verticali.
Ad esempio, se supponessimo di studiare una comunità, questa potrebbe avere sicuramente degli
interessi specifici: i middleware potrebbero quindi, in modo verticale, realizzare dei servizi per un
settore specifico.
Naturalmente questo livello è presente solo negli ambienti molto ricchi, maturi dal punto di vista
dell'accettazione e da una grande diffusione circa l'utenza.
15
Questa è una classificazione dei middleware abbastanza accettata:
• i primi middleware (seminali, quindi di partenza e non veri e propri middleware) furono i
middleware con servizi a remoto: RPC/RMI.
• I primi middleware in termini di complessità e strategie semplici sono i MOM: middleware
orientati ai messaggi. La base di questi middleware è una comunicazione a scambio di
messaggi, sono middleware che hanno un costo inferiore e funzionalità minime (ad esempio,
banche che di notte vogliono scambiare delle informazioni).
• Distribuited Transaction Processing Monitor: Middleware di trattamento delle informazioni.
• Database Middleware: middleware di area data-base
• molto più importanti sono i Distributed Object Computing (DOC) Middleware. Questi
middleware sono basati sul meccanismo c/s.
• middleware adattativi & riflessivi
16
Quando si parla di middleware, bisogna sempre ricordare che il Web è di per se un middleware
veramente molto globale! Non c' è un sistema così ampio come il web di interconnessione di
contenuti e di servizi.
Sicuramente, il web ha molti domini di gestione perché caratterizzato dalla presenza di servizi
molto vari, moltissimi utenti partecipanti, banda totale molto elevata, grande capacità di
interconnessione... …
E sempre più va verso l'idea non solo di ricevere delle pagine, ma anche (parte utente) di poter
scrivere e leggere delle pagine.
Sicuramente ha un estrema diffusione, ed è un sistema legacy molto forte: i protocolli sono inoltre
davvero diventati molto importanti che nessuno li scardina più: e sono pensati maggiormente per
Reti di Calcolatori LM 129
l'erogazione di contenuti.
17 - 18
Tutta la parte di Java Enterprise è stata creata per gestire i server basati su Java integrati col Web.
Non viene esaminata in questo corso perché relativa unicamente ad unica e specifica macchina
(unico server inizialmente poi estese).
19
I middleware RPC come già detto non sono dei middleware veri perché pensati con un economia di
scala limitata: un po' di server e dei clienti niente di più: sono stati dei middleware seminali e
pionieri.
Difatti, non hanno strumenti di livello globale come:
• un sistema di nomi evoluto (non può essere usato direttamente nel globale!), se lo volessimo
dovremmo farlo noi mettendo down il sistema e riconfigurarlo da capo (situazione
disastrosa!);
• e soprattutto, si basa su di una logica (in particolare RMI e quasi tutti gli ambienti RPC)
molto statica, ossia che in generale (parlando di RPC), vi è un qualche linguaggio di
interfaccia (chiamiamolo IDL) che descrive il servizio e da questo, in modo precedente
all'esecuzione, sviluppiamo degli stub e dei proxy che consentono di superare i problemi di
eterogeneità: questo modo di procedere rende RPC sicuramente portabile su qualsiasi
tecnologia ma dà un limite di scalabilità molto forte: la staticità, il fatto cioè di prevedere
prima dell'esecuzione cosa potrebbe venirmi chiesto da qualcuno.
20
I due sistemi basti su basi di dati (sistemi quindi di persistenza) sono:
i TP-Monitor (Distribuited Transaction Processing Monitor).
L'idea di base è fare transazioni su sistemi di basi di dati eterogenei, e quindi avere un buon sistema
integrato non legato a nessun linguaggio ad-hoc.
21
Database middleware
In modo simile sistemi che vengono chiamati Database middleware, che sono quei sistemi il cui
obbiettivo è fare delle query su dati di database eterogenei: si va verso il data mining!
22
I MOM sono dei middleware molto snelli, quindi molto limitati con l'obiettivo di interconnettere dei
sistemi eterogenei attraverso lo scambio di messaggi.
I messaggi vengono scambiati in modi vari: sincroni, asincroni, punto-punto, di gruppo.
In sostanza ogni partecipante si tiene il suo scope, lavora nel suo ambito e di tanto in tanto scambia
queste informazioni.
C'è poco intervento sull'ambito finale mentre c'è molto intervento sull'operabilità dei messaggi, su
come i messaggi vengono scambiati ed ottimizzati.
Si hanno dei sistemi ad eventi, in cui molto spesso si ragiona per la persistenza.
Alcuni esempi sono JMS, MQSeries IBM, MSMQ Microsoft... …
23
130 Stefano Di Monte
OO e DOC Middleware
Gli altri �middleware fondamentali sono quelli ad oggetti, ossia con un meccanismo c/s. Questi di
base prevedono che nei servitori vi siano dei servizi incarnati in essi e dei clienti che li richiedono:
l'obbiettivo di tali middleware è quello di garantire che i servizi siano richiesti da tutti i clienti,
quindi massima integrazione di tutto.
I middleware ad oggetti si basano quindi fortemente su un modello c/s ma presentano variazioni.
L'open source diventa una linea guida molto importante: quello che si paga non è il middleware ma
il servizio offerto ed erogato: cosa fondamentale per accelerare la diffusione di middleware stessi.
24
Tutti i middleware hanno l'esigenza molto forte di rispondere a variazioni di funzionalità del sistema
senza permettere una configurazione del sistema (spegnere tutto e ripartire).
In questo filone, negli ultimi anni, è venuta l'idea di fare dei middleware adattivi e riflessivi!
NOTA:
• adattivo: vuol dire che ci si adatta alla situazione corrente dello scenario d'uso (necessità di
avere un altro server e quindi magari di attivarlo dinamicamente).
• riflessività: capacità di un componente di descrivere se stesso (ad esempio il proprio
stato... ...più in generale ciò che fa!). É importante avere dei componenti riflessivi perché,
supponendo di voler chiedere un servizio ma di non sapere dove si trova, bisognerà quindi
andare dal servizio e chiedere a se stesso dove si trova, come è fatto, come invocarlo, in
sostanza come è fatto. Essere un sistema riflessivo dà al sistema stesso un tempo di vita
molto più lungo.
25
Esistono molti tipi di middleware:
26
TINA-C: standard di comunicazione.
Rappresenta una fotografia molto recente delle esigenze che sono state determinate ma che sono
ancora aperte: è un modello un po' più complesso del c/s in cui si hanno più utenti che vogliono
comunicare e che hanno bisogno di servizi (un minimo elaborati), i quali vengono forniti dal
provider, ma quest'ultimi però, non forniscono la garanticità di comunicazione.
Reti di Calcolatori LM 131
In sostanza è un modello multi-parti: si hanno una serie di entità in cui alcuni si comportano come
erogatori dei servizi altri come utenti dei servizi.
Quindi in tale modello, la cosa importante, è che vengono tracciati un po' di più di relazioni c/s con,
ovviamente, anche una serie di entità che devono interagire con modelli economici.
27
Sicuramente ciò che si deve avere di base è la gestione delle risorse, le quali si dividono in risorse
con capacità di esecuzione (Computing Architecture) e risorse con capacità di gestione
(Management Architecture), quest'ultima fondamentale perché prevede una corretta erogazione del
servizio tanto per dirne una.
Affiancata a quest'ultima vi è l'Architettura di Servizio: anche a livello di telecomunicazione sempre
di più c'è l'idea di servizio, di modello di servizio manifestato con un modello di sottoscrizione e
che implica, molto spesso, una sessione di servizio che dura per qualche tempo.
Sulla parte di servizio c'è una forte focalizzazione!
Non si dimentichi anche l'architettura di rete.
28
Si studia TINA perché tale modello va in dettaglio su una serie di cose, ad esempio, come riusciamo
a contribuire (e si parla dell'architettura di servizio), tenendo conto delle diverse architetture.
In generale, ogni macchina che funziona ed è parte dell'architettura, propone quello che TINA
chiama: il proprio ambiente di computazione e comunicazione Native Computing Communication
Enviroment (NCCE) che in sostanza rappresenta il sistema operativo di una macchina che partecipa
all'architettura standardizzata TINA (macchine diverse con potenza di calcolo diverse, con capacità
di comunicazioni diverse, con architetture diverse... …).
L'idea quindi è quella di fornire sopra NCCE quello che TINA chiama Distributed Procesing
Environment (DPE), che non è altro che un ambiente unificato di servizio, capace di fornire tutte le
applicazioni di servizio delle quali ce n'è bisogno e che rappresenta un'astrazione e dà l'idea di
essere un middleware.
Il piano di sopra quindi fornisce un modello di comunicazione ed esecuzione che si basa su quello
che sta di sotto e ne astrae le specificità ed i dettagli.
Essendo uno standard, naturalmente, le applicazioni di TINA si sviluppano al di sopra del DPE: si
propone un' ambiente standardizzato che è un middleware globale capace di accogliere tutte le
132 Stefano Di Monte
architetture di cui ce n'è bisogno.
Le applicazioni di TINA sono delle applicazioni che rispondono all'architettura: i puntini
rappresentano le entità di base sulle quali costruiamo queste applicazioni.
Si noti inoltre che c'è un forte accento anche sull'integrazione delle applicazioni anche con TINA,
quindi di servizi legacy, ossia servizi già sviluppati e già presenti sul mercato.
Lo scopo di TINA è quindi quello di integrare tutti i servizi esistenti, difatti c'è un grosso problema
da parte dei sistemi telefonici di impegnare la banda disponibile che si può solo risolvere se si hanno
servizi disponibile forniti da qualcuno e pagati da qualcuno.
29
Il modello architetturale è abbastanza comprensibile: quando voglio costruire qualcosa con TINA lo
faccio al di sopra del DPE.
Il modello di architettura di costruzione delle applicazioni prevede di base, naturalmente, dei
servizi, i quali sono le entità capaci di fruire le applicazioni che sono necessarie.
In realtà i servizi saranno basati su una serie di entità che TINA chiama risorse, utilizzate per la
corretta fruizione del servizio stesso (risorse potrebbero essere ad esempio una capacità di
memorizzazione di dati in varie forme, una capacità di calcolo significativa … …).
Sicuramente ci sono anche una serie di entità che se ne stanno lì a livello applicativo, e che siedono
sopra al DPE il quale quindi, è molto somigliante ad un middleware (guarda figura in slide 31).
Tutte queste entità risentono in qualche modo dei livelli sottostanti e della localizzazione delle entità
che stanno sotto: prendendo in considerazione una risorsa, questa potrebbe avere visibilità o non
visibilità di ciò che c'è sotto.
Il caso della non-visibilità è il caso della trasparenza: tutte le entità che sono di sopra al middleware
non sono in nessun modo legate alla localizzazione fisica delle macchine di supporto: nel distribuito
rappresenta una delle linee guide per la progettazioni di buoni sistemi.
30
Di base, in TINA, si adotta la visione trasparente: non mi accorgo se una certa entità è supportata su
di un nodo o su di un altro.
Il vantaggio di questo modo di fare le cose è che, naturalmente, si possono avere delle risorse
logiche supportate da più risorse fisiche contemporaneamente (con conseguente ottenimento ad
esempio, di fault tolerance ecc ecc).
Reti di Calcolatori LM 133
31
Nonostante ciò, è sempre presente anche una visione non trasparente: per cui io posso accorgermi se
una certa risorsa è mappata in una certa località.
Tina con visione trasparente Tina con architettura non trasparente
Vi sono questi due punti di vista perché, la parte della non trasparenza è sicuramente un punto di
vista di maggior dettaglio, ma anche che ci consente di avere una visibilità che in alcuni casi è
necessaria: difatti se volessimo fare un servizio che gestisca ad esempio in modo interno la
replicazione su dei nodi, è evidente che dobbiamo sapere dove sono localizzate le risorse, quindi per
qualsiasi cosa che preveda la conoscenza di dove sono localizzate le risorse una visione non
trasparente è di fondamentale importanza.
Gli standard di telecomunicazioni incorporano questa visione, a differenza degli standard
informatici che ce l'hanno molto di meno!
32
Tornando ai middleware...
Il progetto di un middleware è tanto più complesso quanto più vengono considerate situazioni in cui
si gestisce uno scenario tanto più ampio: la presenza di problemi è direttamente proporzionale alla
grandezza (in termini di ampiezza) dello scenario.
Difatti un middleware deve fornire dei servizi a dei clienti che li vogliono utilizzare o che vogliono
creare e quindi fornire altri servizi.
I middleware hanno un grosso problema di scalabilità!
Perché chiaramente non si vuole fare un applicazione c/s ma si vuole mettere a disposizione di una
serie di clienti molte applicazioni, molti servizi, i quali quindi devono essere molti e dinamicamente
modificabili in numero.
Vi sono anche altri problemi indotti:
• molto spesso ci sono problemi di sicurezza: autorizzazioni nell'accedere alla risorse stesse,
transazioni collegate in delle sequenze che devono essere eseguite tutte o niente.... Tutto ciò
richiede un po' di strutture di sotto, che potrebbero essere chiamati interception: meccanismi
134 Stefano Di Monte
indiretti per la gestione, con un overhead purtroppo rilevante da minimizzare.
• l'aggiunta di funzionalità introdotte da un middleware introduce comunque overhead. Va in
questo senso anche tutta la parte di controllo e gestione dei servizi, i quali devono essere ben
gestiti (cosa stiamo facendo, come stiamo lavorando, identificare i colli di bottiglia).
• Sempre più negli ultimi anni, gli utenti vogliono accedere ai servizi in modo non
convenzionale, il che vuol dire ad esempio attraverso dei dispositivi mobili (cellulari) che
consentono quindi di accedere a dei servizi ma con dei vincoli molto forti di risorse, di
energia … … : difatti i middleware incorporano del supporto per adattarsi continuamente
alla situazione corrente.
32
I MOM sono dei middleware sicuramente molto chiari in termini di paradigma: si basano sullo
scambio di messaggi e amen!, ma che hanno anche un impostazione molto precisa: tendono a dare
una soluzione alla esigenza di comunicazione fra parti molto autonomi ed indipendenti con una
soluzione di basso costo.
I MOM sono i primi sistemi affermatisi per collegare sistemi molto diversi tra loro: facevano da
collante quindi tra sistemi molto eterogenei mantenendo l'autonomia di tali sistemi.
Dal punto di vista economico, l'avere un basso costo è molto importante.
I MOM sono pertanto abbastanza statici!
I MOM sono dei middleware di standardizzazione molto forte del messaggio che viene scambiato:
in questo modo, nonostante si lavori con architetture eterogenee, si riesce ad ottenere un formato
comune per comunicare dei dati.
Una caratteristica che è dietro ai MOM è il disaccoppiamento in tempo ed in spazio, in quanto le
entità che vogliono comunicare potrebbero essere anche non presenti contemporaneamente (il che
va contro il modello c/s).
Molto spesso i messaggi dovrebbero essere persistenti: dato che non c'è accoppiamento tra le parti, i
messaggi devono quindi essere mantenuti magari anche con una certa qualità se possibile (e ciò
deve avvenire sia nel caso di mittente che invia e va via, e sia nel caso di destinatario che riceve ma
non è ancora presente).
Come già accennato, i MOM, tendono ad avere una configurazione statica (derivante dal loro basso
costo); difatti in questi middleware sono molto chiari i collegamenti di comunicazione tra le varie
parti, e non cambiamo durante l'esecuzione! Se dovesse succedere che si voglia cambiare qualcosa,
si spegne il tutto e si riconfigura da capo.
Con dei sistemi statici, tipicamente, non c'è molto bisogno di sistemi di nomi...
In questo filone è di particolare importanza il contributo di JMS. Quest'ultima è una specifica di
standardizzazione dei messaggi in Java, che però possono essere mappati in ambienti diversi.
Ultimamente tutti i MOM hanno adottato questo standard perché molto affermatosi e non
richiedente dal punto vista della scelta (anche se non volessimo lavorare in Java non c'è alcun
problema: non siamo legati ad un linguaggio specifico quale, in questo caso, Java!).
34
<<Come si fa un middleware?>>
Reti di Calcolatori LM 135
Una prima visione che può venire in mente dal punto di vista architetturale, è un sistema
centralizzato. Ossia il MOM esiste da qualche parte come server (magari replicato) al quale i vari
richiedenti effettuano le proprie richieste.
Questa è una visione al quanto tradizionale, che consente anche qualità diverse.
Un altra possibilità è quella in cui non vi è un ruolo centralizzato, ma in cui tutti i nodi partecipanti
hanno una sorta di parte di middleware MOM, che chiaramente sono in grado di interagire tra di
loro. Modello più peer2peer in cui non vi è un nodo centralizzato che dirime e controlla il tutto. In
questo modello è importante che le funzioni siano snelle e che siano capaci di impegnare poche
risorse sui nodi corrispondenti (principio di minima intrusione): da questo punto di vista i MOM
vanno nella direzione giusta perché hanno pochissime funzionalità (tanto da potersi affibbiare il
nomignolo di “middleware a colla” o “glue middleware”). I MOM sono difatti a scarsa funzionalità!
In generale, e vale per entrambi i modelli, un nodo deve poter comunicare con gli altri nodi
mandando messaggi e ricevendo messaggi: ogni singolo nodo deve avere la capacità di prendere
messaggi e portarli verso i destinatari nel caso voglia comunicare con questi.
NOTA: i messaggi vengono scambiati in una sessione, quindi in numero elevato e non un messaggio
solo per tutta l'applicazione!
In sostanza quello che è necessario, è avere delle funzionalità di routing, questo perché il messaggio
potrebbe essere incorporato con altri messaggi e/o avere bisogno di intermediari per raggiungere i
destinatari.
Naturalmente i nodi possono essere eterogenei in quanto a S.O. ecc ecc e quindi nel traferire i dati si
deve avere del trattamento dei dati stessi, con conseguente trasformazione degli stessi per superare i
problemi di eterogeneità.
35
Normalmente in un MOM un utente ha delle API con cui può
chiedere di inviare messaggi e richiedere messaggi: tali API
potrebbero essere anche meccanismi c/s (potrei fare delle send e
delle receive) anche se poi l'obiettivo finale è essere asincrono
nello scambio dei messaggi.
36
In generale, tutti i MOM sono basati su delle code che sono statiche e predefinite.
Il sistema viene quindi configurato alla partenza: ad esempio, si configura che il nodo n1 dovrà
comunicare con il nodo n2 e quindi sul nodo n1 ci sarà una coda di uscita mentre sul nodo n2 ci sarà
una coda di ingresso. Le due code sono corrispondenti e tipicamente, il sistema deve far transitare i
messaggi dalla coda di uscita del nodo che invia il/i messaggio/i alla coda di ingresso del nodo che
136 Stefano Di Monte
riceve.
I messaggi possono essere punto-punto o anche multicast: in quest'ultimo caso ad una coda di
ingresso possono corrispondere molte code di uscita.
In sistemi come questo quindi non c'è il bisogno di avere un sistema di nomi, in quanto le code
rappresentano già quello che spesso viene chiamato, overlay network: è una rete a livello applicativo
di collegamento tra le entità.
Pertanto, le code rappresentano quindi il sistema di nomi: quando mando un messaggio su una coda
di uscita il sistema provvederà a far arrivare il tutto sulla coda corrispondente di ingresso.
37
I problemi principali quindi sono due:
• fare del routing: ed a questo intervengono i Relay. Le code tipicamente sono gestite nei
MOM (non sempre vero) da delle entità che si chiamano per l'appunto Relay: entità attive
che prendono i messaggi che sono su una coda e li portano fino a destinazione dove ci sarà
altrettanto un altro Relay.
• Trattare i dati, trasformandoli all'occorrente quando si passa da un ambiente all'altro:
tipicamente nell'ambito dei MOM ci sono dei broker (Message Broker), i quali sono i
deputati a lavorare sulle rappresentazioni diverse.
NOTA: Message Broker e Relay lavorano in maniera mutalmente esclusiva.
NOTA: Il basso costo dei MOM, sia in termini economici che di overhead, ne ha favorito la
diffusione!
38
Le due soluzioni ampiamente accettate e distribuite sono MQSeries di IBM e la MSMQ di
Microsoft.
In realtà questi sistemi sicuramente sono middleware MOM ma che risentono dello scenario di
diffusione: MQSeries, che è quello più diffuso, in realtà è un MOM ambientato nell'ambito di un
middleware che si chiama WebSphere: si realizza quindi come componente in WebSphere.
Guardando come sono fatte le cose, in generale MQSeries si comporta come detto nelle slide
precedenti:
La determinazione dei partecipanti, dei messaggi scambiati, è fatta in maniera statica: e per questo
tale sistema mette a disposizione una serie di API per fare delle send e delle receive che qui sono
delle API RPC. Lo scambio di messaggi è punto-punto ma anche multicast.
Vengono definite le code, con dei queue menager che le gestiscono. Quest'ultimi si occupano di
garantire che associate all'utente ci siano tutte le code necessarie per la comunicazione che è stata
Reti di Calcolatori LM 137
stabilita in configurazione.
39
In sostanza, il sistema, che non deve essere necessariamente residente sulle macchine clienti ma in
realtà su macchine diverse, realizza delle code in base alle esigenze del cliente, il quale comunicherà
attraverso RPC (stub sui clienti e proxy sui servitori).
Le code sono poi gestite da entità che in generale abbiamo chiamato relay ma che in questo sistema
sono chiamati MCA (Message Channel Agent): prendono la coda e la gestiscono portando i
messaggi dal mittente al destinatario.
Ovviamente, a questo punto, per ogni singola macchina cliente ci devono essere delle macchine di
gestione, non necessariamente una, capaci di sopportare le code e di traferire le informazioni
dall'una coda all'altra.
NOTA: si ricordi sempre la staticità di tali sistemi!
40
Dal punto di vista della gestione della rappresentazione e trasformazione necessari dei dati,
MQSeries ha un broker che è un entità capace di lavorare sulle code e di operare opportune funzioni
di trasformazione dei dati se necessarie quando tali dati passano dal mittente al destinatario.
Naturalmente se il messaggio è un multicast, il dato dovrà essere trasformato dal formato del
mittente ai formati diversi dei corrispondenti destinatari.
Esaminando altre proposte, ad esempio quella di Microsoft, si avrebbe esattamente la stessa
organizzazione.
Riassumendo brevemente:
I MOM sono middleware molto semplici, con funzionalità limitate perché presente un'
138 Stefano Di Monte
organizzazione statica, quindi non si può esportare al filone dei middleware dinamici in cui si vuole
poter aggiungere servizi durante l'esecuzione.
41
Questo rappresenta il filone che più ci interessa: Middleware OO e DOC.
Questi middleware nascono con l'idea che la maggior parte dei componenti possono essere standard
e che il software possa essere visibile in sorgente (vero anche in middleware proprietari come
Microsoft), questo perché alla base di questi middleware c'è l'idea che tutto quello che è disponibile
all'interno degli ambienti sia richiedibile come servizio da parte di tutti: idea molto pervasiva!
Sicuramente, i middleware ad oggetti han lavorato molto sulla definizione di interfaccia: si sono
fatte delle standardizzazioni molto precise, e di base l'idea è stata: prima di invocare un servizio si
deve avere un idea molto precisa di quel servizio, si deve avere quindi un interfaccia molto chiara e
ben definita di quel servizio stesso.
Difatti l'interfaccia è il velivolo attraverso il quale è possibile ottenere l'erogazione e lo svolgimento
di un determinato servizio.
C'è un idea molto precisa di località, intendendo per quest'ultima un ambito in cui i servizi sono
disponibili e possono essere richiesti.
La prima idea che salta alla mente è avere una sorta di sistema a bus dei servizi, i quali possono
essere messi a disposizione a chiunque acceda a quel bus: idea molto forte di condivisione, che si
scontra con l'idea di avere dei bus diversi con servizi diversi, ma che idealmente potrebbero
collegarsi l'uno all'altro per far lavorare tutti con tutti: massima apertura dei servizi stessi!
42
Quindi oggetti che hanno interfaccia e che sono legati a concetti di tipo.
Sicuramente i servizi sono incarnati in operazioni o metodi: un oggetto ha delle operazioni che sono
raggruppate nell' interfaccia, tali operazioni sono dei servizi che possono essere chiesti; la fornitura
del servizio quindi avviene perché viene richiesta un operazione dell'interfaccia dell'oggetto che è
stata messa a disposizione.
Quando si parla di middleware non si parla di architettura vera di soluzione: per i MOM, ad
esempio, si possono avere soluzioni molto peer2peer, o soluzioni molto centralizzate in cui alcuni
nodi sono delegati nello svolgere funzionalità di supporto. Medesima cosa rispettivamente anche per
CORBA (che potrebbe avere realizzazioni centralizzate o p2p) e per DCOM (che è p2p).
43
Alcuni modelli (strategie di soluzioni) che consentono di capire bene come si lavora con sistemi ad
oggetti nel distribuito, approccio di Volter2002, che dividono le funzionalità di base:
• Basic Remoting: parte in cui cominciamo l'interazione remota
• Asynchronous Communication: quella parte dedicata al modo di fare comunicazione, in
particolare in modo asincrono
Reti di Calcolatori LM 139
• Resource and service management: una parte di gestione delle risorse
• Additional Services: discorsi addizionali
• Quality of Service: la parte di qualità del servizio
44 – 45 – 46
Basic Remoting Pattern
La cosa fondamentale che un sistema che lavora ad oggetti deve avere per fornire servizi in remoto è
la presenza di riferimenti remoti a questi stessi oggetti: Remote Object, tutti i sistemi devono averlo
al fine di poter chiedere un metodo ad un altro nodo che si trova da un'altra parte.
Riferire un Remote Object vuol dire poter dare una semantica: l'ID di un Remote Object potrebbe
dipendere dall'interfaccia che lo specifica, e quindi cambiare con essa: pertanto, il contratto del
cliente non è con l'oggetto bensì con l' interfaccia che specifica quell' oggetto stesso.
Quindi Remote Object non è un concetto associato all'oggetto remoto specifico ma è un riferimento
remoto, quindi potrebbe essere anche riferito ad un oggetto diverso ma non come tipo (in quanto con
quest'ultimo termine si intende per l'appunto interfaccia, che dovrà essere sempre la stessa -d'altra
parte un oggetto potrebbe avere anche più interfacce-).
47 – 48
Trasparenza:
Il Remote Object è realizzato con un proxy lato cliente ed uno stub lato servitore : l'accesso ai
remote object è dato tramite questi intermediari locali, per l'appunto tramite i proxy.
I due proxy sono prodotti automaticamente a partire dall'interfaccia, il che prevede che devono
essere noti staticamente, così come l'interfaccia dev'essere nota staticamente ed anche il legame con
l'interfaccia dev'essere statica: vincolo molto forte: posso chiedere dei servizi solo se questi sono
stati definiti staticamente.
In realtà questo modello dice che devono essere presenti delle entità, questi proxy e stub, che
potrebbero essere anche prodotti dinamicamente!
Pertanto se un server implementa molte interfacce, si può avere una proliferazione di molti proxy e
stub: con 50 interfacce ci vogliono 50 proxy/stub.
Bisogna essere scalabili!
140 Stefano Di Monte
49
Non trasparenza:
ObjectID: in alcuni casi è molto importante che il cliente sappia chi c'è dall'altra parte: quindi non
trasparenza.
Un cliente deve poter dire, ad esempio, che vuole esattamente l'oggetto 4711: questo è molto
importante perché se quell'oggetto ha uno stato, allora questo stato è importante che sia mantenuto
in quanto le operazioni dovranno essere sempre eseguite dal servant di quell'oggetto.
In alcuni casi quindi non abbiamo la possibilità di avere una visione trasparente dell'oggetto che ci
serve, non abbiamo quindi bisogno di un Remote Object, il che potrebbe essere idealizzato nel
cliente associando al proxy il numerino, quindi l'ID (che sarà quindi un nome unico), dell'oggetto
specifico.
50 – 51 - 52
Supponiamo di chiedere un metodo ad un qualche riferimento remoto ed ovviamente abbiamo dei
parametri nella richiesta.
Tali parametri possono essere di vario tipo: primitivi, quindi che passano direttamente per
copia/valore, oppure parametri che fanno riferimento a degli oggetti specifici in un sistema, che
quindi sono fissi nel sistema, nel senso che non si muovono dal sistema stesso e che devono essere
quindi riferiti da remoto dall'altra parte (quindi con uno stub ed un proxy); pertanto la possibilità di
passare un oggetto per riferimento come parametro rappresenta l'ObjRef.
Passaggio per riferimento
Reti di Calcolatori LM 141
Passaggio by value
Remoting Error
Quindi due possibilità: parametri per valore e parametri per riferimento!
NOTA: se nel passaggio per riferimento dovesse accadere qualche errore, tale errore dovrà essere
gestito dalla parte cliente o dalla parte servitore.
53
Naming Support
Si ha spesso uno scenario in cui si hanno molti clienti e molti servitori. Chiaramente, quindi,
quando si chiedono delle azioni specifiche, è necessario trovare i servitori di cui abbiamo bisogno
tramite delle entità di supporto: sistema di nomi!
In sostanza la parte di naming ci consente di capire quali sono, dove stanno (in termini di
localizzazione) e di ritrovare le entità di cui abbiamo bisogno durante l'esecuzione, a fronte di una
non conoscenza.
I sistemi di nomi sono fondamentali e qualificano i DOC che stiamo usando.
142 Stefano Di Monte
54
Singleton
Oggetti di cui vi è un unica istanza nel sistema e si garantisce che il servizio incarnato viene attivato
una sola volta: entità tipiche di un'applicazione attivate/eseguite una volta sola, ed un oggetto solo
tipicamente le incarna nel sistema. Servono nel sistema ad esempio per gestire funzionalità quali il
sistema di nomi, per interpretare i parametri di configurazione e così via.
55
Server Application
Un insieme di funzioni iniziali che rappresentano tutte le esigenze dei servitori che devono essere
tipicamente eseguite una volta sola per sistemare tutta la parte di servizio presente nei sistemi: tutta
la parte di attivazione degli oggetti iniziali e tutte le cose necessarie in modo preliminare per
l'applicazione.
56
Holder
E' un contenitore necessario per effettuare l'adattamento della semantica dei linguaggi alla
semantica standard che noi utilizziamo. Ad esempio, ci sono dei linguaggi che hanno dei parametri
di in e di out ed altri che hanno solo dei parametri di in.
Naturalmente sull' holder vengono effettuate operazioni di read e write.
57
Asynchronous Communication Pattern
Molto interessanti sono le modalità di richiesta delle operazioni.
Tutti i sistemi Object Oriented sono tipicamente sincroni bloccanti: il cliente fa la richiesta ed
aspetta finché l'altro non gli da la risposta.
In alcuni casi il middleware ha tenuto questa come unico modo di comunicare. In seguito vennero
apportate delle variazioni: le invocazioni possono anche non essere sincrone bensì asincrone: non si
ha risultato, oppure sincrone non bloccanti: ho il risultato ma non devo aspettarlo.
Alcune forme asincrone sono:
-) Fire & Forget
-) Catch & Return
Alcune forme sincrone non bloccanti sono:
-) Poll Object
-) Result CallBack
58
Fire & Forget
E' la cosa più asincrona che esista: un cliente vuole fare una richiesta ma non vuole un risultato e
Reti di Calcolatori LM 143
vuole avere un tempo di attesa il più possibile limitato, quindi banalmente fa un invocazione locale
(quindi ad un proxy), dopodiché vuole disinteressarsi completamente del tutto avendo, oltretutto, un
tempo di attesa assolutamente limitato. Consegna la richiesta al proxy e quasi immediatamente ha
un ritorno. Sicuramente per avere una Fire & Forget bisogna che tutti i parametri della richiesta
siano d'ingresso!
Vi è comunque un problema di interazione: il cliente invia qualcosa al proxy, che potrebbe avere una
coda e quindi conseguentemente smisterebbe le richieste in base a questa; se la coda fosse piena, o
perdiamo le richieste o si aspetta finché la coda stessa non si svuoti.
Tipicamente, le Fire & Forget vengono implementate a livello di middleware come asincrone
bloccanti, quindi finché il proxy non da risposta si aspetta (a livello locale).
Lavorare Fire & Forget non dice niente della catena distribuita, quindi di come si va dall'altra parte,
sullo stub, che poi andrà all'oggetto e quindi all'operazione: abbiamo perso tutto il controllo su
questo. Abbiamo dei vantaggi sui tempi di risposta ma altresì dei problemi molto forti sulla
semantica: si lavora best-effort.
59
Cath & Return
Un po' più garantista è il modello Cath & Return: si sottopone all'attesa della parte di
comunicazione, è sempre asincrona però in questo caso il risultato di sblocco arriva dopo che il
messaggio è stato correttamente portato dall'altra parte ed ha portato all'invocazione sull'oggetto
corrispondente; a questo punto parte un messaggio di risposta che eventualmente sblocca l'attesa del
cliente leggermente più lunga: a livello locale, quindi posso accorgermi se la cosa è andata dall'altra
parte, dopodiché mi disinteresso di ciò che fa il servitore e di come è andata l'operazione!
60
Presenti in quasi tutti i sistemi sono le forme sincrone non bloccanti: basate su degli oggetti
intermedi che possono essere del tipo poll o del tipo call-back.
Poll Object
Funzionamento: un cliente fa una richiesta, che quindi manifesta la sua esigenza di avere un
operazione ed in più da un indicazione di un oggetto di poll. Quest'ultimo è un oggetto dalla parte
144 Stefano Di Monte
cliente destinato a contenere il risultato: il cliente è quindi disaccoppiato dal risultato
dell'operazione.
Il cliente quindi si può in parte disinteressare dell'operazione stessa e delega a qualcun altro del
dovere del contenimento del risultato; pertanto, quando ne avrà bisogno, il cliente può andare a
prendere il risultato (con delle get e delle set) magari essendosi prima accertato che il risultato ci sia
con un operazione di attributo (resAvailable).
Questo modello richiede quindi che il sistema che c'è di sotto si accorga dell'esistenza di un poll
object e di mandare, con una funzione di sistema, il risultato a quest'ultimo.
Non è necessario che il servitore debba essere consapevole dell'esistenza del poll Object: il modo in
cui si lavora, se sincrono bloccante o non bloccante o asincrono, deve essere schermato dalla parte
del servitore, è solo una decisione del cliente, il servitore deve solo fornire il risultato alla parte di
supporto che provvederà a dare il risultato a chi di dovere.
L'oggetto poll potrebbe essere anche definito dal supporto in quanto la logica di tale oggetto è
standardizzata, è sempre la stessa.
<<Cosa succede se il cliente fa più richieste allo stesso oggetto poll?>>
Sicuramente ci sarà una coda al poll object, cosicché le richieste verranno messe in coda, e quando
andrò a fare delle get, per distinguere le varie risposte, ci sarà sicuramente un ID! Altrimenti non
dovremmo prevedere la possibilità di fare richieste multiple: solo una alla volta.
61
CallBack
Vi è un altro oggetto dalla parte del cliente, CallBack Object, deputato a ricevere il risultato e che
non prevede nessun tipo d'iterazione col cliente: il cliente potrebbe effettuare una richiesta,
dopodiché si disinteressa completamente perché la gestione del risultato (attraverso il “metodo di
callback”) viene effettuata dall'oggetto di callback.
Il metodo di callback viene ovviamente scritto dal cliente!
<<cosa succede se un cliente fa più metodi di callback con lo stesso oggetto di callback?>>
E' il cliente che decide come gestire le richieste, che definisce la politica di gestione, in quanto è
proprio lui a creare il metodo di callback.
Reti di Calcolatori LM 145
62
Resource and Service Management
Supponiamo sempre di avere un servitore da qualche parte, dei servizi su uno o più nodi servitori e
dei clienti dall'altra parte: il problema fondamentale che sorge è quello della gestione delle risorse:
<<quando (e se) i servitori devono ritirarsi?>>
Difatti mantenere i servitori sempre attivi sicuramente facilita le cose, ma consuma inutilmente
delle risorse.
63
Preconfigured Instances
Tutte le istanze di servizio che sono necessarie per l'applicazione sono create all'inizio
dell'applicazione, e durano per tutta la durata dell'applicazione.
É una politica molto semplice, costituita tipicamente da un programma iniziale che crea i servitori
inizialmente, gli da tutte le risorse che gli sono necessarie e li mantiene finché qualcuno non spegne
tutto il sistema, in questo momento verrà fatta una distruzione di tutti questi servitori.
Questo modello non ha gestione: una volta attivati i servitori questo risulteranno in vita per tutta la
durata dell'applicazione e se vorrò usufruire dei loro servizi so che saranno disponibili fino allo
spegnimento totale: il servitore opera tra la create e la destroy.
Così facendo però si ha una semplicità dal punto di vista del cliente ma si impegnano molte risorse
dalla parte del servitore, in quanto sono risorse statiche.
64
On-Demand Activation
Alcuni servizi potrebbero essere utili solo per alcune fasi dell'applicazione e non avrebbe senso
quindi mantenerli vivi per tutta la durata dell'applicazione stessa.
Potrebbero essere attivati ad esempio su richiesta stimolata dal cliente: le istanze dell'oggetto remoto
non sono preconfigurate ma invece sono esistenti ed attivi solo quando ce n'è bisogno, ossia by-
need!
La prima invocazione quindi ha un effetto di creazione (tempi più allungati per la fruizione del
servizio richiesto) nei confronti del servitore, dopodiché il servitore risulterebbe disponibile anche
per ulteriori richieste.
In questo caso si ha che le risorse del servitore sono impegnate solamente quando c'è effettivamente
146 Stefano Di Monte
bisogno e rimangono attive finché, per l'appunto, ce n'è bisogno.
L'attivazione su richiesta è quindi, rinfrescata dalle invocazioni, perciò se non arrivano richieste dal
servitore, quel servitore può essere distrutto.
65
Single-Call Activation
E' qualcosa di un po' più reattivo, in cui gli oggetti non siano attivi ma che vengano attivati su
bisogno solamente quando c'è una richiesta: ogni volta che il cliente fa una richiesta, questa ha
l'effetto di creare il servitore, di attuare l'operazione ed immediatamente di distruggere il servitore e
l'istanza che si stava considerando.
Così facendo si carica veramente poco, dal punto di vista delle risorse, il servitore perché gli oggetti
remoti sono attivi solamente per la durata dell'operazione.
In questo modo si ha anche una discreta separazione dei diversi clienti: ogni cliente difatti, ha il suo
servitore personale creato su sua necessità, solamente per quell'operazione specifica.
Vi sono ovviamente, due controindicazioni:
• ogni invocazione è sicuramente appesantita in termini di tempo dalla fase di creazione: sarà
importante rendere efficienti le operazioni di creazione dei servitori.
• Vi è altresì un piccolo problema dal punto di vista dello stato: con questo modo di lavorare si
fa fatica a mantenere uno stato dalla parte del servitore, in quanto ogni volta il servitore
viene create ex-novo.
Delle soluzione per ovviare a ciò, tenendo conto che lo schema di attivazione è il presente,
potrebbero essere:
� far tenere tutto lo stato al cliente, il che appesantirebbe però il cliente stesso ma
alleggerirebbe il servitore;
� assumere che quando si crea e si distrugge qualcosa, si deve, in contemporanea, salvare
Reti di Calcolatori LM 147
lo stato dell'interazione che non è più legato al server che è stato attivato bensì al
servizio, e che dovrà essere ritrovato perché il cliente propone una qualche modalità di
identificazione dell'interazione.
Chiaramente, questo meccanismo (single call activation) è particolarmente comodo se non c'è stato!
66
Istance Polling
In modo simile, per evitare di avere la distruzione delle attività (quasi) appena queste vengono
create, si può pensare di lavorare con il pool di istanze precreate, quindi disponibili dalla parte del
servitore: quando arriva una richiesta, se c'è un'istanza libera questa viene associata alla richiesta.
Così facendo non si paga più il costo di interazione, ma c'è la possibilità di ottenere direttamente
l'istanza che alla fine , non viene distrutta bensì riconsegnata al pool.
Quindi, supponiamo ad esempio un oggetto con attive in media 6 istanze; a questo punto si crea un
pool di 6 istanze in modo tale che, queste istanze, che sono disponibili, vengono agganciate alle
richieste del cliente ed ogni volta, dopo che il risultato è stato dato, vengono sganciate.
Questo modo di lavorare è stato abbastanza usato, non risponde al discorso dello stato, ma risponde
a limitare la durata delle operazioni perché si paga molto di meno un aggancio dell'istanza anziché
la creazione ex novo e la conseguente distruzione (come nel caso visto precedentemente).
<<Quanto dev'essere numeroso il pool, e cosa succede nel caso in cui sia stato sbagliato il
dimensionamento?>>
Se avessimo una stima del traffico, potremmo capire qual'è il numero medio per la valutazione del
numero di istanze; ovviamente se per caso il sistema viene ingolfato di richieste, ci si potrebbe
trovare nella soluzione in cui chi arriva non trova istanze disponibili e quindi gli toccherà aspettare,
o se avessi una gestione più dinamica e quindi potrei generarne una ed aggiungerla al pool che, da
questo momento in poi, sarà accresciuto di una istanza (la quale, se poi in seguito non venisse
richiesta potrebbe essere distrutta): tutte politiche decise dal sistema di pool.
L'utente interviene in questi casi dicendo qual'è la sua stima del valor medio, dopodiché il sistema
decide la sua politica man mano che le cose vanno avanti.
Anche qui lo stato potrebbe essere consegnato a qualcuno, cliente o servitore che sia.
67
Client Activation
148 Stefano Di Monte
Tutte le cose fin qui viste lasciano la decisione di come gestire lo scheduling delle attività di
attivazione dalla parte del servitore.
In realtà anche il cliente potrebbe incidere in modo più pesante: così facendo ci troviamo in
situazioni in cui l'attivazione è su responsabilità del cliente: c'è un API del cliente che consente di
attivare un istanza dall'altra parte, quindi il cliente non fa solo delle invocazioni bensì anche delle
operazioni di creazione di istanze. Così facendo il cliente ha il controllo dell'attivazione dei servitori
dalla parte del servizio, e quindi può decidere una certa istanza che sarà, da quel momento in poi, a
disposizione di quel cliente: tutte le invocazioni batteranno su quell'istanza.
Questo modo di lavorare semplifica enormemente l'interazione a stato che sarà mantenuto
nell'istanza che il cliente ha creato e sarà disponibile solo per quel cliente (non ci sono problemi di
contesa tra i clienti in quanto ognuno di loro avrà la propria istanza). Così facendo, lasciando la
responsabilità al cliente, è vero che semplifichiamo la gestione dello stato ma complichiamo
l'interfaccia del cliente stesso.
Per quanto riguarda il ciclo di vita, in questo lucido compare il termine Factory: non è un
componente di linguaggio, è un entità capace di creare delle altre entità di tipo diverso, difatti non è
una classe in quanto, quest'ultima, è un componente di linguaggio che può creare entità tutte dello
stesso tipo: quindi basterebbe una factory per tutti i servitori in servizio per quel sistema (nel caso
delle classi ci vorrebbero tante classi quanti sono i servitori).
68
Passivation
Normalmente nei sistemi in cui c'è delega sul cliente, tipicamente il servitore introduce un
meccanismo di risparmio garantito: in questi casi il server ha lo strumento della passivazione, ossia
che può distruggere l'oggetto creato dal cliente.
Ha però un vincolo, quindi un contratto di gestione: deve mettere lo stato di quel servitore da
qualche parte, in una qualche memoria persistente in modo tale che questa memoria possa essere
ritrovata quando ci sarà bisogno di quel servitore: mantenimento totale dello stato, anche delle
identità (degli id) del servitore (se il servitore prima della passivazione aveva l'id 4711 dovrà essere
riattivato con lo stesso id).
Reti di Calcolatori LM 149
In sostanza la passivazione è: prendere lo stato, serializzarlo e portarlo da qualche parte!
NOTA: se si parla si passivazione si deve necessariamente parlare di riattivazione nel caso ce ne sia
ancora bisogno, al fine di poter rispondere a successive invoke.
69
Lease
Normalmente in questi sistemi se c'è invocazione ed attivazione su base cliente, tipicamente il
cliente interviene nel sistema facendo delle invocazioni: se invoca un oggetto remoto, quest'ultimo
rimane in memoria e non viene passivato perché utilizzato.
Si supponga che, per una qualche ragione, il cliente non voglia/possa fare alcuna operazione però
voglia garantire che quell'oggetto rimanga in memoria, e quindi non venga passivato (e distrutto), in
modo tale che nel caso in cui ce ne fosse bisogno, le sue operazioni siano veloci e non gravate dal
tempo di riattivazione dell'oggetto stesso.
Il cliente fa in questo caso una lease!
70
Factory
Non è una classe!
71
L'ultima operazione di questa categoria interviene e stabilisce che a volte la passivazione di un
oggetto può essere complicata:
si supponga che lo stato di un oggetto sia fatto del suo stato interno e, supponendo che quel
determinato server abbia, ad esempio, delle socket aperte, quindi anche di risorse esterne (perché le
socket sono intese come qualcosa di aggancio all'esterno, a risorse per l'appunto esterne): quando si
fa una passivazione/riattivazione bisogna tenerne conto.
In particolare se un oggetto ha delle connessioni, queste dovranno essere spente quando si passiva
l'oggetto e dovranno essere riattivate quando si riattiva l'oggetto.
In questo caso, la gestione del tempo di vita risulta essere più complessa rispetto ad un semplice
salvataggio su database.
NOTA: Maggiore è la gestione di trattamenti specifici, maggiore è la ricchezza del middleware!
Caso di studio:
Supponiamo che un servitore quando viene attivato abbia bisogno di determinati servizi intermedi
che hanno bisogno di altri servizi intermedi che magari, hanno bisogno di lui....se lo si passiva, è
evidente che i servizi a lui correlati debbano essere anche loro passivati perché non più necessari.
Quando poi si riattiva il servitore principale, se non abbiamo nessuno che ci dica qual'è lo stato
complessivo che si vuole ottenere, sarà necessario riattivare tutto!
Questi agganci tra oggetti sono tenuti in conto da dei gestori del tempo di vita.
72
Additional Services
150 Stefano Di Monte
Lavorando con le tre categorie appena viste, si ha la capacità di interagire, di avere una
comunicazione più ricca ed una buona gestione delle risorse dalla parte del servitore, ma per gestire
bene le cose dalle due parti, in particolar modo dalla parte del servitore vi sono altri pattern
importanti: il contesto e la sessione ed anche la call-chain Interceptor che è la catena delle
responsabilità.
73
Invocation Context
Supponendo di avere delle operazioni che ovviamente battono sul servitore e quindi sull'oggetto
finale attraverso la solita catena di proxy e stub; tipicamente quando viene chiesto un metodo ciò
che si passa nell'invocazione è il nome del metodo e gli argomenti.
Supponendo ora che si abbia bisogno di una maggiore continuità tra le operazioni, in particolare
anche delle garanzie semantiche che le operazioni siano considerate parte della stessa interazione,
questo viene rappresentato dal contesto d'invocazione.
Un contesto d'invocazione, supponendo ad esempio una transazione, potrebbe essere l'ID della
transazione stessa.
Il vantaggio sta nel fatto che, il metodo non ha nessuna idea del contesto ed il contesto è un insieme
aggiuntivo di informazioni che viene passato dal cliente al servitore, lasciando l'interfaccia
d'invocazione semplice.
Supponendo di fare delle invocazioni location awere, per come si dovranno chiedere le invocazioni
bisognerà aggiungere la posizione del cliente, che al fine di non modificare l'invocazione del
metodo e i suoi parametri, passerà nel contesto stesso, in modo tale da poter essere trattata a parte
non alterando quindi la logica dell'interazione principale.
Il contesto d'invocazione quindi, è un insieme di parametri aggiunti che qualificano meglio
l'operazione e consentono al servitore di fare delle azioni addizionali tipicamente che sono
dipendenti dal cliente ma che sono nettamente separate, in modo pulito, dalla logica corrispondente.
74
Session
In modo simile al contesto si parla di sessione.
In molti casi l'oggetto finale è un oggetto semplice: potrebbe essere un oggetto senza stato. A tal
punto il servitore per servire meglio l'operazione potrebbe avere bisogno di informazioni
addizionali, in questo caso, parlando di sessione, queste informazioni addizionali sono mantenute
sul servitore.
Queste informazioni possono consentire di aggiungere le necessarie azioni del servitore senza che il
cliente se ne occupi: ad esempio, potrebbe essere che la sessione dalla parte del servitore consenta
di capire quali aggiunte dobbiamo fare dipendentemente, ad esempio, dalla sua posizione rispetto
alle posizioni precedenti ecc ecc.
La sessione potrebbe anche eseguire delle operazioni significative: ad esempio potrebbe avere le
chiavi per decifrare la comunicazione che sta avvenendosi.
NOTA: in realtà il concetto di sessione e contesto sono simili perché producono stato ma l'uno dalla
Reti di Calcolatori LM 151
parte del cliente (il contesto) e l'altro dalla parte del servitore (la sessione).
75
La terza categoria è la catena di responsabilità: Call-Chain Interceptor.
Viene considerata come una operazione di base e tutta una serie di altre pre-operazioni sul servizio
che sono a carico di una serie ordinata di intercettori, ossia dei metodi che vengono attivati
automaticamente per trattare le informazioni e anche alterare le informazioni prima che queste
vengano elaborate.
Guardando la figura nella slide:
vi è una richiesta di invocazione preceduta da una serie di beforeInvocation, ossia dei metodi locali
che devono fare degli interventi. Un interceptor potrebbe ad esempio essere un gestore della
sicurezza, che quindi decodifica il messaggio che sta passando, perché magari cifrato, e lo rende
visibile sicuramente al servitore che a quel punto può ricevere i parametri in maniera assolutamente
normale. In particolare, in questo caso, se il servitore non sa che il messaggio è cifrato, molto
probabilmente neanche il cliente sa di tale cifratura: vi sarà perciò un interceptor anche dalla parte
del cliente accordatosi magari con quello del servitore.
Un metodo beforeInvocatione potrebbe anche essere un qualcosa che verifica, su una sessione, la
storia del cliente, la sua posizione e stabilisce in modo più preciso quali sono le informazioni locali
da fornirgli.
Si chiama catena di chiamate proprio perché ci sono tutta una serie di chiamate, di pre invocazioni,
o beforeInvocation, che avvengono prima della reale invocazione sull'oggetto remoto. Quindi fanno
delle azioni senza le quali le cose non funzionerebbero bene.
Gli interceptor sono normalmente dei componenti di sistema, non vengono descritti dall'utente
finale!
Gli interceptor potrebbero essere molti; sono creati dal supporto anche dinamicamente; e per tutte
queste ragioni rappresentano un carico forte, quindi sarebbe meglio se gestiti dal sistema!
NOTA: è uno dei tipici problemi che deve affrontare un middleware!
La Call-Chain è molto importante perché consente una migliore gestione, non solo applicativa bensì
anche del cliente servitore, e quest'ultimi avendo contesto, sessioni, interceptor ecc ecc possono
contare su di un supporto più ricco senza che l'utente sia consapevole del tutto, e pertanto potrà
interessarsi solo della parte logica lasciando tutta la parte di supporto al middleware.
76 – 77
QoS Services
152 Stefano Di Monte
Broker
Vedere OA in CORBA
80
Plug-in
In realtà i plug-in qui segnalati, sono diversi da quelli del web: sono difatti plug-in di sistema, che
vengono installati direttamente dal middleware che è in grado di avere, tramite questi, dei
comportamenti ad-hoc per certe operazioni.
Si parla di plug-in server, quindi a carico del servitore!
81
Object Group
Molto spesso a livello di principio un cliente fa una richiesta e pretenderebbe che dalla parte del
servitore, ci fossero una serie di servitori coordinati che replicano la stessa funzione e sono in grado
anche di replicare lo stato: questa è un esigenza che non si riesce quasi mai a mappare con una certa
qualità.
Uno dei pattern di qualità ha quest'idea, per l'appunto, di
gruppo di oggetti: una serie di server coordinati che sono in
grado di coordinare il proprio stato e mantenere uno stato
coordinato in modo tale che se uno fallisce, gli altri sono in
grado di andare avanti, continuare a proporre operazioni e a
fare operazioni e a mantenere uno stato che poi possa essere
instaurato sul servitore quando rientra.
La cosa importante da considerare è che i middleware quando diventano ricchi cominciano ad avere
un idea di gestione che va nel senso di oggetti replicati. Automaticamente il supporto è in grado di
mantenere gli oggetti configurati, di attivarli se ce n'è bisogno, di garantire con degli interceptor che
lo stato venga propagato dall'uno all'altro ed una serie di azioni che mantengono lo stato coordinato.
Corba e ambienti microsoft hanno oggetti di questo tipo!
Ovviamente il costo di un gruppo di oggetti è superiore!
82
Pseudo Object
Presente in tutti i middleware ad oggetti.
Uno pseudo oggetto è un sotterfugio di modellazione particolarmente utile perché consente di
vestire un meccanismo e di farlo vedere come se fosse un oggetto.
É un puro meccanismo di middleware (quindi locale al middleware stesso) e che non può essere
visto come un servizio invocabile, ma che può essere molto utile per avere una buona modellazione
dell'interazione tra cliente e servitore.
Reti di Calcolatori LM 153
Assomigliano a degli oggetti in quanto ne hanno l'interfaccia simile ma in realtà non sono oggetti!
Non si possono richiedere operazioni al di fuori del middleware in cui è stato definito, a differenza
di un oggetto vero che può dare le sue funzionalità dovunque, in qualunque istanza di middleware
risieda ed in tutte le istanze del middleware.
NOTA: gli oggetti proxy (stub e skeleton) sono dei pseudo-oggetti!
154 Stefano Di Monte