PZR420 - ćw - temat B

Obiekty rozproszone RMI w języku Java.
RMI = Remote Method Invocation

literatura i inne materiały ...

Krótki opis technologii RMI

.....................................................................................................................

.....................................................................................................................

.....................................................................................................................

Dla obiektu RMI trzeba zdefiniować interfejs zawierający metody dostępne dla klientów, który dziedziczy z interfejsu java.rmi.Remote:
public interface OdleglyObiekt extends Remote
{
int powolnaMetoda(int skok) throws RemoteException;
}

.....................................................................................................................

Serwer musi zawierać klasę implementującą interfejs OdległyObiekt:

class OdleglaKlasa
implements OdleglyObiekt, Serializable
{
// konstruktor
OdleglaKlasa(String s) throws RemoteException
{
super();
try {
UnicastRemoteObject.exportObject(this);
// eksportujemy obiekt
// dzięki temu obiekt będzie "odległy"
// (exportObject() musi byc PRZED rebind())

Naming.rebind(s,this);
// rejestrujemy obiekt w rmiregistry

} catch(Exception e) {
System.err.println("sss: OdleglaKlasa(String); blad !!! "+e.getMessage());
}

// implementacja interfejsu OdleglyObiekt
private int licznik=0;
public int powolnaMetoda(int skok) throws RemoteException
{
for(int i=0; i<10; i++) {
licznik=licznik+skok;
System.out.println("sss: powolnaMetoda(); licznik="+licznik);
try {Thread.sleep(100);} catch(Exception e){};
}
return licznik;
}
}

.....................................................................................................................

Serwer musi wykonać następujące czynności:

  1. utworzyć obiekt - robi to w metodzie sss.main,
  2. wyeksportować go - robi to w konstruktorze OdleglaKlasa; eksportowanie obiektu powoduje że staje się on odległym obiektem (gdyby nie został wyeksportowany to odwołania klienta do tego obiektu spowodowałyby kopiowanie obiektu od serwera do klienta i obiekt stałby się lokalny !)
  3. zarejestrować w rmiregistry - robi to także w konstruktorze OdleglaKlasa.
  4. po wykonaniu tych czynności serwer nie kończy działania lecz oczekuje na klientów
public class sss
{
public static void main(String args[])
{
//System.setSecurityManager(new RMISecurityManager());
// chwilowo nie używamy SecurityManagera !

try {
OdleglyObiekt oo= new OdleglaKlasa("moj_obiekt");
// tworzymy obiekt

} catch(Exception e) {
System.err.println("sss: blad !!! "+e.getMessage());
}
}
}
Uwaga 1: Zamiast wywoływać jawnie UnicastRemoteObject.exportObject() wystarczy że OdległaKlasa dziedziczy z klasy UnicastRemoteObject, której konstruktor eksportuje obiekt (jednak wtedy OdległaKlasa nie może dziedziczyć z żadnej innej klasy ...).

Uwaga 2: Jeśli NIE dziedziczymy z UnicastRemoteObjecta to powinniśmy samodzielnie przedefiniować w OdleglaKlasa niektóre metody klasy Object: hashCode, equals, toString [w podanych przykładach tego się nie robi ...]; patrz też klasa RemoteObject.

.....................................................................................................................

Klient musi wykonać następujące czynności:

  1. uzyskać referencję do obiektu RMI
  2. wywoływać metody na rzecz obiektu RMI
public class kkk
{
   public static void main(String args[])
{
//System.setSecurityManager(new RMISecurityManager());

try {
OdleglyObiekt oo = (OdleglyObiekt)Naming.lookup(
"rmi://localhost/moj_obiekt");
/* uzyskujemy ref do obiektu RMI
trzeba oczywiście podać prawdziwy adres maszyny
na której działa rmiregistry i serwer
*/

System.out.println("kkk: oo.powolnaMetoda()="+oo.powolnaMetoda(1));
// wywołujemy metodę obiektu RMI

} catch(Exception e) {
System.err.println("kkk: blad !!! "+e.getMessage());
}
}
}

.....................................................................................................................

Klasy które muszą być dostępne (poprzez CLASSPATH) dla składników aplikacji RMI:

Uwaga: jeśli używamy mechanizmu opisanego tutaj to nie wszystkie klasy muszą  być dostępne!

.....................................................................................................................

Czynności programisty podczas pisania aplikacji używającej RMI:

(obrazek z książki Java & Corba)

.....................................................................................................................

Co można przekazać do i co może zwrócić metoda obiektu RMI :

public interface OdleglyObiekt extends Remote
{
PrzykladowaKlasa Eksperyment1(PrzykladowaKlasa pk1, PrzykladowaKlasa pk2)
throws RemoteException;
/* metoda zwraca obiekt klasy PrzykladowaKlasa który może być
obiektem odległym (wyeksportowanym) lub nie ...
w tym drugim przypadku obiekt zostanie skopiowany od serwera do klienta

metoda pobiera jako parametry dwa obiekty klasy PrzykładowaKlasa
które zostaną skopiowane od klienta do serwera
*/

}

.....................................................................................................................

Różnica między wyeksportowanym i nie-wyeksporowanym obiektem znajdującym się po stronie serwera:

Zakładamy ze X jest obiektem RMI dostępnym dla klienta (np za pośrednictwem rmiregistry). Niech Y będzie obiektem RMI po stronie serwera dostępnym poprzez metodę X.drugiObiekt().
Co się stanie gdy klient wywoła X.drugiObiekt().metoda1(); ???

.....................................................................................................................
 

Zadanie 10
Uruchom przykład programu RMI rmi4.zip, a następnie:
  1. Zaprojektuj eksperyment który pokaże że jeśli 2 klientów uruchamia metodę na rzecz tego samego obiektu RMI, to są oni obsługiwani na osobnych wątkach (przerób implementację powolnaMetoda() !).
  2. Sprawdź i opisz różnicę w działaniu tego programu gdy drugiObiekt:
  3. Zbadaj jak są obsługiwane wyjątki które pojawiają się w metodach obiektu RMI; w tym celu dodaj następującą metodę do interfejsu OdległyObiekt:
        public void generujeBlad() throws RemoteException
        {
            throw new RemoteException("sztucznie wygenerowany blad ...");
        }
    i zobacz jak się ona zachowuje z pkt widzenia klienta ...

W sprawozdaniu umieść odp na pytania, kod, wydruki produkowane przez programy.

Wskazówki do zadania 10:
Czynności podczas uruchamiania programu rmi4:

  1. klient i serwer mają własne katalogi ...
  2. w katalogu serwera:
  3. w katalogu klienta:

Zadanie 11 ["Odległa" wersja problemu producenta & konsumenta]
Zaprogramuj obiekt RMI "OdległyBufor" (nazwa interfejsu), rozwiązujący problem producenta i konsumenta.
Obiekt RMI powinien mieć metody:

void WstawElement(int el) 
int PobierzElement()
// jak widać do bufora wstawiamy jedynie liczby "int" !

Bufor przechowujacy elementy (typu FIFO) powinien byc w tablicy 50 integerow.
Powinien istnieć pomocniczy obiekt RMI "TwórzOdległeBufory" dostępny przez nazwę "producent_konsument" w rmiregistry, zawierający metodę:

OdleglyBufor nowyOdległyBufor()
// mogą z niej korzystać dwa wątki tego samego procesu ...

tworzącą obiekty OdległyBufor na żądanie (cos w rodzaju "fabryki obiektow").
Przygotuj eksperyment pokazujący że to wszystko działa.
Niech producent produkuje liczby 1..1000, a konsument wyswietla co konsumuje.
Uwaga: producent i konsument musza byc (w zadaniu 11) watkami jednego programu, aby mialy dostep do wspolnego odleglego bufora.
Do sprawozdania wstaw kody źródłowe klas oraz wydruki eksperymentów ...

Zadanie 12
Do poprzedniego zadania dodaj metodę:

    OdleglyBufor nowyOdległyBuforZNazwa(String nazwa)

która pozwala korzystać z bufora dwóm różnym programom (dostają się od tego samego buforu podając tę samą nazwę).


.....................................................................................................................

Dynamiczne ładowanie potrzebnych klas w RMI - java.rmi.server.codebase

Opis dynamicznego ładowania klas z dokumentacji java.sun.com.

Wstępne przypomnienie pewnych cech języka Java:

Klient i serwer aplikacji RMI muszą mieć dostęp do kodu wielu klas, przykładowo:

RMI posiada specjalny mechanizm dynamicznego ładowania potrzebnych klas przez sieć, przy czym klasy mogą być ładowane w obu kierunkach: od serwera do klienta i w przeciwnym kierunku!

Aby mechanizm ten działał należy:

  1. serwer musi podać URL z którego mogą być ładowane klasy serwera (w szczególności pieniek); URL podaje się w właściwości java.rmi.server.codebase, np w taki sposób:
            java -Djava.rmi.server.codebase=file:///D:\Java\jdk1.2.2\Przyklad\rmi4a\SERWER\ klasa_serwera
                // pod Windows
            java -Djava.rmi.server.codebase=file:///home/mhanckow/katalog/ klasa_serwera
                // pod Linux-em
            java -Djava.rmi.server.codebase=http://qqq.www.eee/~jkowalski/moje_klasy klasa_serwera
    Uwaga: sciezka do katalogu musi się kończyć przez "/" !
  2. podobnie klient musi podać URL do swoich klas (np klas obiektów przekazywanych jako parametry metod odległego obiektu)
  3. jeżeli klient i serwer NIE pracują na tej samej maszynie i nie mają dostępu do tego samego systemu plików to trzeba się posłużyć jakimś niezależnym sposobem kopiowania plików, np serwerem httpd lub ftp (wtedy użyjemy codebase=http://...);
  4. rmiregistry MUSI być tak uruchomione żeby NIE MIAŁO(!!!) dostępu do klas serwera poprzez CLASSPATH
  5. interfejs odległego obiektu koniecznie musi mieć słowo "public" (!!!)
  6. program, który przyjmuje obce klasy javowe MUSI mieć włączony SecurityManager!
  7. [implementacja mechanizmu dynamicznego ładowania klas] gdy obiekt jest przesyłany przez sieć to towarzyszy mu informacja GDZIE można znaleźć kod klas tego obiektu, informację tę definiujemy właśnie w codebase ...

.....................................................................................................................

Zadanie 13 [Zastosowanie dynamicznego ładowania klas]
Do przykładu rmi4.zip dodaj zdalną metodę:

PrzykladowaKlasa Eksperyment1(PrzykladowaKlasa pk1, PrzykladowaKlasa pk2);

PrzykładowaKlasa powinna zawierać jakieś dane i metodę pokaz() wyświetlającą te dane; ponadto konstruktor powinien wyświetlać napis informujący o swoim uruchomieniu. Niech klient uruchamia tę metodę podając jako parametry obiekt klasy PrzykładowaKlasa, oraz obiekt podklasy PrzykładowaKlasa o nazwie PrzykładowaKlasa2. Metoda Eksperyment1() powinna uruchamiać pokaz() dla swoich parametrów, podobnie klient powinien uruchomić pokaz() dla obiektu zwróconego przez Eksperyment1().
Klasy których potrzebują klient i serwer powinny być dynamicznie ściągane przy pomocy mechanizmu "codebase". Należy wykorzystać serwer atos i katalog html_public i w nim (w odp podkatalogach) umieścić wszystkie potrzebne klasy. Proszę spróbować uruchomić klienta i serwera na innych maszynach (np na lokalnym linixie i na atosie, ew na 2 lokalnych linuxach). Do sprawozdania proszę oprócz kodu w Javie wstawić także wydruki eksperymentów dowodzące że wszystko działa poprawnie ...

Zadanie 14 ["OdległyBufor" pozwalający wstawiać i pobierać dowolne obiekty]
Rozwiąż zadanie odległy prod & kons ale tym razem zezwala się na wstawianie i pobieranie dowolnych obiektów (niekoniecznie liczb "int"); tak więc interfejs odległego obiektu powinien mieć metody:

void WstawElement(Serializable el) 
Serializable PobierzElement()

Koniecznie użyj mechanizmu "codebase" do kopiowania klas. Zaprojektuj odp przykłady pokazujące że Twoje rozwiązanie działa poprawnie ...


.....................................................................................................................

Zadanie 15 (*) [Model farmer/worker przy pomocy Java/RMI]
Zaprojektuj i zaprogramuj obiekt RMI który potrafi wykonywać zadania paralelizowalne,
tj takie które można podzielić na n- zadań wykonujących się równolegle na osobnych wątkach.
Usługa ta ma byc uniwersalna tj NIE ma być przystosowana jedynie do konkretnego zadania.
Zadanie podzielone na części przez klienta powinno przychodzić do obiektu RMI w postaci
ciągu obiektów ze wspólnym interfejsem zawierającym metodę "Object Oblicz()" (to są właśnie pracownicy).
Obiekt RMI (czyli farmer) powinien uruchamiać metodę oblicz na osobnych wątkach; po zakończeniu pracy przez
wszystkich pracowników powinien zwracac wynik w postaci listy obiektów (klient będzie wiedział
co zrobić z tymi obiektami) ...
Jako zastosowanie rozwiąż problem znajdowania minimum funkcji, przy czym podzadania dla workerów
są generowane przez rozłączne przedziały osi X na których workerzy szukają minimum.
Wskazówka: obiekty z zadaniami oraz wyniki zadań przesyłaj przy pomocy klasy Vector ...

Zadanie 16 (*) [Słownik w cyklu obiektów RMI]
Zaimplementuj słownik, którego elementy (czyli pary (klucz, wartość)) są trzymane w listach,
które są w posiadaniu obiektów RMI,
które to obiekty tworzą cykl (tj każdy obiekt ma ref. do następnika i do poprzednika).
Istnieje metoda szukaj(klucz), zwracająca poszukiwaną wartość (ob. javy zwracany przez wartość).
Jeśli wywołamy X.szukaj(klucz) dla pewnego ob. X w cyklu, to sprawdza ona czy szukany element
znajduje się na liście ob. X, jeśli nie to mają być przeszukiwane listy innych obiektów...
Istnieje też metoda dodaj(klucz, wartość) dodająca element do listy wierzchołka cyklu tak dobranego,
aby listy były zbalansowane (miały w miarę równe długości).
Dodatkowe wymagania:
1. odporność na usunięcie pojedynczego wierzchołka cyklu (cykl obiektów się zmniejsza);
2. automatyczne ładowanie wszystkich potrzebnych klas;
3. obiekty cyklu znajdują się w różnych procesach (w chwili tworzenia cyklu
    można pomocniczo umieszczać ref do ob. w rejestrze, ale zaraz potem usunąć te wpisy...).

Zadanie 17 [porównanie XDR i serializacji javowej]
Proszę podać jakieś istotne różnice w tych 2 sposobach serializacji danych:
  - XDR (używane w SUN/ONC RPC)
  - serializacja "javowa" (używane w RMI)
na podstawie dowolnych materiałów, które można znaleźć w Internecie, np. dokumentów RFC.
Można np. podać jakie są ograniczenia co do danych, które można serializować...
Czy można serializować struktury danych z referencjami/wskazaniami?
Dlaczego w Javie nie zdecydowano się używać formatu XDR?
... itp kwestie można poruszyć.
Proszę też podać z jakich materiałów skorzystano.