Wykład 7: RPC, RMI, CORBA
Transkrypt
Wykład 7: RPC, RMI, CORBA
Narzędzia do tworzenia programów rozproszonych • • • • Wprowadzenie: idee i pojęcia Remote Procedure Call Java Remote Method Invocation Common Object Request Broker Architecture 1 Aspekty programowania rozproszonego • Współdziałanie (interoperability) modułów programowych na różnych maszynach. • Wielokrotne wykorzystanie (reusability) modułów programowych. • Standaryzacja de facto (przemysłowa) lub de iure (niezależna). 2 Struktura oprogramowania rozproszonego klient serwer kod programisty namiastka namiastka implementacja programisty implementacja programisty szkielet serwera mechanizm zdalnych wywołań mechanizm zdalnych wywołań systemowa biblioteka funkcji komunikacyjnych systemowa biblioteka funkcji komunikacyjnych kod programisty kod generowany automatycznie funkcje komunikacji biblioteki narzędzia 3 Struktura oprogramowania rozproszonego • Aplikacje działające w środowisku rozproszonym mogą byd napisane w różnych językach programowania. • Interfejs do operacji zdalnych jest wtedy definiowany w specyficznym języku narzędzia programowania rozproszonego. • Interfejs służy do wygenerowania zestawu procedur w konkretnym języku programowania. 4 Model klient - serwer • Częśd wspomnianych procedur będzie wykonywana przez serwer tj. program świadczący usługę wykonania operacji. • Częśd wspomnianych procedur będzie wykonywana przez klienta tj. program na komputerze zdalnym: – są to tzw. namiastki (stubs) operacji wykonywanych przez serwer. 5 Namiastki • Procedury stub mają prawie dokładnie taką samą liczbę i typy parametrów jak w deklaracji interfejsu, ale służą wyłącznie do przekazania argumentów wywołania do serwera, a następnie odebranie wyników zdalnej procedury tam wykonanej. • Kod odpowiedzialny za organizację i konwersję przekazywanych danych (marshalling code) jest generowany automatycznie. 6 Serwer • Procedury wygenerowane automatycznie dla serwera to także marshalling code • w trakcie obsługi zlecenia następuje wywołanie implementacji tj. procedury, która faktycznie wykona operacje zdefiniowane w interfejsie. • Stworzenie implementacji jest zadaniem programisty. • Szkielet serwera jest tworzony automatycznie. 7 Ograniczenia rodzaju parametrów • Przesyłanie danych wymaga każdorazowo podania ich rozmiaru (tablice). • Przesyłanie wskaźników i referencji nie ma sensu, bo przestrzenie adresowe serwera i klienta są różne. • Przesyłanie deskryptorów plików, uchwytów okien nie ma sensu, bo obiekty te mają charakter lokalny. 8 Opakowywanie procedur • Wrapping – przystosowywanie istniejących procedur do pracy w środowisku rozproszonym. właściwa implementacja właściwa implementacja procedura opakowująca procedura opakowująca szkielet serwera 9 Komunikacja: repozytorium serwerów • Klient musi odnaleźd odpowiedni serwer. • Zapewnia to specjalny proces serwerowy zarządzający katalogiem (repository) serwerów działających w danym systemie. • Udostępnia on klientom identyfikatory operacji wykonywanych przez poszczególne zarejestrowane serwery. • Inne niezbędne usługi (services): – zawiadujące przesyłaniem komunikatów, prawami dostępu do obiektów, bezpieczeostwem, transakcjami. 10 Serwisy klient A klient B Strzałki wskazują kierunek przepływu danych serwis komunikatów katalog serwerów serwer 1 - serwis obowiązkowy - wykonanie operacji na serwerze serwer 2 serwer 3 - serwis fakultatywny - zlecenie usługi rozgłaszania komunikatów - komunikacja z serwisem (jednorazowa) • Serwery rejestrują się w katalogu serwerów; klienci pobierają identyfikatory serwerów. • Serwery i klienci zgłaszają akces do wspólnego kanału komunikatów. 11 Przykład: zadanie obliczeniowe • Rozwiązanie układu równao: A·x = b • Algorytm iteracyjny – konieczna dominacja diagonali macierzy A, tzn. i i j|aij|<|aii|: xn+1 = xn – D(Axn – b) gdzie: {x1,x2,...} – kolejne przybliżenia rozwiązania x; dij=0 dla i j oraz dii=1/aii. 12 Rozproszona implementacja • Wektor x dzielony na N podwektorów (tyle, ile jest jednostek obliczeniowych). • Każda jednostka przechowuje lokalnie własne przybliżenie rozwiązania i modyfikuje lokalny podwektor. • Uzyskane wyniki są przekazywane do jednostki nadrzędnej, która modyfikuje aktualne przybliżenie rozwiązania globalnego. 13 Remote Procedure Call • Mechanizm RPC został opracowany przez firmę Sun; obecnie znormalizowany przez ISO/IEC. • Nie jest przystosowany do programowania obiektowego. • Powszechnie stosowany w systemach Unix. • Wspólny sposób reprezentacji podstawowych typów danych – eXternal Data Representation. 14 External Data Representation • XDR – ma za zadanie zniwelowad różnice w reprezentacji typów danych w różnych maszynach. • RPC zawiera funkcje służące do kodowania i dekodowania typów prostych, łaocuchów znaków, tablic, unii i wskaźników języka C w standardzie XDR. • Dane są zapisywane/odczytywane z potoku XDR tj. strumienia bajtów. 15 Potok XDR • Dane są zapisywane w kwantach 4-bajtowych. • Dane w potoku znajdują się w kolejności wywołao funkcji je kodujących. • Nie ma możliwości testowania typów danych w potoku – kolejnośd dekodowania musi odpowiadad kolejności kodowania. • Funkcje kodujące/dekodujące – filtry XDR. 16 Filtry XDR • Operacje kodowania i dekodowania są wykonywane przez te same funkcje. • Pierwszym argumentem filtru XDR jest zawsze wskaźnik na strukturę reprezentującą potok XDR. • Liczba i typy pozostałych argumentów zależą od typu kodowanych danych. 17 Źródła danych potoków XDR • Deskryptor pliku: – kodowanie – zapis do wskazanego pliku, – dekodowanie – odczyt z pliku, – tworzenie potoku – funkcja xdrstdio_create. • Obszar pamięci operacyjnej: – kodowanie – zapis do pamięci od wskazanego adresu, – dekodowanie – odczyt z pamięci, – tworzenie potoku – funkcja xdrmem_create. • Dowolne źródło danych – poprzez dostarczone z zewnątrz funkcje zapisu i odczytu: – kodowanie – wywołanie funkcji zapisującej dane, – dekodowanie – wywołanie funkcji dostarczającej dane, – tworzenie potoku – funkcja xdrrec_create. 18 Tryb działania potoku • Obowiązkowym parametrem funkcji tworzenia potoku jest tryb, w jakim będzie pracował potok XDR: – XDR_ENCODE – do kodowania danych, – XDR_DECODE – do dekodowania danych, – XDR_FREE – do zwalniania pamięci przydzielonej podczas dekodowania. 19 Nagłówki filtrów XDR • Nagłówki filtrów dla typów prostych języka C: bool_t xdr_type(XDR *pStream, type *pObject); gdzie type jest jednym z typów: char, int, long, float, double, void lub enum. • Argument pObject wskazuje na kodowaną bądź dekodowaną zmienną. • Podobnie wyglądają nagłówki filtrów dla łaocuchów znaków, tablic, unii i wskaźników (mogą one mied większą liczbę argumentów, w zależności od danego typu). 20 Kodowanie struktur • Dla wszystkich pól struktury, w kolejności definiowania wywoływane są odpowiednie filtry. • Brak uniwersalnego filtru dla struktur. • Definicji struktur dokonuje się w języku RPC. • rpcgen – program automatycznie generujący odpowiednie filtry dla struktur: – tworzy plik nagłówkowy z definicjami struktur w języku C, – oraz plik z kodem źródłowym stosownych filtrów. 21 Kodowanie argumentów • Przy korzystaniu z RPC przekazywane argumenty należy umieścid w strukturze. • Opis struktury w języku RPC MyIterationArguments.x : 22 Uwagi: • Linia 3 – tablica float o nieokreślonej liczbie elementów – przybliżenie rozwiązania x*. • Linia 4 – indeks początkowy obliczanego podwektora. • Linia 5 – indeks koocowy obliczanego podwektora. Wykonanie polecenia: $ rpcgen MyIterationArguments.x • Powoduje utworzenie plików w języku C: – MyIterationArguments.h – definicja struktury, – MyIterationArguments_ xdr.c – kod źródłowy filtru XDR. 23 MyIterationArguments.h (fragment) 24 Plik 'MyIterationArguments_ xdr.c' • Zawiera kod filtru dla struktury MyIterationArguments: – sekwencja wywołao xdr_array (przetwarzanie tablicy float), – dwukrotne wywołanie xdr_int (przetwarzanie indeksów), – jeśli przetwarzanie zakooczy się pomyślnie to zwracane jest 1 (TRUE), w przeciwnym razie 0 (FALSE). 25 example1encoder.c • Program kodujący argumenty i zapisujący je do pliku: 26 Uruchomienie: • Po skompilowaniu i uruchomieniu programu powstaje plik binarny "example1.arg": $ gcc -o encoder example1encoder.c MyIterationArguments_xdr.c • Zawartośd pliku w postaci 16-wej: $ od -x example1.arg rozmiar tablicy 0000000 0000 0500 803f 0000 0040 0000 4040 0000 0000020 8040 0000 a040 0000 0000 0000 0000 0400 0000040 indeks początkowy indeks końcowy 27 example1decoder.c • Program dekodujący dane i wykonujący obliczenia: 28 Uruchomienie: • Po skompilowaniu i uruchomieniu programu następuje wypisanie kolejnego przybliżenia: $ gcc -o decoder example1decoder.c My*.c $./decoder 1.000000 2.000000 3.000000 4.000000 5.000000 -0.666667 1.255556 -0.343704 1.402740 0.654657 29 Automatyczne kodowanie wskazao • W razie zdefiniowania w XDR struktury zawierającej wskaźniki na inne struktury podczas kodowania sprawdzane jest, czy dany wskaźnik jest równy NULL, a jeśli nie, to wywoływany jest odpowiedni filtr, kodujący wskazywaną strukturę. • W przypadku struktur cyklicznych ze względu na rekurencyjne wywoływanie kolejnych filtrów występuje przepełnienie stosu. 30 Dekodowanie struktur z wskaźnikami • Podczas dekodowania struktury, jeśli wskaźnik nie był NULL, to przydzielana jest pamięd dla wskazywanej struktury i wywoływany jest filtr ją dekodujący. • Tę niejawnie przydzieloną pamięd należy zwalniad wywołując funkcję: void xdr_free(xdrproc_t proc, char *objp) – proc – filtr, który dekodował dane, – objp – wskaźnik na dekodowaną strukturę. 31 Wymiana danych w RPC • Wszystkie filtry są skojarzone (via xdrrec_create) z funkcjami transmisji danych via gniazdka IP. • Mechanizm jest ukryty przed programistą w funkcjach bibliotecznych. • Rozproszona natura aplikacji narzuca ograniczenia na języki definicji RPC. 32 Identyfikatory procedur w RPC • Identyfikowanie procedury przez nazwę jest niewystarczające. • Potrzebny jest np. – Numer programu, wykonującego zdalną procedurę: • wg firmy Sun numery 0x20 000 000 – 0x3F FFF FFF są zalecane do wykorzystania. – Numer wersji w obrębie programu. – Numer procedury w ramach wersji: • Numer 0 jest zastrzeżony (rpcgen dodaje taką procedurę standardowo do testowania działania serwera). 33 Ograniczenia RPC • Zdalna procedura przyjmuje tylko jeden argument (może on byd strukturą). • Wszelkie zmiany dokonane przez procedurę w obrębie jej argumentu pozostają lokalne i nie są przekazywane z powrotem do klienta. • Do klienta jest przekazywany jest wynik procedury jako dowolny typ XDR – np. także struktura. 34 Schemat tworzenia aplikacji rozproszonej interfejs.x kod źródłowy programisty kod generowany automatycznie interfejs.h interfejs_clnt.c interfejs_xdr.c interfejs_svc.c klient.c serwer.c skompilowany moduł skonsolidowany program generacja (rpcgen) kompilacja (cc -c) klient serwer konsolidacja (cc) 35 Generowanie szkieletu aplikacji • W pliku *.x należy umieścid definicje struktur (tylko tych niezbędnych do komunikacji klienta z serwerem) i deklaracji zdalnych procedur, jakie ma wykonywad serwer. • Program rpcgen tworzy jeden plik nagłówkowy i trzy pliki ze źródłami w C: – *_clnt.c – z namiastkami zadeklarowanych procedur, – *_xdr.c – z filtrami XDR, – *_svc.c – ze szkieletem serwera. • Namiastki mają zawsze dwa argumenty: – wskaźnik na strukturę wysyłaną do serwera, – jednoznaczny identyfikator serwera. 36 Identyfikowanie serwerów • Katalog serwerów – obowiązkowy serwis odwzorowujący parę {identyfikator_programu, identyfikator_wersji} w konkretny numer portu (gniazdka IP). • Program, uruchamiany przy starcie systemu i nasłuchujący na porcie 111, przechowuje katalog serwerów i odpowiadających im portów: – Linux: portmap, Solaris: rpcbind. 37 Serwisy RPC • Lista zarejestrowanych serwerów: $ /usr/bin/rpcinfo –p • W oparciu o RPC opracowano wiele usług sieciowych np. NFS – Network File System. 38 Inne schematy komunikacji • Rozgłaszanie (broadcast) komunikatów bez możliwości otrzymania odpowiedzi: – funkcja rpc_broadcast. • Wywołanie zdalnej procedury bez czekania na odpowiedź: – ustawienie czasu oczekiwania na 0 funkcją clnt_control. • Wywołanie zwrotne (callback): – klient wywołuje zdalną procedurę i nie czekając na wynik sam staje się na pewien czas serwerem; – serwer wywołuje zdalną procedurę udostępnioną przez klienta. 39 Przykład • Rozproszona realizacja rozwiązania układu równao A·x = b. • Częśd obliczeniową będzie realizowad wiele procesów serwerów RPC. • Zarządzad przydziałem zadao będzie wielowątkowy program nadrzędny: – każdy wątek będzie klientem RPC, – synchronizacja obliczeo poprzez synchronizację wątków. 40 inicjacja Schemat zarządca pobranie argumentów obliczenia zapisywanie wyników klienci 1 ... N ... serwer 1 serwer 2 synchronizacja 41 Schemat iteracji • Wątek główny uruchamia N wątków – klientów RPC. • Klienci pracują w pętli nieskooczonej: – pobranie aktualnego rozwiązania x* (globalnego – zastosowanie zamka), – wykonanie procedury RPC, znajdującej fragment nowego rozwiązania, – uaktualnienie fragmentu globalnego rozwiązania (zamek), – bariera (wersja synchroniczna) – czekanie, aż pozostałe wątki dotrą do bariery 42 Plik 'MyIterationProg.x' • Deklaracja interfejsu w języku RPC: 43 Generacja szkieletu • Program rpcgen tworzy pliki: MyIterationProg.h, MyIterationProg_clnt.c, MyIterationProg_svc.c, MyIterationProg_xdr.c. • W pierwszym z nich (MyIterationProg.h) pojawiły się wiersze: • Ostatni deklaruje procedurę my_iteration_proc_1_svc, którą należy zaimplementowad po stronie serwera (ciało funkcji main serwera już powstało). • Po stronie klienta ciało procedury my_iteration_proc_1 już powstało, należy napisad funkcję main klienta. 44 Implementacja serwera 45 Uruchomienie serwera: • Po skompilowaniu uruchomiony serwer rejestruje się w katalogu serwerów i oczekuje na zgłoszenia klientów: $ /usr/bin/rpcinfo -p program vers proto port 536871032 1 udp 32769 536871032 1 tcp 32770 – Numer programu wyrażony dziesiętnie jest identyczny z numerem nadanym w pliku definicji interfejsu RPC. Można wywoład procedurę testową: $ /usr/bin/rpcinfo -t localhost 536871032 1 program 536871032 version 1 ready and waiting 46 Implementacja klienta • Kod źródłowy podzielony na dwie części: – funkcja main, definicje struktur pomocniczych i deklaracje globalne, – kod wątku klienta: wywołania RPC i synchronizacja wątków POSIX z użyciem zamków (chroniących sekcje krytyczne) i barier. - kod odpowiedzialny za sekcję krytyczną - kod odpowiedzialny za barierę - pozostały kod związany z wątkami 47 example2client.c (cz. I) 48 example2client.c (cz. II) 49 example2client.c (cz. III) 50 example2client.c (cz. IV) 51 Uruchomienie klienta: • Po skompilowaniu klient należy uruchomid podając jako parametry nazwy dwóch komputerów, na których pracują serwery: $ ./example2client komputer1 komputer2 Thread 8194: -0.666667 1.255556 3.000000 4.000000 5.000000 Thread 16387: 1.000000 2.000000 -0.355556 1.412222 0.647704 Thread 8194: 0.665877 -0.087411 -0.355556 1.412222 0.647704 Thread 16387: -0.666667 1.255556 0.416988 0.104114 0.156218 – Program działa w nieskooczonośd, aż do jego przerwania przez operatora (Ctrl-C). – W wersji asynchronicznej mogą się kolejno pojawid dwa wiersze wygenerowane przez ten sam wątek. 52 Plik 'example2server.c' 53 Plik 'example2client.c' 54 Plik 'MyIterationProg.x' 55 RPC - uzupełnienie • Możliwe jest uruchamianie serwera przez demon inetd: – działanie serwera regulują opcje użycia rpcgen. • Standardowy klient RPC (utworzony przez funkcję clnt_create) nie jest uwierzytelniany przez serwer. • Uwierzytelnianie w RPC (zależne od implementacji): – prosta autoryzacja (login, itp.), – szyfrowanie DES (rpc-secure), – autoryzacja Kerberos. 56 Java Remote Method Invocation • Mechanizm RMI jest częścią języka Java opracowanego przez firmę Sun (Java Development Kit). • Umożliwia wywoływanie metod obiektów istniejących w maszynie wirtualnej Javy przez obiekty znajdujące się w innej maszynie wirtualnej – komunikacja via protokół TCP. • Obiekty zdalne jak i lokalne są identyfikowane standardowo, przez referencje. 57 Java RMI 58 Java RMI 59 Interfejsy i klasy RMI 60 Ograniczenia RMI • Problemy rozproszonego bezpieczeostwa danych, synchronizacji, odśmiecania pamięci. • Możliwe jest tylko wykonywanie metod zdalnego obiektu, a nie dostęp do jego pól (zmiennych). • Metody RMI muszą byd zadeklarowane w interfejsie rozszerzającym interfejs (extends) java.rmi.Remote: – wygenerowane zostaną odpowiednie procedury (marshalling code). 61 Serwer • Serwer musi implementowad interfejs deklarujący metody udostępniane zdalnym klientom: – musi on rozszerzad (dziedziczyd) klasę java.rmi.Remote, – wszystkie zadeklarowane metody muszą jawnie obsługiwad wyjątki klasy RemoteException, – serwer musi rozszerzad klasę java.rmi.Server.UnicastRemoteObject. – konstruktor serwera musi również jawnie obsługiwad wyjątki klasy RemoteException. • Aby umożliwid klientom odnalezienie serwera musi on się zarejestrowad w serwisie RMI-Registry: java.rmi.Naming.rebind("rmi://host/Name", ServerObject) – stosuje się rebind, ponieważ bind() zostało użyte automatycznie przez konstruktor klasy macierzystej UnicastRemoteObject. 62 Klient • Uzyskuje referencję do zdalnego obiektu (serwera) poprzez użycie znanej mu nazwy usługi serwisu Naming: java.rmi.Naming.lookup(name) – zwraca referencję do lokalnego obiektu-namiastki, – metoda lookup() zwraca referencję uniwersalnego typu Object, a więc jest konieczne rzutowanie (cast) na typ docelowy. • Wykorzystuje zdalny serwer wywołując metody uzyskanego lokalnego obiektu-namiastki. 63 Interfejs RMI • Metody zadeklarowane w interfejsie muszą byd zaimplementowane w klasie zawierającej metody organizujące transport danych (są one dostarczane przez RMI): – różne tryby pracy serwera metod. • Kod serwera RMI powinien implementowad public static void main(String) lub jej odpowiednik dla apletów. 64 Inicjacja serwera RMI • Funkcja main może (ale nie musi) byd jedną z metod klasy implementującej metody wywoływane zdalnie. • Minimalna procedura inicjująca serwer RMI: – tworzy przynajmniej jeden obiekt klasy implementującej zdalne wywołania, – rejestruje ten obiekt w katalogu serwerów. 65 Komunikacja RMI • Obiekt RMI jest gotowy do działania natychmiast po utworzeniu. • Serwis katalogowy przechowuje i udostępnia klientom nazwy zarejestrowanych obiektów- serwerów w postaci URL: rmi://nazwa_komputera/nazwa_interfejsu • Klient może uzyskad referencję do lokalnej namiastki obiektu zdalnego wywołując statyczną metodę lookup klasy java.rmi.Naming i podając jako argument nazwę, pod jaką obiekt jest zarejestrowany: – rezultatem jest referencja do interfejsu java.rmi.Remote, – powinna ona byd rzutowana na referencję do interfejsu implementowanego przez zdalny obiekt. 66 Przykład • Serwer RMI realizujący pojedynczą bezargumentową metodę, która nie zwraca żadnego rezultatu. • Po uruchomieniu serwer ma się zarejestrowad w katalogu obiektów. • Klient, po nawiązaniu kontaktu z serwerem zleci wywołanie zdalnej metody, która wyprowadzi określony napis na standardowe wyjście serwera. 67 Plik 'MyIterationInterface.java' • Plik z definicją interfejsu: 68 Plik 'MyIterationImplementation.java' • Kod klasy implementującej interfejs i inicjującej pracę serwera: 69 Szkielet serwera • Kompilacja: $ javac MyIterationInterface.java MyIterationImplementation.java • Generowanie klasy ze szkieletem serwera i namiastkami: $ rmic MyIterationImplementation – powoduje utworzenie plików MyIterationImplementation_Skel.class, MyIterationImplementation_Stub.class zawierających odpowiednie klasy. 70 JDK 1.5 • Od wersji JDK 1.5 nie jest konieczne generowanie szkieletu i namiastek za pomocą kompilatora rmic. • W razie braku obecności pregenerowanych klas maszyna wirtualna wygeneruje je dynamicznie w oparciu o wykryte interfejsy zdalnych metod klasy implementacji – spowoduje to jej załadowanie. • W celu zachowania kompatybilności z klientami utworzonymi w środowisku JDK <1.5 należy jawnie tworzyd namiastki kompilatorem rmic. 71 Uruchomienie serwera: • Uruchomienie katalogu serwerów (z innego katalogu niż zawierający pliki klas namiastek): $ rmiregistry port -Djava.rmi.server.codebase=file:///path/ – port – numer portu, na którym nasłuchuje katalog (standardowo 1099), – path – ścieżka do katalogu z namiastkami. • Uruchomienie serwera: $ java -Djava.security.policy=/path1/java.policy -Djava.rmi.server.codebase=file:///path2/ MyIterationImplementation – path1 – ścieżka do katalogu z plikiem konfiguracji zabezpieczeo. – path2 – ścieżka do katalogu z klasami serwera. 72 Plik 'java.policy' • Konfiguracja podstawowa konfiguracji zabezpieczeo (pełny dostęp): 73 • Plik java.policy: Przykład – punktem odniesienia przydzielanych uprawnieo jest katalog wskazany przez właściwośd program.codebase, – zezwala na odczyt właściwości client.name, – zezwala na otwarcie połączeo sieciowych powyżej portu 1024, – zezwala na odczyt i zapis pliku wskazanego przez examples.file, – zezwala na nasłuch na dynamicznie przydzielonym porcie. 74 example3client.java • Implementacja klienta RMI: 75 Uruchomienie klienta: • Po skompilowaniu, zakładając, że serwer pracuje na komputerze komputer1, uruchomienie klienta: $ java example3client komputer1 spowoduje wypisanie przez serwer na swoim terminalu napisu: "Hello, world!" 76 Menedżer obiektów • Obiekt zarządzający dostępem do puli serwerów: – pozwala na działanie wielu serwerów tej samej klasy na tym samym komputerze. • Zwraca klientom referencje do serwerów za pomocą mechanizmu RMI: – definiuje nowy interfejs z metodą zwracającą klientowi referencję do jednego z zarządzanych obiektów. 77 Schemat działania menedżera obiektów (1) 1 katalog menedżer Na komputerze działa katalog (rmiregistry) Uruchomienie JVM i w niej menedżera obiektów maszyna wirtualna komputer 2 komputer 1 78 Schemat działania menedżera obiektów (2) 2 katalog Menedżer obiektów rejestruje się w katalogu (rebind) menedżer maszyna wirtualna komputer 2 komputer 1 79 Schemat działania menedżera obiektów (3) 3 katalog menedżer maszyna wirtualna komputer 2 Klient uruchomiony na innym komputerze uzyskuje z katalogu referencję do menedżera na serwerze. maszyna wirtualna komputer 1 80 Schemat działania menedżera obiektów (4) 4 katalog menedżer maszyna wirtualna komputer 2 Klient wywołuje zdalną metodę w menedżerze. Menedżer może wykorzystać istniejący obiekt lub utworzyć nowy maszyna wirtualna komputer 1 81 Schemat działania menedżera obiektów (5) 5 katalog Klient otrzymuje referencję do namiastki, kanał komunikacyjny jest utrzymywany przez RMI menedżer maszyna wirtualna komputer 2 maszyna wirtualna komputer 1 82 Schemat działania menedżera obiektów (6) 6 katalog Klient wywołuje zdalne metody za pośrednictwem namiastki. menedżer maszyna wirtualna komputer 2 maszyna wirtualna komputer 1 83 Własności interfejsu Remote • Mechanizm przekazywania referencji do obiektów implementujących interfejs Remote jako argumentów wywołania metod lub rezultatów ich działania. • Rozproszone odśmiecanie pamięci (distributed garbage collection): – obiekt implementujący Remote może byd usunięty gdy nie odnoszą się do niego referencje w maszynach lokalnej i zdalnych. 84 Mechanizm serializacji • Obiekty nie implementujące Remote i typy proste przekazywane poprzez wartośd (na odległej maszynie tworzone są ich kopie). • Wszystkie klasy będące argumentami lub wynikami metod RMI muszą implementowad interfejs java.io.Serializable: – jego metoda writeObject zapisuje zawartośd obiektu do strumienia bajtów, a readObject rekonstruuje zawartośd obiektu ze strumienia bajtów, – możliwa jest serializacja typów prostych, tablic obiektów dających się serializowad i obiektów klasy String. 85 Przykład • Rozproszona realizacja rozwiązania układu równao A·x = b. • Zarządzad przydziałem zadao będzie wielowątkowy program nadrzędny. • Częśd obliczeniową będzie realizowad wiele procesów serwerów RMI: – zdalna procedura przyjmuje jeden argument – obiekt zawierający m. in. bieżące rozwiązanie, – wynikiem będzie obiekt tej samej klasy. 86 MyIterationParameters.java • Klasa argumentu (i wyniku) zdalnej procedury: 87 MyIterationInteface.java • Interfejs zdalnej procedury: 88 Java Native Interface • Umożliwia wykorzystanie modułu napisanego w C i opakowanie go w celu wykorzystania w aplikacji Java. • JNI pozwala m. in. deklarowad metody w Javie, a implementowad je w języku C. • Taka metoda jest deklarowana jako native. • Program javah generuje na podstawie deklaracji plik nagłówkowy z deklaracją w C. • JNI umożliwia uzyskiwanie referencji do obiektów maszyny wirtualnej, wywoływanie ich metod i sygnalizowanie wyjątków. 89 Korzystanie z JNI • Dla programu w Javie: – implementacje wszystkich procedur native muszą byd umieszczone w bibliotece dołączanej dynamicznie, – funkcje ładujące bibliotekę należy wykonad jawnie. • Dla procedury w języku C: – obiekty maszyny wirtualnej mogą byd przez nią przemieszczane pod inny adres, – w czasie odwołao do nich należy je czasowo unieruchomid za pomocą odpowiednich funkcji. 90 kompilacja (cc –c lub javac) generacja szkieletu i namiastki (rmic) kod źródłowy programisty Schemat tworzenia aplikacji moduły wspólne generacja nagłówka (javah -jni) MyIterationParameters.java kod generowany automatycznie skompilowany moduł MyIterationInterface.java biblioteka dynamiczna konsolidacja biblioteki (ld -shared -o) example4client.java MyIterationImplementation.java moduły serwera MyIterationImplementation.h moduły klienta MyIterationImplementation.c MyIteration.c libmyIterationWrapper.so 91 Zastosowanie JNI • Klasa implementująca metodę zdalną zawierad będzie deklarację funkcji native. • Implementacja metody zdalnej będzie przystosowywała parametry, aby móc wywoład w/w funkcję. • Funkcja wywoła pozostałe konwersje parametrów i wywoła funkcję obliczeniową MyIteration. • Wyniki odwrotną drogą wrócą do klienta. 92 MyIterationImplementation.java • Kod klasy implementującej zdalną procedurę. 93 Generacja szkieletu RMI i nagłówków JNI • Po skompilowaniu kodu serwera należy wygenerowad szkielet serwera i namiastkę dla klienta programem rmic: $ rmic MyIterationImplementation – powstają pliki: MyIterationImplementation_Skel.class, MyIterationImplementation_Stub.class • Następnie należy wygenerowad plik nagłówkowy JNI programem javah: $ javah -jni MyIterationImplementation – powstaje plik: MyIterationImplementation.h 94 Plik 'MyIterationImplementation.h' (fragment) • W pliku nagłówkowym znajduje się deklaracja funkcji opakowującej, którą należy zaimplementowad. 95 MyIterationImplementation.c 96 Uruchomienie serwera: • Moduły języka C należy skompilowad do postaci biblioteki ładowanej dynamicznie: $ gcc -c *.c $ ld -shared -o libmyIterationWrapper.so *.o • Aby uruchamiany serwer odnalazł i załadował bibliotekę dynamiczną należy wcześniej ustawid zmienne środowiskowe (por. opcję -cp): $ export LD_LIBRARY_PATH=/path $ java -cp . -Djava.security.policy=/path/java.policy -Djava.rmi.server.codebase=file:///path/ MyIterationImplementation 97 Kod klienta • Realizacja wielowątkowa. - kod odpowiedzialny za sekcję krytyczną - kod odpowiedzialny za barierę - pozostały kod związany z wątkami 98 example4client.java (cz. I) 99 example4client.java (cz. II) 100 example4client.java (cz. III) 101 example4client.java (cz. IV) 102 Uruchomienie klienta: • Po uruchomieniu serwerów na odpowiednich komputerach można uruchomid klienta: $ java example4client komputer1 komputer2 Thread komputer1: -0.6666667 1.2555557 3.0 4.0 5.0 Thread komputer2: -0.6666667 1.2555557 -0.3437039 1.4027405 0.6546566 Thread komputer1: 0.6586601 -0.080675356 -0.3437039 1.4027405 0.6546566 Thread komputer2: -0.6666667 1.2555557 0.4121416 0.10546201 0.15754676 Thread komputer1: 0.14908929 0.21676 0.4121416 0.10546201 0.15754676 • Zatrzymanie programu jest możliwe przez przesłanie odpowiedniego sygnału (np. via Ctrl-C z konsoli). 103 Superserwer RMI • Możliwe jest uruchamianie serwera RMI na żądanie: – w celu wykonania danego zlecenia (wykonania zdalnej metody), – ewentualnie z oczekiwaniem przez określony czas na kolejne zgłoszenia, – wymaga to działania demona zdalnego aktywowania obiektów rmid (od JDK 1.2), – uruchamia on maszynę wirtualną, a w niej serwer obsługujący żądanie. 104 Przykład - c.d. • Klient wczytuje klucz publiczny (publicKey) z pliku; – przy wywołaniu metody zdalnej „opakowuje” parametry i dołącza podpis cyfrowy: • Serwer wczytuje klucz prywatny (privateKey) z pliku; – przed wykonaniem metody zdalnej weryfikuje tożsamośd klienta, który nadesłał podpisany obiekt (sObj): – zmienna isFriend będzie miała wartośd true, jeśli podpis został wykonany za pomocą prawidłowego klucza. 105 CORBA • CORBA – Common ORB Architecture • ORB – Object Request Broker Wikipedia: W najbardziej generalnym ujęciu brokerem jest podmiot świadczący określone usługi, z reguły pośrednictwa, działający na cudzy rachunek… • Standard komunikacji aplikacji w środowisku rozproszonym realizowanej za pośrednictwem wspólnego brokera ORB. • Opracowany przez Object Management Group: http://www.omg.org/ 106 Interfejs Corby • Moduły programowe komunikują się z innymi za pośrednictwem własnych brokerów. • Wszyscy brokerzy komunikują się ze sobą w jednakowy sposób (common). • Moduł poznaje charakterystykę interfejsu innego modułu: – poprzez dynamiczne pobranie definicji interfejsu ze standardowego serwisu: katalogu interfejsów (interface repository), – poprzez statyczne wkompilowanie do własnego kodu definicji wymaganych interfejsów. 107 CORBA 108 Interface Definition Language • IDL – uniwersalny język opisu interfejsu. • Definicje interfejsów są niezależne od języków programowania używanych do stworzenia modułów. • Odpowiednie narzędzia przekształcają definicje sformułowane w języku IDL na ich odpowiedniki w danym języku: – m. in. C,C++, Smalltalk, Ada, Cobol, Java. 109 Własności IDL • Język IDL umożliwia definiowanie: – modułów zawierających deklaracje typów, stałych, wyjątków, interfejsów oraz definicje innych modułów. • Deklaracje interfejsów mogą zawierad: – deklaracje typów, stałych i wyjątków, – deklaracje atrybutów i operacji. • Możliwe jest wielobazowe dziedziczenie między interfejsami. 110 • Typy proste: Typy IDL – całkowite: short (-215 215-1), long (-231 231-1), long long (263 263-1) oraz ich odpowiedniki bez znaku(unsigned) o zakresach odpowiednio 0 216-1, 0 232-1, 0 263-1; – zmiennoprzecinkowe: float, double i long double (wg standardu ANSI/IEEE 754-1985); – znakowe: char – jednobajtowy dla znaków ISO 8859-1, wchar – (wide) dla znaków w innych standardach, octet – jednobajtowy, nie podlegający konwersjom; – logiczny: boolean (wartości TRUE lub FALSE); – dla danych dowolnego typu: any. 111 Typy IDL • C.d. : – sekwencje (a la wektory) (sequence) w/w; – łaocuchy znaków: string, wstring; – typ fixed – reprezentujący 31-znakową liczbę stałoprzecinkową. • Typy pochodne: – struktury (struct), unie (union), wyliczeniowe (enum); – wyjątki (exception) – CORBA definiuje standardowy zestaw wyjątków zgłaszanych przez operacje. • Rekurencja w definicjach struktur nie jest dozwolona 112 Przykład Definicja błędna (niedozwolona rekurencja) struct Node { long nodeValue; Node nextNode; } Definicja poprawna (użycie sequence dozwolone) struct Node { long nodeValue; sequence<Node> nextNode; } 113 Definicje operacji • Przypominają deklaracje funkcji w języku C. • Każdy z parametrów jest poprzedzony obowiązkowym atrybutem, określającym kierunek przepływu danych: – in – parametr wejściowy (dane przesyłane od klienta do serwera), – out – parametr wyjściowy(od serwera do klienta), – inout – parametr wejściowy i wyjściowy (dane przesyłane w obu kierunkach). • Listę zgłaszanych wyjątków, poprzedzoną dyrektywą raises, umieszcza się w nawiasach okrągłych za listą argumentów. 114 Operacje asynchroniczne • Standardowo CORBA wykonuje operacje synchronicznie tj. blokuje klienta do czasu otrzymania wyników. • Definicja operacji, która ma byd wykonywana asynchronicznie, musi byd poprzedzona dyrektywą oneway: – nie może ona mied parametrów z atrybutami out, inout ani zgłaszad wyjątków, – deklaracja zwracanego typu musi byd void. 115 Ograniczenia IDL • Implementacja zadeklarowanych w IDL operacji jest dokonywana w językach docelowych. • Odwzorowanie niektórych konstrukcji IDL w językach docelowych może byd bardzo rozbudowane. • CORBA dopuszcza tworzenie alternatywnych wersji odwzorowao np. pod kątem określonych kompilatorów. 116 Operacje wykonywane przez referencje • Obiekty, implementujące operacje zdefiniowane w interfejsie, są identyfikowane przez referencje. • Umożliwiają one wykonanie pewnych prostych, niezależnych od języka operacji: – tworzenie swoich duplikatów (Object duplicate()) i usuwanie się (void release()) – należy używad tych operacji do powielania i usuwania referencji, – sprawdzanie, czy referencja odnosi się do jakiegokolwiek obiektu (boolean is_nil()) i czy odnosi się do tego samego obiektu, co inna referencja (boolean is_equivalent(in Object other_object)). 117 Operacje wykonywane przez referencje (2) • Corba umieszcza w/w operacje w module CORBA, w interfejsie Object (CORBA::Object). • Wszystkie wymienione operacje są wykonywane w lokalnej maszynie: – za pomocą operacji is_equivalent można tylko potwierdzid identyfikowanie przez dwie referencje tego samego zdalnego obiektu, – Jednoznaczne zaprzeczenie tożsamości, bez komunikacji ze zdalną maszyną, nie jest możliwe. 118 Object Adapter • Warstwa pośrednicząca między brokerem, a obiektami implementującymi interfejsy. • Standardowa wersja (CORBA 2.3) – Portable OA (POA); – generuje referencje do obiektów implementujących interfejsy, odpowiada za prawidłową interpretację referencji; – Udostępnia obiektom informację o kliencie, która może byd wykorzystana do uwierzytelniania, – realizuje określoną politykę wykonywania operacji na obiektach. 119 Model referencyjny Corby 120 Portable Object Adapter 121 Cykl realizacji żądania w POA 122 Sposoby obsługi żądania • Zależne od producenta implementacji Corby – ogólny podział serwerów: – jednowątkowe – mogą byd (lub nie) jednocześnie klientami oraz mogą szeregowad inne zlecenia w trakcie obsługi bieżącego; zawsze obsługują tylko jedno zlecenie w danej chwili, – wielowątkowe – tworzą nowy wątek dla każdego nowego żądania; pozwala to jednemu klientowi na jednoczesne wywołanie kilku metod serwera. 123 Przykład • Rozproszona realizacja rozwiązania układu równao A·x = b. • Wersja jednowątkowa: – w pełni funkcjonalny serwer, – klient zdolny do komunikacji tylko z jednym serwerem, – język docelowy: C++. 124 Plik 'MyIterationInterface.idl' • Operacja myIteration zdefiniowana w interfejsie MyIterationInterface (w języku IDL): 125 Implementacje Corby • Dalsze tworzenie aplikacji Corby wymaga wyboru konkretnego produktu ją implementującego. • Poniżej zastosowano pakiet ORBacus 4.1: – implementacja CORBA 2.3, – stworzony przez Object-Oriented Concepts, – dawniej projekt typu open source, teraz Iona, – implementacja dla języków C++ i Java. 126 Odwzorowanie interfejsu IDL • Narzędzie idl odwzorowuje interfejs IDL do języka C++: $ idl MyIterationInterface.idl • Generowane są pliki: – zawierające namiastkę serwera oraz jego szkielet: MyIterationInterface.h, MyIterationInterface.cpp, MyIterationInterface_skel.h, MyIterationInterface_skel.cpp. 127 Pliki interfejsu (1) • MyIterationInterface.h – myVector jest synonimem sekwencji danych typu CORBA::Float (sekwencja jest realizowana przez szablon (template) ORBacusa); – interfejs MyIterationInterface został odwzorowany w klasę o tej samej nazwie, dziedziczącą po CORBA::Object; – zadeklarowano w niej jako virtual metodę myIteration. 128 MyIterationInterface.h (fragmenty) 129 Pliki interfejsu (2) • MyIterationInterface.cpp – implementacja metody myIteration; jest to implementacja klienta: – kod pakujący argumenty, – wywołanie funkcji request, – kod rozpakowujący wyniki. 130 MyIterationInterface.cpp (fragmenty) 131 Pliki interfejsu (3) • MyIterationInterface_skel.h – deklaracja klasy szkieletu serwera, POA_MyIterationInterface, dziedziczącej po PortableServer::ServantBase; – ponowna deklaracja metody myIteration, tym razem jako czystej – wirtualnej. 132 MyIterationInterface_skel.h (fragmenty) 133 Pliki interfejsu (4) • MyIterationInterface_skel.cpp – implementacja szkieletu; – nie ma tu implementacji metody zadeklarowanej w pliku nagłówkowym jako czysta – wirtualna. • Programista powinien zaimplementowad myIteration w klasie dziedziczącej po POA_MyIterationInterface i PortableServer::RefCountServantBase. 134 MyIterationInterface_skel.cpp (fragment) 135 Plik 'MyIterationImplementation.h' • Plik nagłówkowy klasy-implementacji: 136 Plik 'MyIterationImplementation.cpp' • Implementacja metody myIteration (z wykorzystaniem MyIteration.c): 137 example5server.cpp 138 Dygresja: • CORBA nie narzuca dostawcy sposobu implementacji referencji do obiektu. • Wywołanie operacji, zdefiniowanej w IDL jako op w interfejsie A, wyglądało: ref->op() : – identyfikator ref oznacza tu referencję i może byd typu A_var lub A_ptr, – referencja A_var usuwa wskazywany przez nią obiekt (lub namiastkę) w chwili gdy sama jest usuwana lub nadawana jest inna wartośd (zarządzanie pamięcią), – np. w ORBacusie referencja A_ptr jest zdefiniowana jako zwyczajny wskaźnik na obiekt klasy A, referencja A_var jest obiektemkontenerem z przedefiniowanym operatorem „->”. 139 Uruchomienie serwera: • Kompilacja serwera z użyciem bibliotek ORBacusa : $ c++ -I. -I$(ORBACUS_DIR)/include -L$(ORBACUS_DIR)/lib -o server example5server.cpp MyIterationImplementation.cpp MyIterationInterface.cpp MyIterationInterface_skel.cpp MyIteration.c -lOB -lJTC -ldl -lpthread (należy podstawid ścieżki do katalogów pakietu ORBacus 4.1.x) • Po uruchomieniu serwer tworzy w bieżącym katalogu plik „MyIteration.ref”, w którym zapisuje swoją referencję i rozpoczyna oczekiwanie na zlecenia od klienta. 140 example5client.cpp 141 Uruchomienie klienta: • Kompilacja: $ c++ -I. -I$(ORBACUS_DIR)/include -L$(ORBACUS_DIR)/lib -o client example5client.cpp MyIterationInterface.cpp lOB -lJTC -ldl -lpthread (należy podstawid ścieżki do katalogów pakietu ORBacus 4.1.x) • Przed uruchomieniem należy dostarczyd plik z referencją. $ ./client 1.000000 2.000000 3.000000 4.000000 5.000000 -0.666667 1.255556 -0.343704 1.402740 0.654657 0.658660 -0.080675 0.145622 0.318677 0.001189 142 Odwzorowanie IDL do Javy • Język Java posiada pakiet implementujący Corbę: org.omg.CORBA. • Przykład – implementacja klienta w Javie. • Wygenerowanie interfejsu: $ $(JDK)/bin/idlj MyIterationInterface.idl (należy podstawid ścieżkę do katalogu pakietu JDK) • Powstają pliki: MyIterationInterface.java, myVectorHolder.java, myVectorHelper.java, MyIterationInterfaceOperations.java, MyIterationInterfaceHolder.java, MyIterationInterfaceHelper.java, _MyIterationInterfaceStub.java. 143 Interfejs Corba – Java (1) • Interfejs (w sensie Cobry) został odwzorowany w interfejs Javy: – plik MyIterationInterfaceOperations.java deklaruje metodę myIteration: o typach argumentów będących odpowiednikami typów prostych IDL, za wyjątkiem snapshot, typu myVectorHolder (ponieważ snapshot jest deklarowany jako inout). 144 Interfejs Corba – Java (2) • Corba wymaga, aby wszystkie parametry transmitowane w Javie do klienta były osadzone w obiektach – uchwytach (przyrostek Holder). • Również obiekty implementujące MyIterationInterface, jako potencjalne parametry innych operacji, są wyposażone w taką klasę – uchwyt. 145 Interfejs Corba – Java (3) • Dla wszystkich klas, których obiekty mogą byd transmitowane między maszynami, muszą zostad wygenerowane definicje klas z kodem serializującym i deserializującym; – mają one przyrostek Helper. • W pliku _MyIterationInterfaceStub.java jest tworzona namiastka operacji, która zleca serwerowi wykonanie zadania, przekazuje parametry i odbiera wyniki. 146 example5client.java 147 Uruchomienie klienta (Java): • Kompilacja: $ $(JDK)/bin/javac example5client.java My*.java my*.java _My*.java (należy podstawid ścieżkę do katalogu pakietu JDK) • Przed uruchomieniem należy dostarczyd plik z referencją. $ $(JDK)/bin/java example5client 1.0 2.0 3.0 4.0 5.0 -0.6666667 1.2555557 -0.3437039 1.4027405 0.6546566 0.6586601 -0.080675356 0.14562233 0.3186774 0.001188775 148