L’architettura descritta nel capitolo 4 pu`o essere implementata in diversi modi che si differenziano essenzialmente per:
1. le tecniche e le tecnologie usate per la realizzazione della tolleranza ai guasti dell’infrastruttura;
2. il protocollo di multicast implementato dalle repliche dell’ObjectGroupHandler per mantenere la consistenza dei membri degli object group.
In questo capitolo verr`a presentato un prototipo dell’architettura: la scelta sulla tecnica di replicazione da adottare per ogni componente `e stata presa sulla base dello stato eventualmente mantenuto dai componenti: tale stato dipende essen-zialmente dalla funzione espletata dal componente. `E stato inoltre implementato il semplice algoritmo di multicast illustrato nella sezione 4.4.1.
I componenti dell’architettura possono essere classificati in due categorie:
• componenti specifici dell’host: sono i componenti che danno supporto agli
host che compongono il dominio di tolleranza ai guasti;le funzionalit`a di questi componenti non devono sopravvivere al guasto dell’host;
• componenti specifici del dominio: sono quei componenti che svolgono le
funzioni principali su tutto il dominio di tolleranza ai guasti. 43
Di seguito verranno prima descritte le caratteristiche che hanno guidato le scelte implementative fatte; poi si descriver`a l’implementazione dei componenti di IRL, entrando nel dettaglio del design dell’ObjectGroupHandler: in particolare nella sezione 5.1 vengono descritte le caratteristiche volute per i client e i server di IRL; nella sezione 5.2 e 5.3 vengono descritte le caratteristiche principali dei componenti id IRL.
5.1 Caratteristiche dell’architettura
5.1.1 Affidabilit`a
Per affidabilit`a si intende la caratteristica base di un sistema tollerante ai guasti, cio`e la sua capacit`a di gestire situazioni di malfunzionamento di uno dei suoi componenti garantendo rispetto ai suoi utilizzatori:
• continuit`a del servizio: il servizio normalmente fornito dal sistema ai
suoi utilizzatori non deve interrompersi in seguito ad un guasto;
• consistenza dei dati: i comportamenti del sistema non devono essere
alterati in seguito ad un guasto e devono mantenersi consistenti con le specifiche attese dagli utilizzatori.
5.1.2 Interoperabilit`a
Una delle caratteristiche fondamentali di CORBA `e la capacit`a di mascherare le eterogeneit`a che in un sistema distribuito possono esistere a vari livelli: si pos-sono cio`e stabilire comunicazioni tra oggetti CORBA indipendentemente dal loro linguaggio di programmazione, sistema operativo, protocollo di rete e anche dalla particolare implementazione CORBA in cui sono stati realizzati. Quest’ultimo punto `e possibile grazie al protocollo GIOP, che specifica il tipo di connessione e il formato dei messaggi che un ORB CORBA-compliant deve rispettare nella co-municazione tra due oggetti. Questa caratteristica viene definita interoperabilit`a ed `e uno dei punti fermi su cui si `e deciso di basare il progetto dell’architettura IRL.
5.2. COMPONENTI SPECIFICI DELL’HOST 45
La specifica OMG per Fault Tolerant CORBA non prevede tra le sue caratteris-tiche l’interoperabilit`a, ma addirittura impone che tutti gli oggetti appartenenti ad un object group devono, per essere tolleranti ai guasti, usare lo stesso ORB e la stessa infrastruttura di tolleranza ai guasti. Questa `e una limitazione piuttosto forte, che verr`a superata nel progetto dell’architettura IRL. Si pu`o ottenere la completa interoperabilit`a sfruttando la caratteristica alla base della stessa inter-operabilit`a di CORBA, e cio`e facendo in modo che tutte le comunicazioni tra i componenti del sistema avvengano per mezzo del protocollo GIOP.
5.1.3 Trasparenza
Nel realizzare l’astrazione di object group, un sistema tollerante ai guasti, dovrebbe preferibilmente mascherare ai suoi utilizzatori i meccanismi della comunicazione di gruppo. In generale, la trasparenza di un sistema rappresenta appunto la ca-pacit`a del sistema stesso di compiere le sue operazioni in maniera visibile rispetto agli utilizzatori, che proprio uno dei principi del middleware per ambienti dis-tribuiti. L’architettura IRL si propone di realizzare la trasparenza rispetto alla replicazione, su due diversi livelli:
• trasparenza lato client: un client non deve distinguere l’invocazione fatta
ad un object group da quella fatta ad un oggetto singolo. Al limite, un singolo oggetto potrebbe essere sostituito da un gruppo senza che questo debba comportare modifiche all’applicazione client;
• trasparenza lato server: ogni oggetto membro di un gruppo non deve essere
consapevole di esserlo. Esso, infatti, deve gestire le invocazioni di gruppo allo stesso modo di quelle singole. Al limite, un oggetto server potrebbe essere aggiunto ad un gruppo senza subire modifiche.
5.2 Componenti specifici dell’host
I componenti specifici dell’host sono i LocalFailureDetector (LFD) e le IRLFacto-ry (IRLF): questi componenti sono installati su ogni host del dominio, e le loro
attivit`a sono confinate solo all’host su cui risiedono; come conseguenza, non `e nec-essario replicarli su host diversi, visto che non devono sopravvivere ai guasti degli host. Comunque, essendo soggetti a guasti a livello software, saranno replicati localmente.
5.2.1 IRLFactory
`
E il componente dell’infrastruttura con il compito di creare tutti i componen-ti dell’infrastruttura stessa: cio`e l’ObjectGroupHandler, l’IRLReplicationManager, l’IRLFaultNotifier, il LocalFailureDetector e l’IRLFactory; tutti i componenti creati sono oggetti CORBA residenti in processi separati da quello dell’IRLFactory; la IRLFactory estende l’interfaccia GenericFactory definita dallo standard FTCOR-BA.
L’IRLFactory `e sostanzialmente un componente senza stato: crea oggetti e restitu-isce la reference degli oggetti creati, senza memorizzare le informazioni riguardanti gli oggetti creati. Di conseguenza, lo stile di replicazione implementato per tale componente `e lo stateless primary-single-backup. Su ciascun host sono posizion-ate due IRLFactory, aventi l’una il ruolo di primary, l’altra di backup. Il flusso bidirezionale di heartbeat tra le due entit`a garantisce un rilevamento di guasto reciproco: quando uno dei due oggetti rileva che l’altro `e andato in crash, (non riceve pi`u heartbeat dal partner), ricrea il compagno per ripristinare la config-urazione tandem del monitoraggio. Il flusso di heartbeat pu`o essere realizzato tramite IPC, dato che comunque i due componenti si trovano nel medesimo host. Se `e il primary a guastarsi, il backup ripristina la configurazione tandem e si elegge nuovo primary.
5.2.2 LocalFailureDetector
Il componente LocalFailureDetector `e conforme alle specifiche FTCORBA: ciascun host del dominio `e fornito di uno ed un solo LocalFailureDetector. I compiti svolti dal componente in esame sono due:
5.2. COMPONENTI SPECIFICI DELL’HOST 47
possono essere sia componenti dell’architettura IRL (IRLReplicationManager, ObjectGroupHandler, IRLFaultNotifier) sia oggetti forniti dai programmatori di applicazioni (server replicati tramite IRL). Il componente IRLReplica-tionManager richiede, tramite invocazioni standard CORBA di monitorare particolari oggetti residenti su quell’host. Il LocalFailureDetector conserv-er`a nel suo stato una lista degli IOR di tutti gli oggetti monitorati e per ciascuno i valori corrispondenti delle propriet`a di fault monitoring (timeout e monitoring interval). Lo stile di monitoraggio si basa su un modello di tipo pull, secondo il quale `e il LocalFailureDetector periodicamente invoca il metodo is alive()1 sugli oggetti. La mancata risposta entro il timeout in-duce il LocalFailureDetector a sollevare verso l’IRLFaultNotifier una notifica di guasto;
• cooperare con l’IRLFaultNotifier per il rilevamento del guasto dell’intero
host: secondo uno stile di monitoraggio di tipo push, ciascun LocalFail-ureDetector invia periodicamente heartbeat verso l’IRLFaultNotifier.
Lo stile di replicazione scelto per questo componente `e la replicazione passiva a
freddo: le informazioni che compongono lo stato dell’oggetto sono salvate in un
log, usato per ripristinare lo stato del componente a fronte di guasti. Il rileva-mento del guasto del componente `e realizzato in collaborazione con l’IRLFactory: il LocalFailureDetector invoca periodicamente il metodo is alive() sull’IRLFactory2; ad ogni invocazione viene reinizializzato un timeout opportuno. Se il LocalFail-ureDetector non reinvoca tale metodo entro il timeout, l’IRLFactory lo considera guasto. Di conseguenza, l’IRLFactory ricrea il LocalFailureDetector, il quale con-figura il suo stato iniziale a quello memorizzato nel log. La Figura 5.1 illustra i messaggi scambiati fra i componenti specifici dell’host e le loro relazioni.
1Operazione messa a disposizione dall’interfaccia PullMonitorable definita dallo standard FTCORBA.
2L’IRLFactory implementa le interfacce GenericFactory e PullMonitorable dello standard FTCORBA.
IRL Factory Replica 1 IRL Factory Update is_alive I’m alive Host A FN ORB ORB Host B Host A alive is_alive IRL Factory Replica 2
Log Lo ca l F ail ur e D ete ct or
Figura 5.1: Replicazione dei componenti specifici dell’host
5.3 Componenti specifici del dominio
I componenti IRLReplicationManager, IRLFaultNotifier, ed ObjectGroupHandler, im-plementano funzionalit`a che devono sopravvivere al guasto di un host: sono stati quindi replicati per renderli tolleranti ai guasti.
5.3.1 IRLReplicationManager
Il componente si occupa della gestione della replicazione (vedi sezione 4.2): in particolare invoca delle operazioni sulle factory residenti sugli host (ad esempio per la creazione degli object group) subito dopo aver ricevuto una richiesta dai client. Questo rende IRLReplicationManager un componente non deterministico: per questo `e stato scelto di replicare il componente con la tecnica della repli-cazione passiva. A questo scopo, ogni replica del componente `e “wrappato” da un oggetto CORBA, che riceve tutte le richieste dirette all’IRLReplicationMan-ager, implementando un protocollo di sincronizzazione tra il wrapper primary e i wrapper backup (vedi [3] per i dettagli).
5.3. COMPONENTI SPECIFICI DEL DOMINIO 49
5.3.2 IRLFaultNotifier
Il componente svolge le funzioni di fault notification (sezione 4.3) in collabo-razione con i LocalFailureDetector. Per il prototipo realizzato questo fault notifier assicura failure detection perfetta ([11]), inoltre al momento non ne esiste una versione replicata (ancora in fase di studio). Quindi attualmente l’oggetto `e non replicato, e di conseguenza supposto tollerante ai guasti.
La funzione principale del fault notifier `e quella di propagare fault report ai con-sumatori, attraverso un canale di comunicazione creato dal fault notifier stesso; i consumer, ad esempio l’IRLReplicationManager, gli ObjectGroupHandler o con-sumer objects, per sfruttare le potenzialit`a del canale aperto dal FaultNotifier, devono espletare due operazioni:
• si devono registrare al FaultNotifier per ricevere fault reports. Per far ci`o,
utilizzano i metodi connect structured consumer() e connect sequence consumer() dell’interfaccia FaultNotifier;
• devono ereditare l’interfaccia StructuredPushConsumer o
SequencePushCon-sumer per ricevere, su invocazione del FaultNotifier, rispettivamente eventi nel formato CosNotification::StructuredEvent o CosNotification::EventBatch. In generale, un consumer sar`a interessato solo ad alcuni eventi relativi ai guasti di oggetti: il fault notifier effettua a questo proposito un opportuno filtering dei fault report. I vincoli che guidano il filtering vengono specificati dai vari consumer con il metodo replace constraint() dell’interfaccia FaultNotifier ([43]).
5.3.3 ObjectGroupHandler
Nell’attuale prototipo di IRL, il componente ObjectGroupHandler implementa il semplice protocollo illustrato nella sezione 4.4.1.
Prima di entrare in dettaglio sull’design del componente, si illustreranno breve-mente le caratteristiche dei client e dei server di IRL.
Client-tier
I client di IRL implementano solo il semplice meccanismo di ritrasmissione e redirezione delle richieste definito dalla specifica FTCORBA. Gli ORB non com-pliant con la specifica FTCORBA possono utilizzare il componente di IRL de-nominato ORGW (Object Request GateWay). L’ORGW `e realizzato attraverso i
portable interceptor di CORBA: in pratica il componente emula il meccanismo di
ritrasmissione in modo portabile. Per ulteriori dettagli si veda [2] e [34].
End-tier
Ogni membro stateful di un object group deve essere deterministico (ipotesi fat-ta per la correttezza del protocollo), non pu`o invocare altri oggetti per servire una richiesta di un client (cio`e non deve effettuare richieste uscenti ) e deve im-plementare dei servizi aggiuntivi per il filtraggio dei duplicati e per il recovery. Queste funzioni aggiuntive sono realizzate attraverso il componente di IRL de-nominato IRGW (Incoming Request GateWay): l’IRGW implementa un semplice meccanismo di logging delle richieste basate sulla coppia< request, result >;
pri-ma di eseguire un metodo, verifica se la richiesta `e gi`a stata servita, restituendo il risultato presente nel log; se invece non `e stata mai servita, esegue il metodo cor-rispondente, memorizza il risultato nel log e restituisce il risultato. Oltre a questo meccanismo l’IRGW implementa le funzioni necessarie per la fase di recovery del protocollo: in particolare il metodo get last, usato per determinare la replica con lo stato pi`u aggiornato. Ogni replica server, per permettere il recovery, deve poi implementare necessariamente l’interfaccia Checkpointable, ed eventualmente l’interfaccia Updateable definite dalla specifica FTCORBA.
Inizializzazione del protocollo
Quando un client richiede all’IRLReplicationManager di creare un object group stateful, vengono create anche le repliche dell’ObjectGroupHandler che gestir`a tale gruppo. L’IRLReplicationManager restituir`a al client la reference contenente i pro-fili degli ObjectGroupHandler, cos`ı che le richieste del client siano indirizzate agli questi oggetti, e non direttamente alle repliche server. Infine, l’ IRLReplication-Manager comunicher`a alle repliche dell’ObjectGroupHandler le reference di tutte
5.3. COMPONENTI SPECIFICI DEL DOMINIO 51
le repliche server e di tutte le repliche degli ObjectGroupHandler: queste “viste” saranno aggiornate dagli ObjectGroupHandler subito dopo l’arrivo dei fault report provenienti dall’IRLFaultNotifier.
Design del componente
Come detto nel capitolo 4, l’ObjectGroupHandler rappresenta il mid-tier di una architettura a tre livelli; quando un client invoca un metodo su un object group, in realt`a invoca quel metodo sulla replica primary dell’ObjectGroupHandler: cio`e l’ObjectGroupHandler deve offrire la propriet`a di trasparenza lato client definita nella sezione 5.1.3. Dal punto di vista realizzativo, questo significa che l’inter-faccia offerta dall’oggetto CORBA relativo al componente deve essere la stessa offerta dai server replicati: per fare questo, lo standard CORBA mette a dispo-sizione lo strumento denominato DSI (Dynamic Skeleton Interface) che permette di creare a runtime interfacce CORBA.
ObiectGroupHandler stack.idl helloserver.idl conto.idl . . IFR stack.idl stack description 1 3 stack.idl 4 IRLReplicationManager 5 2 create (... stack.idl ....)
Figura 5.2: Acquisizione dinamica dell’interfaccia di un oggetto.
Durante la fase di startup, l’ObjectGroupHandler adotter`a l’interfaccia del tipo op-portuno, specificato dall’IRLReplicationManager; questa fase prevede l’interazione con uno dei servizi offerti da CORBA: l’InterfaceRepository (IFR); tramite questo servizio, `e possibile ottenere tutte le informazioni relative ad una interfaccia COR-BA: per il nostro scopo, rendere trasparente l’invocazione del client su un object group, le informazioni di interesse riguardavano, il tipo IDL dell’oggetto consid-erato, le operazioni offerte, con il numero di parametri, il tipo di parametri, etc.
Questo requisito ha portato ad una scelta realizzativa ben precisa: l’ObjectGroupHandler, oltre ad essere il gateway tra client e server, `e anche un oggetto a se stante; in particolare, l’interfaccia di questo oggetto deve offrire delle operazioni per la ges-tione del gruppo di repliche che controlla (ad esempio operazioni per l’aggiunta o la rimozione di repliche server); deve inoltre estendere l’interfaccia Structured-PushConsumer per poter ricevere i fault report da un FaultNotifier FTCORBA (vedi [43] per i dettagli relativi alla notifica di guasti).
OGHRequestHandler OGHManager Object Group Handler
C S1 S2 S3 S4 req req req req req remove_member notifica di guastodi S4
Figura 5.3: Design di OGH: separazione tra gestione gruppo e gestione richiesta. Per questo motivo `e stato necessario a dividere l’ObjectGroupHandler in due oggetti CORBA distinti (Figura 5.3):
• OGHRequestHandler: `e l’oggetto CORBA che si occupa dell’interazione tra
client e server; adotter`a dinamicamente l’interfaccia dell’oggetto controlla-to dall’ObjectGroupHandler, e implementer`a il protocollo di multicast (vedi sezione 4.4.1);
• OGHManager: `e l’oggetto CORBA che si occupa della gestione del gruppo di
repliche; `e l’oggetto che ricever`a i fault report dal FaultNotifier FTCORBA e che quindi si occuper`a anche del recovery.
La divisione nei due oggetti CORBA `e stata necessaria a causa dell’impossibilit`a di far convivere DSI e SSI3.
5.3. COMPONENTI SPECIFICI DEL DOMINIO 53
Un’altro aspetto curato nel design del componente `e stato quello di disaccoppiare il pi`u possibile lo stadio di accettazione della richiesta, dallo stadio di esecuzione dell stessa (Figura 5.4): questo per poter “cambiare” il protocollo di multicast, senza impattare sul design del componente.
OGHRequest
Handler multicaststadio di Object Group Handler C S1 S2 S3 S4 req req req req req informazioni sulla richiesta( req) OGHManager remove_member notifica di guastodi S4
Figura 5.4: Separazione tra lo stadio di accettazione e quello di esecuzione di una richiesta.
La separazione tra lo stadio di accettazione e quello di esecuzione della richiesta si basa sull’uso di una interfaccia che stabilisca le funzioni base che un protocollo di multicast progettato per IRL deve avere; in particolare l’interfaccia espone due metodi (Figura 5.5:
• serve request(): attraverso l’invocazione di questo metodo, `e possibile
comu-nicare allo stadio di multicast tutte le informazioni sufficienti per effettuare l’invocazione sui server replicati; le informazioni passate sono principal-mente la segnatura del metodo e il valore dei parametri;
• recovery(): attraverso l’invocazione di questo metodo, l’ObjectGroupHandler
potr`a effettuare la fase di recovery del protocollo.
Quando un client C invoca una richiesta req, l’OGHRequestHandler processa la
richiesta passandola allo stadio di multicast, e poi si mette in attesa del risultato; come specificato nel protocollo (sezione 4.4.1), eventuali altre richieste dirette allo stesso object group, vengono accodate e servite in seguito; l’accodamento
stadio di multicast OGHRequest
Handler
Object Group Handler
C S1 S2 S3 S4 req req req req req informazioni sulla richiesta ( req) OGHManager remove_member notifica di guastodi S4 Request Interface
Figura 5.5: Interfaccia di disaccoppiamento nello stadio di multicast.
viene realizzato con il supporto dell’ORB settando opportune policies in fase di creazione dell’oggetto ([44]).
Implementazione del protocollo di multicast
Per effettuare il multicast, ad ogni membro di un object group viene associato un oggetto che ne gestir`a direttamente l’interazione; questo oggetto, il Replicated-ServerHandler viene creato non appena viene aggiunto all’object group un nuovo membro; una volta creato, rimane in attesa di inoltrare una richiesta verso il membro dell’object group ad esso associato; quando un client invoca una richies-ta su un object group, ogni ReplicatedServerHandler tenrichies-ta di invocare il metodo richiesto sull’oggetto server: tenter`a di farlo fino a quando non ha ottenuto un risultato o fino a quando l’OGHManager non eliminer`a dalla lista dei membri del-l’object group la replica server in questione (a fronte della ricezione di un fault report che riguarda la replica). Se la replica server non `e guasta, allora il Replicat-edServerHandler si rimette in attesa di una richiesta, altrimenti esce (Figura 5.6 e Figura 5.7).
Secondo il protocollo descritto, l’ObjectGroupHandler prima di restituire al client il risultato dell’invocazione aspetta il risultato da tutti membri dell’object group non guasti; quindi `e necessario interporre tra i ReplicatedServerHandler e lo stadio di accettazione della richiesta un oggetto che aspetter`a la fine del processamento
5.3. COMPONENTI SPECIFICI DEL DOMINIO 55 : ReplicatedServerHandler Stadio di accetazione della richiesta Og getto CORBA : RequestInterface : OGHM an ag er in attesa di una richiesta da servire si sblocca ed invoca il metodo sull'oggetto gestito wait() serve_request( foo) invoke_member() notify() foo() result new() wait() res ult res ult restituisce il risultato e si rimette in attesa
: ReplicatedServerHandler Stadio di accetazione della richiesta Og getto CORBA : RequestInterface : OGHM an ag er destroy() new() wait() crash() guasto della replica continuerà ad invocare fino a quando non arriva la notifica di guasto serve_req uest(foo ) invoke_ member() notify() foo() exception * fo o()
5.3. COMPONENTI SPECIFICI DEL DOMINIO 57
della richiesta da parte di tutti i ReplicatedServerHandler4 prima di restituire il risultato da mandare al client (Figura 5.8).
Il design finale del componente `e riportato in Figura 5.9
Stadio di accettazione
della richiesta RequestInterface: : SyncProtocol ReplicatedServerHandlerRSH1 : ReplicatedServerHandlerRSH2 : : OG HManager
serv e_request( f oo)
inv oke_request() new() wait() new() new() wait() wait() in vo ke_ me mb er( ) invoke_member( ) notif y () notity () notif y () rsh_completion( ) s yn c_c om plet ion( ) result wait() wait() destroy ()
viene creato in fase di startup dell'ObjectGroupHandler
v iene p opola to l 'object group
aspetta che tutti i ReplicatedServerHandler attivi rispondano guasto dell'oggetto: il ReplicatedServerHandl er corrispondente non è più attivo
5.3. COMPONENTI SPECIFICI DEL DOMINIO 59
PullMonitorable
is_aliv e()
(from FT)
<<IDL def inition>>