Sisteme distribuite obiectuale si invocare la distantasoftware.ucv.ro/~cbadica/dadr/cap6.pdf · si...

32
2013 Sisteme distribuite obiectuale si invocare la distanta Capitolul 6 2013 Invocare la distanta Protocoale cerere – raspuns (engl. request – reply protocols) Ofera suport de nivel coborat pentru emiterea unor cereri de executie a operatiilor la distanta Ofera suport direct metodelor RPC si RMI Se bazeaza pe serializarea datelor (engl. marshalling) si referinte la distanta (engl. remote references) Apel de procedura la distanta (engl. remote procedure call – RPC), aparut in 1984 Permite unui program client sa apeleze in mod transparent o procedura ce ruleaza intr-un proces server, aflat posibil pe un calculator diferit de calculatorul clientului. Invocarea metodelor la distanta (engl. remote method invocation – RMI) Permite unor obiecte aflate in procese diferite, posibil pe calculatoare diferite sa comunice prin invocari de metode.

Transcript of Sisteme distribuite obiectuale si invocare la distantasoftware.ucv.ro/~cbadica/dadr/cap6.pdf · si...

2013

Sisteme distribuite obiectuale si

invocare la distanta

Capitolul 6

2013

Invocare la distanta

• Protocoale cerere – raspuns (engl. request – reply protocols)

– Ofera suport de nivel coborat pentru emiterea unor cereri de executie a operatiilor la distanta

– Ofera suport direct metodelor RPC si RMI

– Se bazeaza pe serializarea datelor (engl. marshalling) si referinte la distanta (engl. remote references)

• Apel de procedura la distanta (engl. remote procedure call –RPC), aparut in 1984

– Permite unui program client sa apeleze in mod transparent o procedura ce ruleaza intr-un proces server, aflat posibil pe un calculator diferit de calculatorul clientului.

• Invocarea metodelor la distanta (engl. remote method invocation – RMI)

– Permite unor obiecte aflate in procese diferite, posibil pe calculatoare diferite sa comunice prin invocari de metode.

2013

Impachetarea si despachetarea datelor • Structurile de date din programele in executie trebuie serializate sub forma

de mesaje ce constau din secvente de octeti. Structurile de date compuse trebuie liniarizate, iar datele primitive trebuie convertite in format binar.

• Reprezentarile binare ale datelor primitive specifice diverselor platforme pot sa difere. De ex., caracterele se pot codifica Unicode sau ASCII, intregii pot avea lungimi si orientari diferite (big endian si little endian), iar numerele reale pot folosi diverse reprezentari in virgula mobila.

• Exista doua metode de a realiza interschimbul de date:– Valorile sunt convertite din formatul expeditorului in format extern inaintea

transmisiei si reconvertite din formatul extern in formatul destinatarului dupa receptie.

– Valorile sunt transmise direct in formatul expeditorului impreuna cu indicarea explicita a formatului folosit.

• Un format extern comun de reprezentare a datelor primitive si a structurilor de date compuse se numeste reprezentare externa a datelor.

• Procesul de conversie a unei structuri de date intr-o forma convenabila pentru transmisie = impachetare (engl. marshalling). Procesul de reconstruire a unei structuri de date dintr-un format folosit pentru transmisie = despachetare (engl. unmarshalling).

2013

Reprezentari externe

• Formatul de serializare al obiectelor Java.

– Specific limbajului Java

– Fiecare obiect este serializat astfel incat sa poata fi refacut la destinatie

– Serializarea contine si informatie despre clasa obiectului

• Formatul CDR – Common Data Representation) folosit de

CORBA.

– Este un format intermediar in care se traduc structurile de date din

diverse limbaje de programare

• XML

– continut

– Schema

• Ontologii pt inteoperabilitate in Semantic Web

– OWL

2013

Referinte la distanta I

• Cand un client invoca o metoda a unui obiect aflat la distanta –OD (engl. remote object) se va trimite un mesaj de invocare catre procesul server care gazduieste obiectul. Acest mesaj trebuie sa specifice obiectul referit.

• Referinta unui obiect la distanta (engl. remote object reference) – ROD = identificator al unui obiect care este valid intr-un SD.

• In cadrul oricarui mesaj de invocare a unui OD se transmite un ROD.

• ROD trebuie generate astfel incat sa se asigure unicitatea lor in timp si spatiu. Deoarece pot exista mai multe procese ce gazduiesc OD, trebuie ca ROD sa fie unice pe multimea tuturor acestor procese. Chiar si dupa ce un OD a fost sters, ROD corespunzatoare nu se va refolosi pentru a se evita referirea unor obiecte eronate.

2013

Referinte la distanta II

• O reprezentare a unui ROD poate contine: adresa de IP a calculatorului, numarul portului, data crearii OD, un numar local al obiectului ce este incrementat automat de procesul care a creat OD. La aceasta se poate adauga o descriere a interfetei OD.

• In cazul in care un OD exista numai in cadrul procesului care l-a creat si va dispare odata cu distrugerea acestuia, o ROD va putea fi folosita pe post de adresa a obiectului. In cazul in care obiectele pot fi relocate, o ROD nu se va putea utiliza pe post de adresa a obiectului, pentru aceasta existand tehnici speciale.

IP address port number time object numberinterface of

remote object

32 bits 32 bits 32 bits 32 bits

2013

Protocol cerere-raspuns

Request

ServerClient

doOperation

(wait)

(continuation)

Reply

message

getRequest

execute

method

message

select object

sendReply

• Este de obicei o operatie sincrona, clientul blocandu-se pana la primirea raspunsului serverului.

• Este fiabila raspunsul serverului este in acelasi timp si o confirmare de primire a cererii de catre client.

• Pentru mesaje scurte este convenabil de implementat in UDP.

2013

Implementarea unui protocol cerere-raspuns

• Protocolul se bazeaza pe trei primitive de comunicare: doOperation, getRequest si sendReply.

• Sistemele RMI si RPC se bazeaza pe un astfel de protocol.public byte[] doOperation(RemoteRef o, int operationId,

byte[] args)

– se utilizeaza de clienti pentru a invoca o operatie la distanta.

– argumentele sale specifica un OD si metoda care se va invoca, impreuna cu eventualele argumente. Rezultatul executiei acestei metode este primirea unui raspuns. Clientul va impacheta datele inainte de transmisie si le va despacheta dupa receptie.

public byte[] getRequest()

– se utilizeaza de procesul server pentru a prelua o cerere. public void sendReply(byte reply[],InetAddress

clientHost,int clientPort)

– se utilizeaza de procesul server pentru a trimite un raspuns clientului.

2013

Structura mesajelor de cerere-raspuns

• messageType – indica tipul mesajului, 0 ⇒ cerere si 1 ⇒ raspuns.

• requestId – identificator al mesajului. O operatie doOperation a clientului va genera acest identificator, iar serverul il va copia in mesajul de raspuns.

• remoteReference – este o RD impachetata.

• operationId – este un identificator al operatiei invocate. In cazul in care atat clientul cat si serverul folosesc un limbaj comun ce suporta tehnica de reflectie (de exemplu Java), se va putea folosi o reprezentare a unei metode in acel limbaj (de exemplu Method in Java).

• arguments – reprezentarea impachetata a argumentelor metodei.

messageType

requestId

remoteReference

operationId

arguments

int (0=Request, 1= Reply)

int

RemoteRef

int or Operation

array of bytes

2013

Identificatori de mesaje

• Orice schema de gestiune a mesajelor intr-un SD ce presupune asigurarea fiabilitatii si/sau implementarea unui protocol cerere-raspuns cere ca fiecarui mesaj sa i se aloce un identificator unic.

• Un identificator de mesaj are doua parti:

– requestId ce se genereaza prin incrementare de catre expeditor. Se impune ca ciclul de viata al mesajului sa fie mai mic decat timpul in care generatorul revine la 0.

– Identificatorul procesului expeditor: adresa de IP si numar port. Se poate determina dintr-un pachet UDP

• Daca requestId se reprezinta pe n biti atunci valoarea sa maxima este 2n-1. Dupa depasirea valorii maxime, valorile se reiau prin incrementare de la 0. Se impune ca timpul in care se epuizeaza toate valorile posibile sa fie mult mai mare decat durata medie de viata a mesajului in sistem.

2013

Modelul de eroare al protocolului cerere-raspuns

• Daca cele 3 primitive doOperation, getRequest si sendReply sunt implementate peste datagrame UDP atunci ele vor suferi problemele UDP:

– i) erori de omisiune;

– ii) nu se garanteaza livrarea mesajelor in ordinea expedierii.

• In plus protocolul poate suferi de erori ale proceselor. Sa presupunem ca acestea sunt erori de oprire (engl.crash).

2013

Timeout

• Metoda doOperation trebuie sa foloseasca tehnica timeout pentru a trata cazurile de oprire neasteptata a serverului sau de pierdere a mesajelor. In acest caz exista diverse optiuni:

– Retur imediat cu indicarea catre client ca operatia a esuat.

– Eroarea de timeout poate fi cauzata de pierderea mesajelor de cerere sau de raspuns. In acest caz doOperation poate emite cererea in mod repetat pana cand fie primeste un raspuns, fie intarzierea de primire a raspunsului este suficient de mare ca sa existe certitudine ca problema este de la server, nu de la pierderea mesajelor.

2013

Inlaturarea mesajelor de cerere duplicate

• In cazurile in care cererea este retransmisa, serverul o poate receptiona de mai multe ori. De exemplu, serverul poate primi cererea, insa executarea cererii si emiterea raspunsului de catre server poate dura mai mult decat cuanta de timeout.

• Astfel ca exista posibilitatea ca serverul sa execute cererea de mai multe ori.

• Din acest motiv, mesajele cu acelasi requestId trebuie recunoscute si filtrate.

• Daca insa raspunsul nu a fost inca transmis, nu trebuie sa se execute nici o actiune speciala.

2013

Pierderea mesajelor de raspuns

• Daca un server a trimis deja raspunsul la o cerere pe care o primeste in duplicat, el va trebui sa o reexecute daca nu a stocat rezultatul prelucrarii initiale.

• O operatie se numeste idempotenta daca executia sa repetata va produce un acelasi rezultat. De exemplu, adaugarea unui element la o multime este o operatie idempotenta, insa adaugarea unui element la o secventa nu este o operatie idempotenta.

• Un server ale carui operatii sunt toate idempotente nu trebuie sa aiba in vedere masuri speciale pentru evitarea executiei repetate ale aceleeasi operatii.

2013

Istoricul interactiunii

• Pentru serverele care necesita retransmisia raspunsului fara a reexecuta operatia trebuie gestionata istoria interactiunii.

• Se numeste istorie o structura care contine mesajele de raspuns care au fost transmise. O intrare in aceasta structura contine un identificator al cererii, un mesaj de raspuns si identificatorul clientului catre care a fost transmis. Aceasta structura se foloseste pentru a permite serverului sa retransmita mesajele de raspuns la cererile clientilor.

• Pentru ca structura sa nu devina prea mare serverul trebuie sa poata decide cand anumite raspunsuri nu mai trebuie pastrate in istorie. Deoarece un client face o singura cerere la un moment dat, serverul poate interpreta fiecare cerere drept o confirmare a raspunsului anterior. De aceea istoria poate pastra doar ultimul mesaj de raspuns trimis fiecarui client.

• Tot sunt insa probleme daca numarul clientilor este mare.

• Deoarece cand un client se termina el nu va confirma ultimul raspuns primit, acesta va trebui sa fie inlaturat automat din istorie dupa un anumit timp.

2013

Variante de protocoale pentru cereri (I)

Confirmare raspunsRaspunsCerereRRA

RaspunsCerereRR

CerereR

ClientServerClient

Mesaj trimis deNume

2013

Variante de protocoale pentru cereri

• Pentru implementarea apelului de proceduri la distanta (engl.remote procedure call – RPC) s-au folosit trei protocoale, cu semantici diferite in prezenta erorilor de comunicatie: i) protocolul cerere (engl.request – R); ii) protocolul cerere-raspuns – RR; iii) protocolul cerere-raspuns-confirmare raspuns (engl.request-reply-acknowledgement – RRA.– Protocolul R poate folosit cand nu exista valori returnate catre client in urma apelului

si clientul nu are nevoie de confirmare ca procedura a fost executata. Clientul isi poate continua executia imediat dupa transmiterea apelului, nefiind nevoie sa astepte un rezultat sau confirmare

– Protocolul RR este folosit in majoritatea interactiunilor client-server. Nu este necesara confirmarea deoarece raspunsul serverului este interpretat drept confirmare a cererii clientului iar o cerere ulterioara a clientului este interpretata drept confirmare de primire a raspunsului serverului la cererea precedenta.

– Protocolul RRA foloseste un mesaj de confirmare de la client ca a primit raspunsul serverului. Aceasta confirmare este folosita de server pentru a inlatura intrari de istorie. Primirea unei confirmari cu requestId se interpreteaza drept confirmare a primirii raspunsurilor cu un identificator mai mic decat requestId. Astfel, pierderea mesajelor de confirmare a raspunsului nu creaza probleme. In plus confirmarea nu blocheaza clientul.

2013

Interfete (I)

• Limbajele moderne de programare permit organizarea programelor ca multimi de module ce comunica intre ele. Comunicarea se face printr-o interfata pentru fiecare modul in parte.

• Interfata unui modul specifica metodele si variabilele ce pot fi accesate din alte module.

• Modulele unui SD pot rula in procese separate. Astfel ca un modul nu va putea accesa variabilele din alt modul. Chiar daca de exemplu se poate specifica accesul la anumite atribute, accesul propriuzis se va face prin medode getter si setter.

• Tehnicile clasice de transfer a parametrilor (apel prin valoare si apel prin referinta) nu sunt potrivite cand apelantul si apelatul sunt in procese diferite.

2013

Interfete (II)

• Specificarea unei proceduri sau metode intr-o interfata a unui modul intr-un SD se face prin parametrii de intrare/iesire. – Parametrii de intrare sunt transmisi modulului la distanta prin trimiterea valorilor lor

intr-un mesaj de cerere si apoi folosirea lor drept argumente pentru executarea operatiei la server.

– Parametrii de iesire sunt returnati in mesajul de raspuns si sunt utilizati drept rezultat al apelului sau vor inlocui valorile variabilelor corespunzatoare din mediul apelului.

– Cand un parametru este atat de intrare cat si de iesire, valoarea corespunzatoare va fi transmisa atat in mesajul de cerere cat si in cel de raspuns.

• Deoarece pointerii dintr-un proces nu sunt valizi intr-un alt proces, ei nu se transmit ca argumente si nu se returneaza ca rezultate in apeluri la distanta.

• In modelul client-server, serverul furnizeaza o interfata pentru servicii –IS (engl.service interface). In SD obiectuale, un OD furnizeaza o interfata la distanta – ID (engl.remote interface). Intre ele exista diferenta ca metodele dintr-o ID pot transmite obiecte si/sau ROD ca argumente si pot returna obiecte si/sau ROD ca rezultate.

2013

Limbaje de definire a interfetelor

• RMI poate fi integrata intr-un limbaj de programare care permite definirea interfetelor. Astfel parametrii de intrare si iesire pot fi mapati pe utilizarea normala a parametrilor din acel limbaj (de ex.Java RMI). Este utila cand aplicatia distribuita este scrisa intr-un singur limbaj.

• Pot exista diverse servicii deja scrise in C++ sau in alte limbaje de programare. Este benefic sa se asigure accesul la distanta la acestea din programe scrise in limbaje de programare diferite. Astfel s-au proiectat limbaje de definire a interfetelor (engl.interface definition language –IDL) care permit OD scrise in limbaje diferite sa se invoce unele pe altele.

• Un IDL este o notatie pentru interfete. Pentru fiecare parametru al unei interfete se specifica: i) daca este de intrare si/sau de iesire; ii) tipul sau.

• Exemple de IDL:– CORBA IDL

– IDL pentru RPC in DCE (Distributed Computing Environment, al OSF) – DCE IDL, foloseste sintaxa C.

– DCOM IDL (bazat pe DCE IDL), folosit de DCOM (Distributed Common Object Model, al firmei Microsoft).

– WSDL pentru servicii web.

2013

Comunicatia intre obiecte in SD obiectuale

• Modelul obiectual al unui SD extinde modelul obiectual clasic prin OD.

• Trebuie tratate urmatoarele probleme:– Elementele modelul obiectual: pornind de la modelul obiectual clasic, relevante

pentru discutia referitoare la SD obiectuale.

– SD obiectuale: SD ce folosesc modelul obiectual

– Modelul obiectual distribuit: o extensie a modelului obiectual in vederea aplicarii sale SD

– Consideratii de proiectare: i) in timp ce invocarile locale se executa o singura data, ce semantica trebuie adoptata pentru invocarile la distanta ? ii) cum se poate realiza o semantica a RMI cat mai apropiata de cea a invocarilor locale si ce diferente nu pot fi eliminate ?

– Implementare: se arata cum se poate proiecta un nivel middleware aflat deasupra protocolului cerere-raspuns pentru a asigura suportul necesar RMI intre OD ale unei aplicatii distribuite

– Colectarea distribuita a gunoaielor (engl.distributed garbage collection): o prezentare a unui algoritm de colectare distribuita a gunoaielor ce poate fi folosit intr-o implementare a RMI

2013

Modelul obiectual I

• O aplicatie obiectuala consta dintr-o multime de obiecte ce interactioneaza. Un obiect incapsuleaza date si cod. Vom presupune ca accesul la datele private ale unui obiect se poate face numai prin intermediul metodelor sale.

• Referinte la obiecte. Obiectele sunt accesate prin referinte. Invocarea metodelor unui obiect se face prin intermediul referintei la obiect. Obiectul a carui metoda a fost invocata se numeste obiect tinta(engl.target) sau receptor (engl.receiver). Referintele pot fi atribuite variabilelor, transmise ca argumente metodelor sau returnate ca rezultate ale metodelor.

• Interfete. O interfata defineste semnaturile unei multimi de metode. Un obiect furnizeaza o anumita interfata daca clasa sa contine cod ce implementeaza metodele interfetei respective. O clasa poate implementa mai multe interfete. O interfata defineste un tip ce se poate folosi in declaratii de variabile sau parametrii.

2013

Modelul obiectual II

• Actiuni. O actiune se initiaza cand un obiect invoca o metoda a altui obiect. Obiectul receptor executa metoda corespunzatoare si eventual intoarce controlul obiectului apelant. O invocare poate avea doua efecte:

– schimbarea starii obiectului receptor;

– crearea de noi obiecte;

– invocari ulterioare de metode ale altor obiecte.

• Exceptii. Exceptiile sunt metode elegante de a trata erorile, fara complicarea codului. Ele separa clar codul de tratare a erorilorde codul pentru o executie normala.

• Colectarea gunoaielor. Este mecanismul prin care se asigura eliberarea automata a spatiului de memorie ocupat de obiectele care nu mai sunt necesare.

2013

SD obiectuale

• Starea unui obiect este multimea valorilor variabilelor membre. In acest fel starea unui program obiectual este partitionata logic intr-o multime de obiecte. Distribuirea fizica a acestor obiecte in procese si/sau calculatoare diferite este o extensie naturala a modelului obiectual.

• SD obiectuale pot adera la o arhitectura client-server. Obiectele sunt gestionate de servere iar clientii pot invoca metodele acestora folosind RMI. Obiectele din servere pot fi la randul lor clienti ale unor obiecte din alte servere.

• Obiectele dintr-un SD pot fi replicate pentru cresterea tolerantei la defecte si imbunatatirea performantelor sau pot migra pentru cresterea performantei si a disponibilitatii.

• Obiectele pot folosi primitive de sincronizare pentru a-si asigura accesul concurent corect la propriile variabile membre.

• Accesul la obiecte doar prin metode este un prim pas spre independenta de formatul de reprezentare si de caracteristicile fizice ale platformei gazda.

2013

Modelul obiectual distribuit (I)

• Are la baza doua concepte fundamentale: i) referinta unui obiect la distanta (engl.remote object reference) – ROD; ii) interfata la distanta(engl.remote interface) – ID.

• ROD este o extensie a conceptului de referinta a unui obiect la SD. O ROD este un identificator care se poate folosi intr-un SD pentru referirea la un obiect unic. ROD se folosesc pentru invocarea unei metode a unui OD si pot fi transmise ca argumente si intoarse ca rezultate in RMI.

• O ID specifica metodele unui OD care pot fi invocate prin RMI de catre alte obiecte. In CORBA, definirea ID se face folosind limbajul CORBA IDL. In Java RMI, o ID se defineste prin extinderea interfetei Remote.

• Actiunile intr-un SD obiectual pot genera lanturi de RMI.

invocation invocation

remote

invocationremote

local

local

local

invocation

invocation

AB

C

D

E

F

2013

Modelul obiectual distribuit (II)

• Daca un limbaj suporta colectarea gunoaielor, sistemul RMI asociat va trebui sa asigure colectarea gunoaielor corespunzatoare OD. Acest lucru se realizeaza de obicei printr-o cooperare intre colectorul local de gunoaie si un modul care realizeaza colectarea distribuita a gunoaielor.

• Orice invocare la distanta poate esua: i) datorita faptului ca procesul ce contine OD fie s-a oprit, fie este prea solicitat si nu poate raspunde la timp; ii) deoarece mesajul de cerere sau de raspuns s-a pierdut. Din acest motiv o invocare la distanta trebuie sa poata genera o exceptie ce sa indice fie depasirea unui timeout, fie o eroare in executia metodei.

interface

remote

m1

m2

m3

m4m5m6

Data

implementation

remoteobject

{ of methods

2013

Instantierea OD

• AD pot contine OD ce dispun de metode speciale – gen constructor, pentru instantierea altor OD ce pot fi ulterior invocate prin RMI.

• Spre exemplu, obiectul L din figura de mai jos contine o metoda pentru crearea de OD. Astfel ca in urma invocarii la distanta de catre obiectele C si K ale metodei constructor din obiectul L vor fi create 2 OD si anume M si N.

2013

Semantica RMI

• Am aratat ca implementarea functiei doOperation in protocolul RR se poate face in diverse moduri, asigurandu-se diverse nivele ale garantarii livrarii parametrilor:

– Reincercarea de a transmite mesajul de cerere: mesajul de cerere este retransmis pana cand se receptioneaza un raspuns sau se presupune ca serverul s-a oprit.

– Filtrarea duplicatelor: cand se utilizeaza retransmiterea, cererile duplicate sunt filtrate si eliminate de catre server.

– Retransmisia rezultatelor: se pastreaza o istorie a mesajelor cu rezultatele, pentru a permite retransmiterea fara reexecutarea operatiilor la server.

• Diverse combinatii ale acestor variante conduc la o varietate de semantici posbile pentru fiabilitatea RMI din punctul de vedere al apelantului.

Fault tolerance measures Invocation semantics

Retransmit request message

Duplicate filtering

Re-execute procedure or retransmit reply

No

Yes

Yes

Not applicable

No

Yes

Not applicable

Re-execute procedure

Retransmit reply At-most-once

At-least-once

Maybe

2013

Semantica invocarii maybe

• In acest caz apelantul nu va putea sti cu siguranta daca invocarea s-a executat sau nu.

• Aceasta situatie apare cand nu s-a luat nici una dintre masurile de toleranta la defecte. Putem avea urmatoarele tipuri de erori: – i) erori de omisiune in cazul in care mesajul de invocare sau de rezultat s-a pierdut;

ii) erori de oprire in cazul in care serverul ce contine OD se defecteaza.

• Daca mesajul de rezultat nu a fost receptionat dupa scurgerea cuantei de timeout si nu exista reincercari, nu exista certitudinea ca metoda s-a executat sau nu. Se poate insa ca metoda sa se fi executat, dar mesajul cu rezultatul sa se fi pierdut. Mai mult, in cazul unui sistem asincron este posibil ca mesajul de raspuns sa soseasca dupa timeout.

• Aceasta semantica este utila in aplicatiile in care eventualele invocari esuate sunt acceptabile.

2013

Semantica invocarii at-least-once

• In acest caz apelantul fie primeste un rezultat, in cazul in care apelul s-a executat cel putin o data, fie o exceptie ce il informeaza ca nu s-a receptionat nici un rezultat.

• Aceasta semantica se poate realiza prin retransmisia mesajelor de cerere, fapt ce mascheaza eventualele erori de omisiune in mesajele de cerere sau raspuns.

• Sufera de urmatoarele tipuri de erori: i) erori de oprire ale serverului ce contine OD; ii) erori arbitrare, in cazul in care retransmiterea mesajului de invocare poate conduce la receptionarea multipla si executia multipla a metodei invocate, fapt ce poate determina stocarea si returnarea unor valori eronate (se intampla in cazul operatiile neidempotente).

• Aceasta semantica este acceptabila atunci cand metodele ID sunt toate idempotente.

2013

Semantica invocarii at-most-once

• In acest caz apelantul fie primeste un raspuns, in cazul in care apelul s-a executat exact o data, fie o exceptie ce il informeaza ca nu s-a receptionat nici un rezultat.

• Aceasta semantica se poate realiza prin utilizarea tuturor masurilor de toleranta la defecte. Utilizarea reincercarilor va duce la mascarea erorilor de omisiune a mesajelor de invocare sau de rezultat. Masurile aditionale previn erorile arbitrare asigurandu-se ca pentru fiecare invocare o metoda se va executa cel mult o singura data.

2013

Transparenta RMI• In general, invocarile la distanta sunt similare cu invocarile locale din

punct de vedere sintactic.

• Cu toate acestea, invocarile la distanta sunt mai vulnerabile la erori decat invocarile locale. Indiferent de semantica adoptata, exista intotdeauna posibilitatea sa nu se obtina nici un rezultat si in cazul unei erori sa nu se distinga intre o eroare de retea si o eroare in procesul server. Din acest motiv trebuie ca obiectele care efectueaza invocari la distanta sa poata recupera din eventualele erori.

• Astfel se apreciaza ca diferentele dintre invocarile locale si invocarile la distanta trebuie sa existe la nivelul interfetelor. Spre exemplu, in Java RMI, OD se disting prin faptul ca implementeaza interfata Remote. Ele pot genera exceptii RemoteException.

• Implementatorii OD cu interfetele specificate printr-un IDL vor avea in vedere faptul ca aceste obiecte pot fi accesate concurent de clienti multiplii, trebuind sa ia masurile de proiectare corespunzatoare.

• O alta varianta o reprezinta RMI tranzactional – unui apel la distanta is se ataseaza proprietati de tranzactie.

2013

Implementarea RMI

• Consta dintr-o multime de obiecte si module ce includ:

– Modulul de comunicatie

– Modulul de gestiune a ROD

– Software-ul de RMI, ce contine obiectele proxy, skeleton si dispatcher.

2013

Modulul de comunicatie

• Modulul de comunicatie:

– Exista doua module de comunicatie care interactioneaza cu un protocol RR. Aceste module vor folosi doar primele trei campuri din cadrul mesajelor de cerere-raspuns: messageType, requestId si remoteReference (pe post de ROD). Campurile operationId si arguments sunt tratate separat de software-ul de RMI.

– Modulele de comunicatie sunt responsabile sa asigura o anumita semantica, de exemplu at-most-once.

– Modulul de comunicatie din server selecteaza obiectul dispatcher corespunzator clasei obiectului invocat. Pentru aceasta el obtine referinta locala a obiectului de la modulul pentru referinte la distanta, dupa ce i-a transmis ROD din cadrul mesajului de cerere.

2013

Modulul de gestiune a ROD

• Modulul de gestiune a ROD:

– Este responsabil cu traducerea intre referintele locale si ROD si pentru crearea ROD. Pentru aceasta el gestioneaza o tabela de obiecte la distanta (engl.remote object table) – TOD. Aceasta tabela memoreaza corespondenta intre referintele locale in cadrul procesului si ROD. Tabela include: i) cate o intrare pentru fiecare OD continut de procesul server; ii) cate o intrare pentru fiecare obiect proxy local.

– Modulul este apelat de software-ul de RMI, cand se impacheteaza sau despacheteaza ROD.

– Actiunile acestui modul sunt: • i) cand un OD este transmis ca argument sau intors ca rezultat pentru prima oara, acest modul este interogat pentru a crea o ROD pentru acest obiect, acest ROD fiind adaugat la tabela;

• ii) cand se primeste un mesaj de cerere sau raspuns cu un ROD, modulul este interogat pentru a determina referinta locala corespunzatoare. Ea poate fi un obiect proxy sau o referinta la OD propriuzis. Daca ROD nu este in taabela, atunci se creaza un nou obiect proxy si se adauga la tabela.

2013

Software-ul de RMI I

• Este un nivel intermediar intre obiectele aplicatiei si modulelede comunicatie si gestiune ROD.

• Obiectul proxy sau stub. Rolul unui obiect proxy este de a face invocarea metodelor la distanta transparenta pentru client; ele vor delega invocarea catre OD, ascunzand: referirea OD, impachetarea argumentelor, despachetarea rezultatului si expedierea/receptia mesajelor.

• Exista cate un obiect proxy pentru fiecare OD referit dintr-un proces client ce detine o ROD. Clasa obiectului proxyimplementeaza metodele ID ale OD pe care il reprezinta, dar diferit de OD. Fiecare metoda a obiectului proxy impacheteaza o ROD la obiectul tinta, propriul operationId si argumentele sale intr-un mesaj de cerere trimis catre server. Apoi asteapta un mesaj de raspuns, despacheteaza rezultatul si il intoarce obiectului apelant.

2013

Software-ul de RMI II

• Obiectul dispatcher. Un server are cate un obiect dispatcher(dispecer) si un obiect skeleton (schelet) pentru fiecare clasa reprezentand un OD. Obiectul dispecer primeste mesajul de cerere de la modulul de comunicatie si utilizeaza campul operationId pentru a selecta metoda corespunzatoare din obiectul schelet. Obiectele dispecer si schelet utilizeaza acelasi operationId pentru metodele ID.

• Obiectul skeleton. Obiectul schelet implementeaza metodele din ID. Implementarea este destul de diferita de cea din OD. O metoda a scheletului despacheteaza argumentele metodei din mesajul de cerere si invoca metoda corespunzatoare din OD. Apoi asteapta terminarea invocarii, impacheteaza rezultatul, impreuna cu exceptiile, intr-un mesaj de raspuns catre mesajul de cerere expediat de obiectul proxy.

2013

Probleme la implementarea RMI (I)

• Generarea claselor pentru obiectele proxy, dispecer si schelet. Acest lucru se realizeaza automat de catre un compilator de interfete. Spre exemplu:– In CORBA interfetele sunt specificate in CORBA IDL si din ele se genereaza cod

C++ pentru clasele proxy, dispecer si schelet.

– In Java RMI, multimea metodelor unui OD se defineste intr-o interfata Java. Ea trebuie apoi implementata in cadrul clasei OD. Compilatorul de Java RMI genereaza clasele proxy, dispecer si schelet din clasa corespunzatoare OD.

• Programele client si server.– Programul server contine clasele dispecer si schelet, impreuna cu clasele

corespunzatoare tuturor OD gazduite de server (numite si clase servant). In plus, serverul contine si o sectiune de initializare, de exemplu intr-o metoda main in Java

sau C++. Ea este responsabila cu cu crearea si initializarea cel putin a unuia dintre OD gazduite de server. OD aditionale pot fi create ca raspuns la cererile clientilor. Sectionea de initializare poate de asemenea sa inregistreze unele OD cu servicu de nume (engl.binder). In general se inregistreaza un singur obiect, care va fi folosit sa le acceseze pe celelalte.

– Programul client contine clasele obiectelor proxy corespunzatoare OD. Poate folosi servicul de nume pentru a regasi ROD.

2013

Probleme la implementarea RMI (II)

• Metode factory. Am aratat ca ID nu pot contine constructori. Acest lucru inseamna ca OD nu pot fi create prin invocarea la distanta a constructorilor. OD se creaza fie in sectiunea de initializare a serverului, fie printr-o ID proiectata special pentru aceasta. Termenul de metoda factory este folosit pentru a indica o metoda de creare a OD. Un obiect factory este un obiect creat cu o metoda factory. Orice OD care trebuie sa poata crea noi OD la cerere trebuie sa furnizeze metode in propria ID pentru acest scop.

• Serviciul de nume (engl.binder). In general, programele client necesita o modalitate de a putea obtine o ROD pentru cel putin un OD gazduit de server. Un serviciu de nume intr-un SD este un serviciu separat care gestioneaza o tabela cu maparile numelor textuale ale OD la ROD. Acest serviciu este utilizat de programele server pentru inregistrarea OD pe care le gazduiesc si de programele client pentru regasirea lor. Serviciul de nume Java RMI este RMIRegistry, iar servicul de nume CORBA este CORBA Naming Service.

• Fire pe server. Ori de cate ori un obiect executa o invocare la distanta, executia poate conduce la alte invocari de metode, eventual la distanta, inainte de intoarcerea unui rezultat. Pentru a se evita ca o invocare la distanta sa provoace intarzieri ale unor invocari ulterioare din acelasi obiect, in general serverele aloca cate un fir separat pentru executia fiecarei invocari la distanta in parte.

2013

Activarea OD

• Unele aplicatii cer ca informatiile sa supravietuiaca perioade lungi de timp. Nu este insa practic ca obiectele ce gestioneaza aceste informatii sa fie mentinute in cadrul proceselor in executie pentru un timp nelimitat, deoarece ele nu sunt efectiv folosite in tot acest timp. Pentru a se evita pierderea de resurse datorata executiei continue a serverelor ce gazduiesc OD, se poate recurge la pornirea acestor servere ori de cate ori acest lucru este cerut de catre clienti. Procesele care pornesc procese server se numes activatori(engl.activator), de exemplu serviciul Inetd din Linux.

• Un OD este activ cand este disponibil pentru RMI intr-un proces in executie. Altfel el este pasiv, dar poate fi activat. Un OD pasiv consta din 2 parti: i) implementarea metodelor; ii) starea sa in forma impachetata.

• Activarea unui OD consta din crearea unui obiect activ din obiectul pasiv asociat prin crearea unei noi instante a clasei si initializarea variabilelor membre din starea salvata. Activarea poate avea loc la cerere, de exemplu cand obiectul este invocat de alt obiect.

• Un proces activator are urmatoarele responsabilitati: i) inregistrarea obiectelor pasive care sunt disponibile pentru activare. Acest lucru presupune inregistrarea numelor serverelor la URL-urile sau numele fisierelor corespunzatoare obiectelor pasive; ii) pornirea proceselor server si activarea OD din cadrul lor; iii) Monitorizarea locatiilor serverelor pentru OD ce au fost deja activate.

• In CORBA activatorul se cheama implementation repository. In Java RMI exista cate un activator pentru fiecare calculator server.

2013

Persistenta obiectelor

• Un obiect care transcede peste activarile/dezactivarile proceselor server se numeste obiect persistent – OP. Un astfel de obiect este in general gestionat de o memorie de OP – MOP care stocheaza starea sa in forma impachetata pe disc.

• O MOP gestioneaza un numar mare de OP. Ele sunt activate in momentul invocarii lor de catre alte obiecte. Activarea este transparenta din punctul de vedere al obiectului apelant. Cand nu mai sunt necesare in memorie, OP sunt pasivizate si salvate in MOP. MOP are nevoie de o strategie pentru pasivizarea OP (de exemplu la sfarsitul unei tranzactii, cand OP au o stare consuistenta, sau la terminarea programului). MOP realizeaza si o optimizare, salvand doar acele obiecte care au fost modificate de la ultima salvare.

• MOP permit in general organizarea OP sub forma de colectii cu nume interpretabile de un agent uman – URL sau cale in sistemul de fisiere.

• Exista doua abordari pentru a decide daca un obiect este OP sau nu: i) MOP gestioneaza multimea radacinilor colectiilor de obiecte persistente si orice obiect care este accesibil dintr-o astfel de radacina este OP. Aceasta abordare este folosita de Persistent Java. MOP ce folosesc aceasta abordare se bazeaza pe un colector de gunoaie pentru a elimina obiectele care nu mai sunt accesibile dintr-o radacina persistenta; ii) MOP utilizeaza clase speciale pe care se bazeaza persistenta. Un OP apartine unei astfel de subclase. Obiectele care nu mai sunt necesare trebuie sterse explicit (abordare specifica C++).

2013

Probleme la implementarea RMI – localizarea obiectelor (IV)

• In momentul in care un OD ramane in acelasi proces unde a fost creat, pe durata intregului sau ciclu de viata, ROD bazate pe adresa de IP si numarul portului pot fi folosite pe post de adresa a obiectului. Dar exista posibilitatea ca un OD sa calatoreasca in diverse procese, posibil pe calculatoare diferite, in ciclul sau de viata. In acest caz ROD nu mai poate fi folosita pe post de adresa a obiectului. Clientii acestui OD vor avea nevoie atat de ROD cat si de adresa OD.

• Se poate folosi un serviciu de localizare (engl.location service) pentru localizarea unui obiect pe baza ROD. El foloseste o tabela care mapeaza ROD intr-o locatie probabila a OD (probabila deoarece este posibil ca OD poate sa fi migrat intre timp de acolo). Gasirea locatiei se poate baza pe o schema care combina un mecanism de cache cu un mecanism de difuzare (engl.broadcast) si poate fi imbunatatita prin folosirea unor pointeri la locatiile urmatoare (engl.forward location pointer).

2013

Colectarea distribuita a gunoaielor (I)

• Scopul unui colector distribuit de gunoaie (engl.distributed garbage collector) este sa se asigure ca daca o referinta locala la un obiect sau o ROD sunt pastrate intr-o multime distribuita de obiecte, atunci obiectul respectiv va continua sa existe, insa imediat ce nu mai exista obiecte care il refera, obiectul poate fi eliminat si memoria ocupata poate fi eliberata.

• Java foloseste un algoritm de colectare distribuita a gunoaielor bazat pe contorizarea referintelor. Fiecare OD de pe server va trebui informat ori de cate ori o ROD apare, respectiv nu mai este folosita, intr-un proces client, prin intermediul unui obiect proxy.

• Colectorul distribuit coopereaza cu colectorul local in maniera urmatoare:– Fiecare proces server gestioneaza multimea proceselor client (masini virtuale in cazul

Java) care folosesc o ROD a unui OD al sau (multimea holders a acelui OD). Ea se poate pastra ca o coloana suplimentara a tabelei de OD din cadrul sau.

– Cand un client C primeste pentru prima oara o ROD pentru un obiect particular B, va face o invocare addRef(B) catre serverul ce contine B si apoi creaza obiectul proxy. Serverul va adauga apoi pe C la multimea holders a lui B.

– Cand colectorul de gunoaie al clientului C observa ca obiectul proxy al lui B nu mai este accesibil, va executa o invocare removeRef(B). Acest lucru va elimina pe C din multimea holders a lui B.

– Cand multimea holders a lui B devine vida, colectorul local al serverului va elibera spatiul ocupat de B daca nu exista nici o referinta locala la el.

2013

Colectarea distribuita a gunoaielor (II)

• Algoritmul prezentat foloseste o comunicatie cerere-raspuns cu o semantica at-most-once intre invocarile modulelor de gestiune ROD ale celor doua procese. Facem observatia ca apelurile suplimentare datorate algoritmului de colectare nu afecteaza operarea normala a RMI; ele apr doar la crearea, respectiv eliminarea obiectelor proxy.

• Colectorul distribuit Java tolereaza defectele de comunicatie in felul urmator. Operatiile addRef si removeRef sunt idempotente. Daca addRef genereaza o exceptie, fapt ce inseamna ca fie a fost exeutata o singura data, fie nu a fost executata, atunci clientul nu va crea obiectul proxy, dar va executa removeRef. Daca si removeRef esueaza problema se rezolva prin mecanismul de inchiriere.

• Colectorul distribuit Java tolereaza defectele la client prin mecanismul de inchiriere (engl.lease). Serverele inchiriaza OD pe care le gazduiesc clientilor lor pentru o perioada limitata de timp. Este responsabilitatea clientilor sa ceara reinnoirea inchiriererii in mod explicit. Perioada de inchiriere incepe atunci cand un client executa o invocare addRef catre server. Inchirierea se termina fie la o invocare removeRef, fie la expirarea cuantei de timp. Pentru fiecare inchiriere serverul pastreaza identificatorul masinii virtuale a clientului si perioada inchirierii.

2013

Privire de ansamblu a Java RMI

• O aplicatie Java RMI contine doua tipuri de procese: server si client.

• Serverul creaza OD, face disponibile referintele la OD si asteapta clientii sa invoce metode asupra acestor OD.

• Clientul obtine una sau mai multe referinte la OD si invoca metodele lor.

• RMI permite clientului si serverului sa schimbe informatie prin invocare de metode: parametri de la client la server, rezultate de la server la client.

• O aplicatie obiectuala distribuita – AOD realizeaza urmatoarele operatii :– Localizarea OD prin diverse metode: i) procesele server inregistreaza OD in registrul

RMI – RMI registry folosind serviciul de nume al RMI; un client poate regasi un ROD dupa numele OD prin acces la acest registru; ii) procesele pot transmite parametrii OD si apelurile de metode RMI pot returna ROD;

– Comunicarea cu OD: detaliile acestei comunicari sunt rezolvate de software-ul de RMI astfel incat pentru programatorul de aplicatie comunicarea cu un OD sa fie similara invocarii locale a unei metode Java;

– Incarcarea definitiilor de clase pentru obiectele transmise intre procese: Deoarece RMI permite transferul obiectelor intre procese, el asigura ca un proces sa obtina definitia clasei obiectului, cat si datele corespunzatoare obiectului respectiv.

2013

Schema unei aplicatii Java RMI

• Serverul inscrie OD in registru si ii asigneaza/leaga (engl.bind) un nume• Clientul regaseste un OD in registru dupa nume si determina o ROD• Sistemul RMI acceseaza un server Web pentru a descarca definitii de

clase de la server la client sau invers, pentru diverse OD, atunci cand este necesar.

2013

Caracteristici Java RMI I

• Descarcarea dinamica a codului

– Unul dintre avantajele centrale si unice ale RMI este posibilitatea descarcarii dinamice a codului clasei unui obiect atunci cand clasa obiectului nu este disponibila in masina virtuala Java a receptorului obiectului respectiv.

– Clasa unui obiect (semnaturi si comportament) disponibila initial in cadrul unei masini virtuale Java – JVM din sistem poate fi transmisa altei JVM, posibil aflata la distanta.

– Prin transmiterea clasei impreuna cu obiectul, comportamentul obiectului nu se modifica atunci cand obiectul este trimis pe o alta JVM.

– Acest lucru permite posibilitatea extinderii dinamice a comportamentului unei aplicatii.

2013

Caracteristici Java RMI II

• Interfete la distanta, obiecte, metode– O AOD este construita din interfete si clase. Intefetele declara metode si clasele definesc metodele declarate in interfete si posibil alte metode aditionale.

– Un OD trebuie sa implementeze o interfata la distanta – ID:• O ID va extinde interfata java.rmi.Remote

• Fiecare metoda din ID declara o exceptie java.rmi.RemoteException, pe langa alte eventuale exceptii specifice aplicatiei respective

– Accesul la un OD se face prin intermediul unui reprezentativ local al acestuia numit stub sau proxy. Astfel un client va invoca o metoda asupra obiectului stub, acesta fiind responsabil pentru comunicarea cu serverul si executia metodei asupra OD corespunzator pe server.

– Un obiect stub corespunzator unui OD implementeaza acelasi set de ID ca si OD.

2013

Crearea unei AOD folosind Java RMI

• Proiectarea si implementarea componentelor AOD: consta in determinarea arhitecturii aplicatiei incluzand specificarea ce componente sunt locale si ce componente sunt accesibile la distanta:– Definirea ID. Proiectarea ID presupune determinarea metodelor ce vor fi disponibile

la distanta si a parametrilor si valorilor returnate. Daca acestea sunt clase, trebuie stabilite si interfetele acestora. Un client va avea acces doar la ID, nu si la modul de implementare al acestora.

– Implementarea OD. Un OD va implementa una sau mai multe ID. Un OD poate implementa in plus si alte interfete si metode disponibile local. Daca implementarea parametrilor si valorilor returnate de aceste metode necesita clase locale, acestea se vor implementa.

– Implementarea clientilor. Se poate face oricand dupa implementarea OD.

• Compilarea surselor.

• Disponibilizarea claselor in retea. Se refera la disponibilizarea ID si a claselor ce trebuie descarcate de clienti sau servere.

• Pornirea aplicatiei. Presupune rularea registrului RMI, a serverelor si a clientilor.

2013

Proiectarea unui motor generic de calcul

• Se considera o AOD ce implementeaza un motor generic de calcul –MGC. MGC este un OD gazduit pe server ce primeste sarcini de calcul de la clienti, le executa si intoarce rezultatele acestora. MGC permite unuia sau mai multor clienti sa acceseze resursele unei masini mai puternice ce poate avea acces la resurse hardware specializate.

• Aspectul inovativ al MGC este ca sarcinile nu trebuie definite cand MGC este implementat si pornit. Se pot crea noi tipuri de sarcini ce pot fi livrate spre executie catre MGC. Singura restrictie este ca sarcinile saimplementeze o anumita interfata. Codul necesar pentru rularea sarcini poate fi descarcat dinamic de catre sistemul RMI. Ulterior, codul poate fi rulat de masina gazda a MGC.

• Abilitatea de a executa sarcini generice este obtinuta prin: i) natura dinamica a platformei Java, ce permite incarcarea dinamica a claselor; ii) extensia modelului obiectual pentru retele prin RMI. In acest fel MGC poate descarca dinamic si apoi rula codul unei sarcini de calcul, fara sa fie nevoie sa cunoasca dinainte (de exemplu de la compilare) clasa ce contine acel cod.

2013

Proiectarea ID a MGC

• MGC primeste sarcini de la clienti, le executa si le intoarce rezultatul.

• ID a MGC defineste o singura metoda pentru trimiterea spre executie a unei sarcini. O sarcina de executie este un tip parametrizat Task<T> unde T este tipul rezultatului sarcinii de calcul.package compute;

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface Compute extends Remote {

<T> T executeTask(Task<T> t) throws RemoteException;

}

• Interfata unei sarcini defineste o metoda pentru executia sarcinii:package compute;

public interface Task<T> {

T execute();

}

2013

Transferul parametrilor I

• Java RMI foloseste mecanismul de serializare Java pentru transportul obiectelor intre JVM diferite in cazul apelurilor la distanta.

• Un obiect este considerat serializabil daca implementeaza interfata java.io.Serializable. Astfel, clasele care implementeaza interfata Task vor trebui sa implementeze si interfata java.io.Serializable pentru a putea fi transmise ca parametru metodei executeTask(). Acelasi lucru este valabil si pentru obiectele rezultat (corespunzatoare tipului generic T), deoarece ele sunt intoarse ca rezultat de metoda executeTask().

• Orice sarcina ce implementeaza interfata Task poate fi transmisa spre executie catre MGC. O astfel de clasa poate contine si alte date necesare pentru executia sarcinii, cat si alte metode necesare in cadrul executiei.

• Implementarile unor obiecte Task vor putea fi descarcate de Java RMI in JVM unde ruleaza MGC. In acest fel clientii vor putea defini noi sarcini ce pot fi executate pe calculatorul MGC fara a fi nevoie de codul acestor clase instalat pe acest calculator.

• Transferul unei sarcini catre MGC se face cu metoda executeTask(), disponibila tuturor clientilor pentru apel la distanta..

2013

Transferul parametrilor II

• Argumentele si valorile returnate ale metodelor la distanta pot fi de urmatoarele tipuri: obiecte locale, OD, tipuri primitive, etc. Obiectele locale trebuie sa fie serializabile.

• Regulile de transfer sunt urmatoarele:– OD sunt transmise in general prin referinta – ROD. Pe partea de client o ROD

desemneaza obiectul stub asociat OD respectiv.

– Obiectele locale sunt transmise prin valoare, folosind serializarea obiectelor. Se copiaza implicit toate campurile, exceptand campurile static si transient.

• Transferul unui OD prin ROD inseamna ca orice modificare a starii OD prin invocarea unei metode la distanta se va reflecta in OD. Cand se transmite un OD, numai metodele definite de ID sunt disponibile la receptor. Celelalte metode din implementarea clasei obiectului nu disponibile la receptor.

• In schimb transferul unui obiect local presupune transferul prin valoare, fiind creata o copie a obiectului la receptor. Astfel ca orice scmibare a obiectul la receptor nu se va reflecta in originalul copiei la expeditor.

2013

Implementarea unei ID

• O clasa ce implementeaza una sau mai multe ID-uri trebuie in general sa realizeze urmatoarele:– Sa declare ce ID-uri implementeaza

– Sa defineasca cate un constructor pentru fiecare OD

– Sa furnizeze cate o implementare pentru fiecare dintre metodele din ID-urile implementate

• Un program server RMI trebuie sa creeze o multime de OD-uri initiale si sa le ‘exporte’ in cadrul sistemului RMI. Acest lucru inseamna ca ele vor fi disponibile invocarii la distanta.

• Procedura de initializare - setup poate fi incapsulata intr-una dintre metodele implementare clasei unui OD sau poate fi inclusa intr-o alta clasa. Ea trebuie sa realizeze urmatoarele:– Sa creze si sa instaleze un manager de securitate

– Sa creeze si sa ‘exporte’ unul sau mai multe OD-uri

– Sa inregistreze cel putin un OD in registrul RMI (sau intr-un alt serviciu de nume, cum ar fi un serviciu accesibil prin Java Naming and Direcory Interface – JNDI) pentru

2013

Implementarea MGC Ipackage engine;

import java.rmi.RemoteException;

import java.rmi.registry.LocateRegistry;

import java.rmi.registry.Registry;

import java.rmi.server.UnicastRemoteObject;

import compute.Compute;

import compute.Task;

public class ComputeEngine implements Compute {

public ComputeEngine() {

super();

}

public <T> T executeTask(Task<T> t) {

return t.execute();

}

...

2013

Implementarea MGC II

...

public static void main(String[] args) {

if (System.getSecurityManager() == null) {

System.setSecurityManager(new SecurityManager());

}

try {

String name = "Compute";

Compute engine = new ComputeEngine();

Compute stub =

(Compute)UnicastRemoteObject.exportObject(engine, 0);

Registry registry = LocateRegistry.getRegistry();

registry.rebind(name, stub);

System.out.println("ComputeEngine bound");

} catch (Exception e) {

System.err.println("ComputeEngine exception:");

e.printStackTrace();

}

}

}

2013

Initializarea serverului RMI I

• Pasul 1: se instaleaza un manager de securitate (engl.security manager) ce protejeaza accesul la resursele sistemului de un eventual cod de‘neincredere’ (engl.untrusted) descarcat in cadrul JVM. Un manager de securitate are rolul de a determina daca codul descarcat poate accesa sistemul local de fisiere sau poate executa alte operatii privilegiate.

• Daca nu se instaleaza un manager de securitate atunci RMI nu va putea descarca clase dinamic de la alta locatie decat calea locala catre fisierele cu clase – classpath pentru obiectele primite ca argumente sau returnate de invocari la distanta. In acest fel se asigura faptul ca operatiile realizate de codul descarcat sunt conforme cu o politica de securitate.

• Pasul 2: se creaza o instanta a clasei ComputeEngine si se exporta aceasta instanta in sistemul RMI pentru a fi disponibila pentru apeluri la distanta.Al doilea argument (de tip int) al metodei exportObject() specifica optional un port pe care se asculta invocarile la distanta ale OD-ului respectiv. Daca se specifica valoarea 0 (ca in exemplu) atunci portul este anonim. Apelul de ‘export’ returneaza o ROD la OD creat. Tipul sau va fi Compute (adica ID), si nu clasa care implementeaza aceasta ID (ComputeEngine in acest caz).

2013

Initializarea serverului RMI II

• Pasul 3: Se creaza un nume extern pentru OD, “Compute” in acest caz. Apoi se inregistreaza OD creat sub acest nume in registrul RMI.

• Registrul RMI este un tip special de OD care se foloseste pentru a determina referinte la alte OD. De obicei el se foloseste pentru localizarea unui singur OD prin intermediul caruia se vor determina alte referinte la OD-uri disponibile.

• Interfata java.rmi.registry.Registry defineste interfata pentru inregistrarea si regasirea OD-urilor in registrul RMI.

• Pentru sintetizarea unei ROD la un registru RMI aflat la o adresa particulara (adresa IP si port) se foloseste clasa java.rmi.registry.LocateRegistry.

• Invocarea metodei statice getRegistry() a clasei LocateRegistry are ca efect sintetizarea unei ROD la un registru RMI aflat pe calculatorul local si conectat la portul implicit 1099.

• Invocarile registrului RMI primesc ca parametru ROD ale obiectelor cautate respectiv inregistrate.

• Din motive de securitate, o aplicatie poate inregistra obiecte (bind, unbind, rebind) doar intr-un registru ce ruleaza pe acelasi calculator.

2013

Crearea programului client• In cazul nostru trebuie sa implementam doua clase pe partea de client:

– Clasa ComputePi determina OD si invoca sarcina de calcul a lui π.

– Clasa Pi care calculeaza pe π cu un numar prestabilit de zecimale.

• Schema de lucru a programului principal corespunzator clasei ComputePi este urmatoarea:

• Pasii de lucru ai clientului sunt:– Instalarea unui manager de securitate. Acest pas este necesar deoarece receptionarea unei ROD

poate necesita descarcarea unor clase de pe server.

– Determinarea numelui OD. In exemplul nostru se foloseste numele “Compute”.

– Determinarea unui OD corespunzator registrului RMI asociat calculatorului ce gazduieste OD. Se foloseste metoda LocateRegistry.getRegistry(host).

– Regasirea OD folosind registrul RMI cu metoda lookup(name) a clasei Registry.

– Crearea sarcinii de calcul, o instanta a clasei Pi in acest caz. Argumentul constructorului indica numarul de zecimale.

– In final se transfera sarcina spre executie OD-ului ce reprezinta motorul de calcul, folosind metoda executeTask(task).

2013

Observatii asupra programului client

• Toate clasele serializabile trebuie sa declare un camp private static final long serialVersionUID pentru a garanta compatibilitatea la serializare/deserializare intre diversele versiuni ale clasei respective.

• Se observa ca OD ce implementeaza interfata Compute nu are nevoie sa cunoasca dinainte codul clasei Pi pana cand un obiect instanta a clasei Pieste transmis ca parametru al metodei executeTask(). In acel moment codul clasei Pi este incarcat in JVM-ul corespunzator motorului de calcul si apoi se invoca metoda execute() asupra obiectului transmis ca parametru ce reprezinta sarcina de calcul a lui π.

• Rezultatul executiei sarcinii este in acest caz un obiect BigDecimal ce se transmite ca rezultat clientului.

• In concluzie, din punctul de vedere al motorului de calcul, este nerelevant faptul ca sarcina transmisa ca parametru calculeaza valoarea lui π. Aceasta tehnica se putea folosi la fel de bine pentru determinarea unui numar prim foarte mare folosind spre exemplu un algoritm probabilistic. In acest caz executarea sarcinii ar presupune incarcarea altei clase corespunzatoare acestei sarcini de calcul.

2013

Compilarea unei aplicatii Java RMI

• Primul pas este construirea unei biblioteci JAR care sa contina codul interfetelor Compute si Task. Aceste interfete sunt necesare:– Clientului, care va utiliza interfata Compute pentru accesul la OD si va implementa

interfata Task pentru crearea sarcinii de calcul a lui π

– Serverului care va implementa interfata Compute si va executa sarcinile primite folosind interfata Task.

• Pentru aceasta se compileaza sursele celor doua interfete si se construieste bibilioteca JAR.cd c:\__users\Lucru\workshops\InterfataCompute\src

javac compute/*.java

jar cvf compute.jar compute/*.class

• Rezulta fisierul compute.jar care se distribuie in subdirectoarele lib ale proiectelor RMIClient si RMIServer.

• Compilarea celor doua proiecte presupune intai adaugarea la fiecare proiect in parte a bibliotecii compute.jar.

• In versiunile JDK inaintea versiunii 5.0 era nevoie de un pas suplimentar pentru determinarea claselor stub cu compilatorul rmic. Incepand cu versiunea 5.0 acest pas nu mai este necesar.

2013

Manageri de securitate

• Ambele aplicatii client si server au instalat cate un manager de securitate. Din acest motiv fiecare trebuie sa specifice cate o politica de securitate descrisa printr-un fisier special.

• Politica de securitate descrie drepturile de executie pe care le are un anumit in functie de provenienta sa. In aplicatia noastra se dau toate drepturile posibile codului local, si nici o permisiune codului descarcat dintr-o alta sursa. Efectul este ca MGC restictioneaza codul sarcinilor de calcul primite de a putea executa operatii ce ar necesita permisiuni speciale de securitate.

• Spre exemplu, codul sarcinii Pi nu necesita nici o permisune de securitate speciala pentru a putea fi executat.grant codeBase "file:C:/__users/Lucru/workshops/RMIServer/bin/" {

permission java.security.AllPermission;

};

grant codeBase "file:C:/__users/Lucru/workshops/RMIClient/bin/" {

permission java.security.AllPermission;

};

2013

Rularea unei aplicatii Java RMI

• Pasii sunt urmatorii:– Se porneste registrul RMI. Acesta permite unui client sa obtina o referinta initiala la un

OD.– Se porneste serverul

– Se porneste clientul

• Pornirea registrului RMI:start rmiregistry

• Pornirea serverului:java -cp .;../lib/compute.jar -Djava.rmi.server.codebase=file:/C:/__users/Lucru/workshops/RMIServer/lib/compute.jar -Djava.rmi.server.hostname=Toshiba -Djava.security.policy=server.policyengine.ComputeEngine

• Proprietatea codebase defineste o sursa sau locatie de unde se pot incarca clase intr-un JVM. Variabile CLASSPATH defineste un codebase local, in sensul ca defineste una sau mai multe cai din sistemul local de fisiere de unde se pot incarca clase.

• Pornirea clientului:java -cp .;../lib/compute.jar -Djava.rmi.server.codebase=file:/c:/__users/Lucru/workshops/RMIClient/bin/ -Djava.security.policy=client.policy client.ComputePi Toshiba 45