Wyklad SR 4


Systemy rozproszone
Dr inż. L. Miękina
Department of Robotics and Mechatronics
AGH University of Science and Technology
Marzec, 2013
1/1
Java RMI
Przykład aplikacji ChatRMI - wymagania funkcjonalne
Przykład realizuje aplikację typu Chat, obsługującą komunikację między
zarejestrowanymi użytkownikami, w ramach której wymieniane są komunikaty
tekstowe.
Funkcjonalność serwera:
operacja zarejestruj rejestruje użytkownika w systemie, pozwalając na przesyłanie
do niego komunikatów.
operacja wyrejestruj usuwa użytkownika z systemu
operacja informuj zwraca listę nazw zarejestrowanych użytkowników
operacja komunikuj przesyła komunikat do wybranego użytkownika.
2 / 1
Java RMI
Przykład aplikacji ChatRMI - zdalne interfejsy
Zdalne interfejsy są definiowane przez rozszerzanie interfejsu Remote, dostarczanego w
pakiecie java.rmi. Metody realizujące interfejs muszą generować wyjątek
RemoteException, a poza tym mogą generować wyjątki innych rodzajów,
odpowiadających specyfice aplikacji.
Poniżej przedstawiono definicję interfejsu serwera:
1import java.rmi.*;
2import java.util.Vector;
3
4public interface IChat extends Remote {
5 boolean zarejestruj(String nick, ICallback n) throws RemoteException;
6 boolean wyrejestruj(String nick) throws RemoteException;
7 boolean komunikuj(String nick, String message) throws RemoteException;
8 Vector informuj(String nick) throws RemoteException;
9}
3 / 1
Java RMI
Przykład aplikacji ChatRMI - kod serwera
Serwer zawiera klasę ChatServer i klasę usługową ChatServant, implementującą
zdalny interfejs.
Metoda main klasy ChatServer tworzy instancję klasy ChatServant i wiąże ją z pewną
nazwą w rejestrze RMIregistry. Wiązana wartość reprezentuje zdalną referencję
obiektu, a jej typ jest typem zdalnego interfejsu - IChat.
1import java.rmi.RemoteException;
2import java.rmi.registry.LocateRegistry;
3import java.rmi.registry.Registry;
4
5public class ChatServer {
6 Registry reg; // rejestr nazw obiektow
7 ChatServant servant; // klasa uslugowa
8
9 public static void main(String[] args) {
10 try {
11 new ChatServer();
12 } catch (Exception e) {
13 e.printStackTrace();
14 System.exit(1);
15 } }
16
17 protected ChatServer() throws RemoteException {
18 try {
19 reg = LocateRegistry.createRegistry(1099); // Utworzenie rejestru nazw
20 servant = new ChatServant(); // utworzenie zdalnego obiektu
21 reg.rebind("ChatServer", servant); // zwiazanie nazwy z obiektem
22 System.out.println("ChatServer READY");
23 } catch(RemoteException e) {
24 e.printStackTrace();
25 throw e;
26 } }
4 / 1
27}
Java RMI
Przykład aplikacji ChatRMI - kod klasy usługowej ChatServant
1import java.rmi.RemoteException;
2import java.rmi.server.UnicastRemoteObject;
3import java.util.HashMap;
4import java.util.Map;
5import java.util.Set;
6import java.util.Vector;
7
8public class ChatServant
9 extends UnicastRemoteObject
10 implements IChat {
11 private Map obecni = new HashMap();
12
13 public ChatServant() throws RemoteException {
14 }
15 // Metoda implementujaca funkcje komunikuj() interfejsu IChat
16 public boolean komunikuj(String nick, String text) throws RemoteException {
17 System.out.println("Server.komunikuj(): " + text);
18 ICallback callback = obecni.get(nick);
19 if(callback != null) {
20 callback.komunikuj(nick, text);
21 return true;
22 }
23 return false;
24 }
25 //Metoda implementujaca funkcje zarejestruj() interfejsu IChat
26 public boolean zarejestruj(String nick, ICallback n) throws RemoteException {
27 System.out.println("Server.zarejestruj(): " + nick);
28 if (!obecni.containsKey(nick)) {
29 obecni.put(nick, n);
30 return true;
31 }
32 return false;
5 / 1
Java RMI
Przykład aplikacji ChatRMI - kod klasy usługowej ChatServant c.d.
33 }
34 //Metoda implementujaca funkcje wyrejestruj() interfejsu IChat
35 public boolean wyrejestruj(String nick) throws RemoteException {
36 if(obecni.remove(nick) != null) {
37 System.out.println("Server.wyrejestruj(): " + nick);
38 return true;
39 }
40 return false;
41 }
42 //Metoda implementujaca funkcje informuj() interfejsu IChat
43 public Vector informuj(String nick) throws RemoteException {
44 Set set = obecni.keySet();
45 Vector v = new Vector();
46 for(String s : set)
47 if(nick.equals("*") || s.equals(nick))
48 v.add(s);
49 return v;
50 }
51}
6 / 1
Java RMI
Przykład aplikacji ChatRMI - kod klasy klienta ChatClient
9public class ChatClient {
10 public static void main(String[] args) {
11 if(args.length < 2) {
12 System.out.println("Usage: ChatClient ");
13 System.exit(-1);
14 }
15 if (System.getSecurityManager() == null)
16 System.setSecurityManager(new RMISecurityManager());
17 IChat remoteObject; // referencja do zdalnego obiektu
18 Registry reg; // rejestr nazw obiektow
19 try {
20 // pobranie referencji do rejestru nazw obiektow
21 reg = LocateRegistry.getRegistry(args[0]);
22 // odszukanie zdalnego obiektu po jego nazwie
23 remoteObject = (IChat) reg.lookup("ChatServer");
24 ICallback callback = new ClientCallback();
25 // wywolanie metod zdalnego obiektu
26 remoteObject.zarejestruj("LM", callback);
27 if(remoteObject.zarejestruj("SM", callback)) {
28 Vector vec = remoteObject.informuj("*");
29 System.out.println("There are " + vec.size() + " user(s):");
30 for (String s : vec)
31 System.out.println(" - " + s);
32 remoteObject.komunikuj("SM", args[1]);
33 remoteObject.wyrejestruj("LM");
34 remoteObject.wyrejestruj("SM");
35 }
36 System.exit(0);
37 }
38 catch(RemoteException e) {
39 e.printStackTrace();
40 }
41 catch(NotBoundException e) {
7 / 1
42 e.printStackTrace();
Java RMI
Przykład aplikacji ChatRMI - interfejs i implementacja wywołania zwrotnego
1import java.rmi.Remote;
2import java.rmi.RemoteException;
3
4public interface ICallback extends Remote {
5 public void komunikuj(String nick, String text) throws RemoteException;
6}
1import java.rmi.RemoteException;
2import java.rmi.server.UnicastRemoteObject;
3
4public class ClientCallback extends UnicastRemoteObject implements ICallback {
5 public ClientCallback() throws RemoteException {
6 super();
7 }
8 public void komunikuj(String nick, String text) throws RemoteException {
9 System.out.println("odebrano komunikat: " + text);
10 }
11}
8 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie
Serwery RMI pracujące w trybie  unicast (pojedynczym) są oparte na klasie
UnicastRemoteObject, lub są eksportowane za pomocą statycznej metody
exportObject tej klasy. Zdalna referencja obiektu działającego w takim serwerze RMI
pozostaje poprawna tak długo dopóki serwer działa, ale nie dłużej. Gdy serwer kończy
działanie, lub usuwa zdalny obiekt (ze swojej TZO), zdalna referencja staje się
bezużyteczna, bo nie odnosi się już do rzeczywistego obiektu. Użycie jej spowoduje
błąd wykonania. Referencje tego typu nie mogą być zapisane i pózniej użyte. Klienci
tych serwerów muszą ponownie wykonać procedurę pozyskania zdalnej referencji,
stosując metodę lookup rejestru RMI.
Aktywacja usuwa to ograniczenie. Zdalna referencja do obiektu serwera RMI typu
 activatable pozostaje poprawna dopóki zdalny obiekt nie zostanie wyrejestrowany z
systemu aktywacji RMI (implementowanego przez demom rmid). Za każdym razem
gdy używa się tej referencji, serwer będzie automatycznie restartowany jeśli nie działa.
Sama referencja może być przechowywana (zapisywana i odczytywana) pomiędzy
sesjami systemu i pozostawać użyteczna.
Można w związku z tym traktować zdalną referencję do obiektu typu "activatable"
jako trwałą (persistent).
Zastosowania aktywacji
Aktywacja jest przydatna w przypadkach gdy, wymagane jest posiadanie serwera:
1
uruchamianego tylko na życzenie (on-demand)
2
trwale działającego (persistent) lub tolerującego awarie (fault-tolerant)
3
ciągle działającego w trybie  24x7 .
9 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie
Serwery aktywowalne (activatable)
Serwer aktywowalny może być aktywowany (uruchomiony) na życzenie. Aby to było
możliwe musi on:
1
implementować zdalny interfejs
2
być zarejestrowany przez system aktywacji RMI
3
posiadać dostępny konstruktor typu wymaganego przez system aktywacji
4
wyeksportować obiekt klasy usługowej, albo wywołując odpowiedni konstruktor
nadklasy Activatable (jeśli z niej dziedziczy) lub wywołując statyczną metodę
Activatable.exportObject.
Aktywowalny serwer jest rejestrowany przez metodę Activatable.register. Po
zarejestrowaniu staje się on powiązany z grupą aktywacji (activation group),
lokalizacją kodu klas (codebase) i (opcjonalnie) argumentem początkowym.
Rejestracja dotyczy aktywowalnego serwera, a nie tylko klasy. Aktywowalny serwer jest
określony przez deskryptor (activation descriptor), tzn. krotkę złożoną z
identyfikatora grupy aktywacji, lokalizacji kodu klas - codebase, klasy usługowej i
argumentu początkowego. Klasa usługowa jest jednym z elementów serwera.
Lokalizacja kodu klas (codebase) jest nazwą URL - adresem gdzie znajduje się kod
klas serwera. Może on być lokalnym katalogiem, ale zwykle odnosi się do zasobu
udostępnianego przez serwer HTTP.
Argument poczatkowy jest obiektem typu MarshalledObject, który jest przekazywany
do konstruktora wywoływanego przez system aktywacji. Obiekt ten jest tworzony
przez program który rejestruje serwer i może zawierać dowolną serializowalną daną, lub
może nie występować.
10 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie
Grupa aktywacji
Aktywowalny serwer jest rejestrowany w wybranej grupie aktywacji (activation group),
złożonej z pewnej liczby serwerów. Każda grupa aktywacji działa w oddzielnej JVM i
jest zarejestrowana w systemie aktywacji.
System aktywacji RMI jest instancją interfejsu ActivationSystem dostarczoną przez
implementację - w przypadku JDK firmy Sun/Oracle implementacja przybiera postać
programu demona rmid. Referencja do obiektu systemu aktywacji może być
udostępniona przez statyczną metodę ActivationGroup.getSystem.
11 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie
Ten przykład pokazuje sposób tworzenia zdalnego obiektu typu activatable,
który ma właściwość automatycznego uruchomienia na żądanie klienta, dzięki
temu że dziedziczy z klasy java.rmi.activation.Activatable. W ten sposób
poprzednio opracowany serwer Monitora może być aktywowany na życzenie -
gdy klient wyszuka go w rejestrze obiektów i zażąda wykonania jednej z jego
funkcji.
Przed wprowadzeniem Javy w wersji 2, instancja typu UnicastRemoteObject
mogła być udostępniona przez program serwera, który
1
utworzył instancję zdalnego obiektu i
2
działał w sposób ciągły, oczekując na ewentualne żądania.
Po wprowadzeniu klasy java.rmi.activation.Activatable i demona RMI o nazwie
rmid, programy mogą rejestrować informacje o implementacjach zdalnych
obiektów, które mają być używane i aktywowane na życzenie.
12 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - zdalne interfejsy
Zdalne interfejsy są definiowane przez dziedziczenie z interfejsu Remote
dostępnego w pakiecie java.rmi. Metody interfejsu muszą generować wyjątek
RemoteException, a poza tym dowolne wyjątki specyficzne dla aplikacji.
Przykład zdalnego interfejsu:
1import java.rmi.*;
2import java.util.Vector;
3
4public interface IMonitor extends Remote {
5 void inform(String message) throws RemoteException;
6 Event get(int i) throws RemoteException;
7 void add(Event event) throws RemoteException;
8 int getCount() throws RemoteException;
9 Vector allEvents() throws RemoteException;
10}
Zdalny interfejs deklaruje następujące metody:
inform, która posiada jeden parametr o nazwie message, przez który
przekazywany jest łańcuch reprezentujący komunikat.
get do odczytu komunikatu zapisanego pod wybranym indeksem
add do rejestracji nowego komunikatu przez serwer
getCount do odczytu ilości zarejestrowanych komunikatów
allEvents do odczytu wszystkich zarejestrowanych komunikatów.
13 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klasy Setup
Kod serwera składa się z klas Setup, MonitorServant i z pomocniczej klasy
Event.
Setup jest klasą główną i wykonuje następujące zadania:
instaluje zarządcę bezpieczeństwa SecurityManager
tworzy instancję klasy ActivationGroup
tworzy instancję klasy ActivationDesc
deklaruje instancję zdalnego interfejsu i rejestruje ją w demonie rmid
definiuje powiązanie namiastki zdalnego obiektu z nazwą w rejestrze rmiregistry
Tak więc zadaniem klasy Setup jest utworzenie informacji wymaganych przez
klasę aktywowanego obiektu, zwykle bez tworzenia jego instancji.
1import java.rmi.MarshalledObject;
2import java.rmi.Naming;
3import java.rmi.RMISecurityManager;
4import java.rmi.activation.Activatable;
5import java.rmi.activation.ActivationDesc;
6import java.rmi.activation.ActivationGroup;
7import java.rmi.activation.ActivationGroupDesc;
8import java.rmi.activation.ActivationGroupID;
9import java.rmi.registry.LocateRegistry;
14 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klasy Setup
11
12public class Setup {
13 public static void main(String[] args) throws Exception {
14 System.setSecurityManager(new RMISecurityManager());
15 // Because of the 1.2 security model, a security policy
16 // should be specified for the ActivationGroup VM.
17 Properties props = new Properties();
18 props.put("java.security.policy",
19 "/home/lm/workspace/Distributed/RMI/Monitor/Activatable/src/java.policy");
20 ActivationGroupDesc.CommandEnvironment ace = null;
21 ActivationGroupDesc group = new ActivationGroupDesc(props, ace);
22 // Register the ActivationGroupDesc with the activation system to obtain its ID
23 ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(group);
24 String serviceName = "MonitorServant";
25 String location =
26 "file:/home/lm/workspace/Distributed/RMI/Monitor/Activatable/src/";
27 // The rest of the parameters to be passed to the ActivationDesc constructor
28 MarshalledObject data = null;
29 // The location argument to the ActivationDesc constructor will be used
30 // to uniquely identify this class.
31 ActivationDesc desc = new ActivationDesc(agi, serviceName,
32 location, data);
33 // Register with rmid
34 IMonitor mri = (IMonitor)Activatable.register(desc);
35 LocateRegistry.getRegistry().rebind(serviceName, mri);
36 System.out.println("Got the stub for the " + serviceName);
37 System.out.println("Exported " + serviceName);
38 System.exit(0);
39 }
40}
15 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klasy usługowej MonitorServant
Klasa MonitorServant implementuje interfejs IMonitor. Pierwsza część kodu
klasy zawiera wymagane dyrektywy import, pola klasy i konstruktora.
1import java.rmi.MarshalledObject;
2import java.rmi.RemoteException;
3import java.rmi.activation.Activatable;
4import java.rmi.activation.ActivationID;
5import java.util.Vector;
6
7public class MonitorServant
8 extends Activatable
9 implements IMonitor {
10
11 private static final long serialVersionUID = 1L;
12 private Vector events;
13
14 public MonitorServant(ActivationID id, MarshalledObject data)
15 throws RemoteException {
16 super(id, 0);
17 events = new Vector();
18 }
16 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klasy usługowej MonitorServant
Druga część kodu klasy zawiera realizacje metod zadeklarowanych w interfejsie.
20 public void inform(String message) throws RemoteException {
21 events.add(new Event(message));
22 System.out.println("Server: " + message);
23 }
24
25 public Event get(int i) throws RemoteException {
26 if (i < 0 || i >= events.size())
27 return null;
28 return events.get(i);
29 }
30
31 public void add(Event event) throws RemoteException {
32 events.add(event);
33 }
34
35 public int getCount() throws RemoteException {
36 return events.size();
37 }
38
39 public Vector allEvents() throws RemoteException {
40 return events;
41 }
42}
17 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klienta
1import java.net.MalformedURLException;
2import java.rmi.Naming;
3import java.rmi.NotBoundException;
4import java.rmi.RMISecurityManager;
5import java.rmi.RemoteException;
6import java.rmi.registry.LocateRegistry;
7import java.rmi.registry.Registry;
8import java.util.Vector;
9
10public class MonitorClient {
11 public static void main(String[] args) {
12 if (args.length < 2) {
13 System.out.println("Usage: MonitorClient ");
14 System.exit(-1);
15 }
16 if (System.getSecurityManager() == null)
17 System.setSecurityManager(new RMISecurityManager());
18 IMonitor remoteObject; // referencja do zdalnego obiektu
18 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kod klienta
20
21 try {
22 // pobranie referencji do rejestru nazw obiektow
23 reg = LocateRegistry.getRegistry(args[0]);
24 String[] names = reg.list();
25 System.out.println("There are " + names.length
26 + " name(s) in the registry:");
27 for (String s : names)
28 System.out.println(" - " + s);
29 // odszukanie zdalnego obiektu po jego nazwie
30 remoteObject = (IMonitor) reg.lookup(args[1]);
31 System.out.println("FOUND " + args[1]);
32 // wywolanie metody zdalnego obiektu
33 remoteObject.inform("FIRST event");
34 remoteObject.inform("SECOND event");
35 int cnt = remoteObject.getCount();
36 System.out.println("There are " + cnt + " registered events:");
37 Vector e = remoteObject.allEvents();
38 for (Event ev : e) {
39 System.out.print(" - ");
40 ev.print();
41 }
42 }
43 catch (RemoteException e) {
44 e.printStackTrace();
45 }
46 catch (NotBoundException e) {
47 e.printStackTrace();
48 }
49 }
50}
19 / 1
Java RMI
Automatyczna aktywacja serwera na żądanie - kompilacja i uruchomienie
1
Kompilacja klas
lm@suse-lm: /src> javac *.java
2
Utworzenie rejestru RMI
lm@suse-lm: /src> rmiregistry &
[1] 4770
3
Utworzenie demona aktywacji
lm@suse-lm: /src> rmid -J-Djava.security.policy=rmid.policy &
[2] 4790
4
Aktywacja serwera
lm@suse-lm: /src> java -Djava.security.policy=java.policy
-Djava.rmi.server.codebase=file:./ Setup
Got the stub for the MonitorServant
Exported MonitorServant
5
Uruchomienie programu klienta
lm@suse-lm: /src> java -Djava.security.policy=java.policy MonitorClient localhost
MonitorServant
There are 1 name(s) in the registry:
- MonitorServant
FOUND MonitorServant
There are 2 registered events:
- Mon May 19 11:55:29 CEST 2014: FIRST event
- Mon May 19 11:55:29 CEST 2014: SECOND event
20 / 1
Uwaga: przed uruchomieniem rmiregistry, należy się upewnić, że w katalogu bieżącym nie ma ustawień zmiennej


Wyszukiwarka

Podobne podstrony:
Wyklad SR 1,2
Wyklad SR 3
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej
mo3 wykladyJJ
ZARZĄDZANIE WARTOŚCIĄ PRZEDSIĘBIORSTWA Z DNIA 26 MARZEC 2011 WYKŁAD NR 3
Wyklad 2 PNOP 08 9 zaoczne
Wyklad studport 8
Kryptografia wyklad
Budownictwo Ogolne II zaoczne wyklad 13 ppoz
wyklad09

więcej podobnych podstron