• Non ci sono risultati.

4.1 Overview sull’architettura

L’architettura tollerante ai guasti denominata IRL (Interoperable Replication Logic) utilizza la replicazione a tre livelli per aumentare la disponibilit`a di ogget-ti stateful determinisogget-tici sviluppaogget-ti sulla piattaforma CORBA ([44]). IRL mette a disposizione degli sviluppatori di applicazioni CORBA tolleranti ai guasti mec-canismi per la rilevazione di guasti e per la gestione della replicazione attraverso interfacce standard definite nella specifica FT-CORBA ([43]).

La scelta di realizzare il prototipo basandoci sullo standard FT-CORBA si basa essenzialmente su due considerazioni:

• la specifica FT-CORBA `e lo standard pi`u conosciuto per la tolleranza ai

guasti nell’ambiente distribuito ad oggetti;

• la specifica FT-CORBA “aumenta” i client solo con un semplice

meccanis-mo di ritrasmissione e redirezione, che si adatta al meccanis-modello di client ipotizza-to per lo schema di replicazione a tre livelli. Quesipotizza-to significa che un client compliant con la specifica FT-CORBA soddisfa la propriet`a denominata

Client-Autonomy, definita nella sezione 3.1.

L’infrastruttura denominata IRL corrisponde al mid-tier dell’architettura a tre livelli per la replicazione software di oggetti CORBA stateless e stateful. La Figura 4.1 mostra i principali componenti dell’infrastruttura.

Per salvaguardare la portabilit`a e l’interoperabilt`a dell’infrastruttura, cos`ı come

mostrato nella Figura 4.1, la comunicazione tra i client, le entit`a del mid-tier e i membri degli object group (cio`e le repliche server dell’end-tier) `e realizzata attraverso le invocazioni standard di CORBA1: in particolare, i client di object group stateful interagiscono col componente dell’architettura denominato Object-GroupHandler che gestisce l’interazione con i membri degli object group; nel caso di server stateless replicati, i client si connettono direttamente con uno dei mem-bri dell’object group.

Object Request Broker

Client Obj Obj Obj

RM RM RM FN FN FN OGH OGH OGH mid-tier STATEFUL Object Group

Client Obj Obj Obj

STATELESS Object Group client-tier end-tier Sitema Distribuito Asincrono Sistema Distribuito Parzialmente Sincrono Sitema Distribuito Asincrono OGH RM FN

IRL Object Group Handler IRL Replication Manager

IRL Fault Notifier

Intra-component message bus

Figura 4.1: L’architettura di IRL

Per assicurare la terminazione dell’interazione client/server e i servizi di gestione e controllo, i componenti di IRL, denominati ObjectGroupHandler, IRLReplication-Manager e IRLFaultNotifier sono replicati, come mostrato in Figura 4.1.

Le repliche di tutti i componenti di IRL girano un in ambiente parzialmente 1IRL usa solo meccanismo standard definiti da CORBA, come ad esempio SSI (Static

Skele-ton Interface) e DSI (Dynamic SkeleSkele-ton Interface), SII (Static Invocation Interface) e DII (Dynamic Invocation Interface), i Portable Interceptors, il Naming Service e l’Interface Repository

4.2. REPLICATION MANAGEMENT 33

sincrono; si pu`o notare che sia i client che i membri degli object group non neces-sitano di nessuna assunzione temporale: quindi IRL soddisfa la propriet`a definita nella sezione 3.1 denominata Client/Server-Asynchrony. In altre parole, tutte le assunzioni di sincronia necessarie per mantenere la consistenza dei membri degli object group sono confinate nel mid-tier; inoltre le repliche dei componenti di IRL interagiscono tra loro attraverso un intra-component message bus (non nec-essariamente un ORB) basato essenzialmente su TCP/IP.

Nel seguito, saranno presentate delle brevi descrizioni dei componenti di IRL: questa descrizione sar`a funzionale, nel senso che sar`a indipendente dalla tecni-ca adottata per replitecni-care i componenti di IRL, che sar`a introdotta nel prossimo capitolo.

4.2 Replication Management

Il componente IRLReplicationManager implementa l’interfaccia ReplicationManager definita nella specifica FT-CORBA. In particolare, quando viene richiesto ad RM di creare nuovi object group, questo componente crea, attraverso le local factory messe a disposizione dagli sviluppatori dei server, i nuovi membri degli object group, restituendo poi il riferimento all’object group appena creato; l’interazione tra RM e le local factory `e definita dalla specifica FT-CORBA attraverso l’inter-faccia GenericFactory.

Il replication manager di IRL permette la gestione di object group stateless e stateful con consistenza e membership controllata sia da una applicazione che dall’infrastruttura stessa. Nel caso in cui la consistenza del gruppo sia controlla-ta dall’infrastruttura, il componente si occupa della creazione delle repliche degli ObjectGroupHandler (vedi sezione 4.4 per i dettagli).

4.3 Fault Notification

Come definito nella specifica FT-CORBA, il componente denominato IRLFault-Notifier:

• riceve dagli IRL LocalFailureDetector (LFD)2 i report riguardanti i guasti di

oggetti;

• riceve sottoscrizioni dai client per le notifiche di guasti.

Subito dopo aver ricevuto un fault report da un failure detector, il fault notifier di IRL lo inoltra al replication manager e ai client interessati. Oltre a questo, il fault notifier riceve heartbeat dai vari LFD del domino, per monitorare eventuali guasti degli host: non appena rileva3 il guasto di un host, FN crea un fault report che sar`a mandato al replication manager e a tutti i client che si soni iscritti per gli oggetti residenti sull’host guasto.

4.4 Gestione degli object group

Il componente ObjectGroupHandler `e associato ad ogni object group stateful : memorizza le informazioni riguardanti i membri degli object group, ed `e inoltre responsabile di assicurare la strong replica consistency dello stato dei membri degli object group.

Questo componente realizza il mid-tier di architettura a tre livelli. Sfruttando gli IOGR e i meccanismi DII e DSI di CORBA, l’Object Group Handler:

• accetta tutte le connessioni dai client;

• riceve tutte le richieste dirette all’object group che gestisce; • impone a queste richieste un ordine totale;

2Compliant con i FaultDetector della specifica FT-CORBA

3Il modo in cui FN “decide” che un host `e guasto dipende da vari fattori, come ad esempio

il modello di sistema ipotizzato; nel Capitolo 5 verr`a specificato il meccanismo di rilevamento dei guasti.

4.4. GESTIONE DEGLI OBJECT GROUP 35

• inoltra le richieste a tutti i membri degli object group;

• raccoglie i risultati provenienti dai membri degli object group e li restituisce

al client. Client OG Member1 OG Member3 OG Member2 OGH Object Group

Figura 4.2: Schema di funzionamento del componente ObjectGroupHandler.

Si pu`o notare che i client non appartengono a nessun tipo di gruppo, e che si connettono ad OGH diversi per accedere ad object group diversi4.

L’attivit`a principale svolta dall’ObjectGroupHandler `e quella di ordinare le richi-este provenienti dai client; in fase di analisi sono stati sviluppati due differenti protocolli di ordinamento: uno che si basa su forti assunzioni di sincronia, e per questo pi`u facilmente realizzabile, che sar`a poi illustrato in dettaglio nella sezione 4.4.1, e uno pi`u complesso ([4]) che permette di rilassare le forti assunzioni fatte in precedenza.

4.4.1 Un semplice protocollo

Il primo protocollo proposto si basa essenzialmente su forti assunzioni di sincronia del mid-tier; il sistema distribuito considerato `e asincrono e composto da un insieme finito di processi che comunicano tramite scambio di messaggi su canali di comunicazione affidabili. I processi sono soggetti a guasti di tipo crash (vedi sezione 2.3.1); si possono individuare tre insiemi distinti di processi:

• C ∈ {c1, c2, c3, c4, . . . , cn}: insieme di processi client;

• A ∈ {a1, a2, a3, a4, . . . , ak}: insieme delle repliche del mid-tier; • E ∈ {e1, e2, e3, e4, . . . , em}: insieme delle repliche server.

Le repliche del mid-tier sono stateless rispetto alla richiesta che il client vuole invocare sui server replicati: cio`e, le richieste dei client vengono solo inoltrate ai server replicati; come diretta conseguenza di ci`o si `e scelto di replicare i processi dell’end-tier con uno schema di replicazione passiva; le richieste vengono proces-sate dal mid-tier una alla volta: le richieste ricevute dal primary vengono inserite in una coda locale al processo. Ad ogni richiesta inoltrata viene associato un numero di sequenza che verr`a usato nel caso il primary si guasti. Per evitare che gli end-server processino anche richieste pervenute con notevole ritardo (cio`e relative a vecchi primary ormai guasti), ogni messaggio include l’identit`a del pri-mary che lo ha spedito; sulle repliche verr`a di volta in volta aggiornata l’identit`a del primary attivo in un determinato istante.

c1 r1 a2 a3 r2 a1 r3 r5 r4 coda di richieste

Figura 4.3: Interazione client/server.

Il protocollo si compone essenzialmente di tre parti: una per il client, una per il mid-tier e una per l’end-tier.

4.4.1.1 Protocollo del client

L’invocazione di una operazione da parte di un client avviene attraverso l’invo-cazione della primitiva issue (Figura 4.4): questa primitiva prende come parametro di input la richiesta destinata ai server replicati, e ritorna il risultato a tale richies-ta. Il client ritrasmetter`a la richiesta a tutti i processi del mid-tier, fino a quando

4.4. GESTIONE DEGLI OBJECT GROUP 37

Class ClientProtocol()

1 array of AppServer alist := theAppServers; 2 Integer i := 1;

3

4 Result issue(Request request) 5 AppServer a;

6

7 begin

8 while true do

9 a := alist[i];

10 send [Request, < c id, req id, request >] to a;

11 when ((receive [Result, res] from a) or (exception)) do

12 if (not exception)

13 then return (res);

14 else i := (i + 1) mod|alist|;

15 end

Figura 4.4: Pseudo codice del protocollo lato client.

non ricever`a un risultato: solo il primary per`o inoltrer`a la richiesta alle repliche dell’end-tier, mentre le altre repliche risponderanno con un’eccezione, che causer`a una reinvocazione da parte del client; l’ipotesi di avere almeno una replica del mid-tier corretta assicura che il processo di reinvocazione prima o poi finir`a con la consegna del risultato al client. Le eccezioni dovute alla richiesta sono state modellate come dei risultati da restituire comunque al client, mentre eventuali timeout sulla connessione tra client e mid-tier oppure eccezioni dovuti a guasti del mid-tier, sono state modellate come quelle eccezioni che causeranno una rein-vocazione della richiesta su un’altro processo del mid-tier.

Si pu`o notare che il protocollo del client implementa un semplice meccanismo di ritrasmissione e redirezione: cio`e `e soddisfatta la propriet`a Client-Autonomy definita nella sezione 3.1.

4.4.1.2 Protocollo del mid-tier

Il mid-tier adotta uno schema di replicazione passiva: una replica degli Ob-jectGroupHandler processa tutte le richieste occupandosi di mantenere ordine

e atomicit`a. Per assicurare queste due propriet`a, il primary processa le richi-este una alla volta: quando il client invoca una richiesta sui server, il primary si occupa di inoltrarla a tutte le repliche server, attendendo il risultato da tutte le repliche; restituito poi il risultato al client, processa una nuova richiesta.

C1 R2 C2 req1 req2 R1 OGH1 OGH3 OGH2 R3 req1 req2

Figura 4.5: Interazione client/server senza guasti.

Riferendoci alla Figura 4.5, quando il client C1 invoca la richiesta req1, il pri-mary dell’ObjectGroupHandler la inoltre a tutte le repliche del servizio; quando il client C2 invoca la richiesta req2, questa viene accodata dall’ObjectGroupHandler primary per essere processata quando tutte le repliche server hanno restituito la risposta alla richiesta req1.

La forte assunzione fatta sul sistema consiste nell’uso di failure detector

per-fetti : cio`e caratterizzati dalle propriet`a di “accuratezza forte” (strong accuracy) e “completezza forte” (strong completeness) definite da [11]; in pratica l’ipotesi fatta `e che non vengono commessi errori nella rilevazione dei guasti, sia delle repliche dell’mid-tier sia di quelle dell’end-tier.5 Se una replica dell’end-tier si guasta il primary che sta processando la richiesta, non aspetter`a il risultato da 5Questo tipo di rilevazione dei guasti pu`o essere fatta rispettare facendo girare le repliche

monitorate in un sistema con un determinato tasso di sincronia (es. una rete a traffico control-lato) o in un sistema parzialmente sincrono (come il “timed asynchronous system”) con l’ausilio di hardware watchdogs ([24]).

4.4. GESTIONE DEGLI OBJECT GROUP 39

tale replica, visto che sicuramente il processo in questione `e guasto. C1 R2 req1 R1 OGH1 OGH3 OGH2 R3 crash di R3 req1 rilevamento del guasto FN

Figura 4.6: Interazione client/server con guasto di una replica dell’end-tier.

La Figura 4.6 mostra come il primary si sblocchi non aspettando pi`u il risultato da una replica guasta. Quando il FaultNotifier rileva che una replica `e guasta, lo comunica a tutti i processi del mid-tier; se il primary `e bloccato in attesa del risultato da quella replica, si sboccher`a restituendo al client il risultato ottenuto dalle altre repliche.

Oltre ai guasti delle repliche server, gli OGH gestiscono eventuali guasti del pri-mary: in questo caso `e necessario (i) stabilire un protocollo per l’elezione del nuovo primary (ii) effettuare una fase di recovery per ripristinare la consistenza del gruppo di repliche dell’end-tier (eventualmente violata).

L’elezione del nuovo primary avviene sfruttando l’ipotesi di accuratezza dei fail-ure detector: quando viene notificato il guasto di una replica degli OGH, ogni replica del mid-tier verifica se deve diventare primary o no; in particolare la prima replica del mid-tier non guasta diventer`a il nuovo primary (Figura 4.7) dopo aver effettuato il recovery delle repliche dell’end-tier.

1 clean() 2

3 begin

4 while true do

5 cobegin

6  when (ai ∈ alist is crashed) do

7 when (∀i < this : ai ∈ alist is crashed) do

8 this.recovery();

9 primary := this;

10  when (ei ∈ elist is crashed) do

11 remove ei from elist;

12 coend

13 end

Figura 4.7: Pseudo codice del protocollo del mid tier: gestione dei guasti.

La replica degli ObjectGroupHandler che diventer`a primary, prima di accettare nuove richieste, deve effettuare una fase di recovery: questo `e necessario perch`e a fronte di un guasto di un processo, non `e noto quali repliche dell’end-tier ricev-eranno le richieste6. Quando il primary inoltra le richieste dei client verso le repliche server, associa ad ogni richiesta effettuata un numero di sequenza lo-cale (cio`e valido solo per la singola replica): durante la fase di recovery il futuro primary richieder`a alle repliche server di comunicare il numero di sequenza del-l’ultima richiesta processata; se tutte le repliche server ritornano lo stesso numero di sequenza, allora sono in uno stato consistente, e quindi il primary neoeletto pu`o iniziare a servire richieste; altrimenti il nuovo primary prender`a lo stato dalla replica pi`u aggiornata (quella con il numero di sequenza pi`u alto), ed aggiorner`a lo stato delle altre repliche.

Nella Figura 4.8 viene mostrata la fase di recovery intrapresa a fronte di un guasto del primary degli ObjectGroupHandler; nonostante il guasto, la richiesta req1 `e stata correttamente eseguita dalla replica R1, che quindi avr`a lo stato pi`u aggiornato rispetto alle repliche. Quando OGH2 inizia la fase di recovery, chiede prima alle repliche server di comunicare il numero di sequenza dell’ultima

4.4. GESTIONE DEGLI OBJECT GROUP 41 C1 R2 req1 R1 OGH1 OGH3 OGH2 R3

crash del primary

rilevamento del guasto FN < req1 , 1> 1 00

get_last() get_state() set_state()

req1

Figura 4.8: Protocollo di recovery del mid-tier.

ta servita; dopo aver verificato che esiste almeno una replica pi`u aggiornata delle altre, OGH2 prende lo stato dalla replica R1 e lo setta come nuovo stato delle altre repliche (R2 e R3).

4.4.1.3 Protocollo dell’end-tier

Il protocollo delle repliche dell’end-tier necessitano solo di funzioni aggiuntive per la gestione del recovery durante l’elezione del nuovo primary del mid-tier, e un servizio di logging per filtrare i duplicati.

4.4.2 Approccio basato su un sequencer

Abbiamo visto, nel protocollo della sezione precedente, che la linearizzabilit`a `e assicurata dal modo in cui l’ObjectGroupHandler processa le richieste.

Un altro possibile approccio (illustrato nella Figura 4.9) `e quello di associare ad ogni richiesta di un client un identificativo unico per il sistema.

Quando un client vuole invocare un’operazione su un server replicato, questa viene processata dal mid-tier, che associer`a alla richiesta un numero di sequenza

Sistema Asincrono

Sistema Asincrono

Sistema Parzialmente Sincrono Sistema Asincrono Midtier C req1 1 Sequencer j 2 3 S1 S2 < req1, j > < req1, j > 4

Figura 4.9: Protocollo basato sull’uso di un sequencer.

attraverso l’interazione con un sequencer tollerante ai guasti. Una volta ricevuto il numero di sequenza, la richiesta viene inoltrata alle repliche server che servi-ranno le richieste secondo l’ordine stabilito dal sequencer. Visto che le repliche sono supposte deterministiche, il mid-tier restituir`a il primo risultato restituito dai server replicati, senza aspettare tutti i risultati.

Con questo protocollo si pu`o notare che i client e i server rispettano entrambe le propriet`a di Client-Autonomy e Client/Server-Asynchrony definite nella sezione 3.1; inoltre cos`ı come `e stato presentato l’approccio, solo il sequencer necessita di un ambiente parzialmente sincrono7.

In [5] si possono trovare i dettagli per il sequencer, mentre si veda in [4] per i dettagli sull’algoritmo proposto in questa sezione.

Capitolo 5