13. java: remote method invocation (4) · 2002. 5. 20. · remote method invocation (4) vittorio...
TRANSCRIPT
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
1
Corso di Laurea in Informatica
Università degli Studi di Salerno
13. Java: Remote Method Invocation (4)
Vittorio Scarano
Algoritmi e Strutture Dati: Sistemi Distribuiti
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
2
Organizzazione della lezione
• Oggetti attivabili– meccanismo e protocollo di attivazione
– esempi
– dati persistenti
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
2
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
3
Persistenza
• In generale, un sistema a oggetti distribuiti deve offrire la persistenza dei dati– insieme di numerosi oggetti che devono fornire servizi
• Alcune considerazioni:– è inutile avere attivi degli oggetti se non vengono utilizzati
– è possibile che ci siano dei problemi sulla macchina server che obblighi a far “ripartire” il sistema
• ripristinando i dati relativi agli oggetti server
• A questo scopo sono introdotti in RMI gli oggetti “Attivabili”
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
4
Le classi ed interfacce di RMI
RemoteObject
<<interface>>Remote
RemoteServer
Activatable UnicastRemoteObject
IOException
RemoteException
Object
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
3
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
5
Attivazione di oggetti
• E’ un meccanismo per fornire riferimenti persistenti ad oggetti distribuiti– gestendo la loro esecuzione
– sulla base delle richieste pervenute
• Lazy activation– un oggetto viene attivato solamente all’atto della prima
chiamata ricevuta
– inizializzandone lo stato
– e, se necessario, facendo partire una JVM appropriata
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
6
Terminologia utilizzata
• Un oggetto (distribuito) è attivo se– risulta essere istanziato ed esportato (in esecuzione) su una
JVM
• Un oggetto (distribuito) è passivo se– risulta non essere ancora istanziato ed in esecuzione, ma può
essere portato nello stato di attivo
• Il processo di trasformare un oggetto passivo in attivo è detto attivazione
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
4
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
7
La lazy activation
• Meccanismo di riferimento remoto faulting– alla prima invocazione su un metodo di un oggetto
• Ogni riferimento remoto faulting contiene– un identificatore di attivazione (activation identifier)
• server per comunicare i dati per far attivare l’oggetto
– un riferimento remoto all’oggetto remoto• all’inizio vale null poi contiene il riferimento dell’oggetto attivato
• Importante: anche in presenza di fallimenti hw/sw– RMI garantisce la semantica sui metodi chiamata “at most
once”: il metodo non è mai eseguito più volte
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
8
Protocollo di attivazione - 1
• In caso il riferimento remoto sia null il riferimento remotofaulting inizia un protocollo di attivazione
• Componenti• l’attivatore• il gruppo di attivazione• l’oggetto remoto da attivare
• L’attivatore (uno per host)– contiene un database di informazioni che associano
identificatori di attivazione alle informazioni necessarie per la attivazione (classe, URL, dati per il bootstrap, etc)
– manager di JVM (una per gruppo)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
5
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
9
Protocollo di attivazione - 2
• Il gruppo di attivazione (uno per ogni JVM)• riceve la richiesta di attivazione e restituisce il riferimento
all’oggetto attivato all’attivatore
• Passi del protocollo:• l’attivatore usa le informazioni relative all’identificatore di
attivazione
• se esiste il gruppo di atttivazione, invia la richiesta al gruppo
• altrimenti, istanzia una JVM per il gruppo e poi invia la richiesta
• il gruppo carica la classe, istanzia l’oggetto (con un costruttore particolare)
• ne restituisce il riferimento remoto all’attivatore
• che lo registra e lo restituisce al riferimento remoto faulting
• che invia la richiesta di esecuzione di metodo all’oggetto
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
10
Come creare un oggetto attivabile
• Necessario:– registrare il descrittore di attivazione
– includere uno speciale costruttore usato per la attivazione
• Il descrittore di attivazione può essere registrato:– con il metodo register (statico) di Activatable
– con il metodo exportObject di Activatable• se l’oggetto non deriva da Activatable
– all’atto della creazione (se si vuole istanziare comunque l’oggetto senza una chiamata)
• usando dei costruttori di Activatable
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
6
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
11
I costruttori di Activatable - 1
• 2 costruttori– per la instanziazione e registrazione
• se si vuole istanziare un oggetto e contemporaneamente renderlo attivabile
• può servire per permettere l’automatico restart dell’oggetto
– per la sola attivazione• chiamato dall’attivatore all’atto della prima invocazione
• Ognuno di questi costruttori ha una variante– per l’utilizzo di socket personalizzati con una SocketFactory
• crittografia (SSL, etc.), protocolli particolari
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
12
I costruttori di Activatable - 2
protected Activatable (String codebase, java.rmi.MarshalledObject data, boolean restart, int port)
throws ActivationException, java.rmi.RemoteException; protected Activatable (String codebase,
java.rmi.MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
throws ActivationException, java.rmi.RemoteException;
• Costruttori per istanziazione e attivazione
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
7
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
13
I costruttori di Activatable - 3
protected Activatable (ActivationID id, int port)
throws java.rmi.RemoteException; protected Activatable (ActivationID id,
int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
• Costruttori per la attivazione– se la porta è zero viene usato una porta anonima
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
14
Il demon di attivazione: rmid
• In carica del ruolo di attivatore
• Lanciato con – rmid -J-Djava.security.policy=rmid.policy– che permette il passaggio della security policy al demon
• Usa una directory log (modificabile da parametri) per mantenere il database degli identificatori di attivazione
• Alcuni parametri utili:-C per passare parametri ad ognuna delle JVM lanciate
ad esempio: rmid -C-Djava.rmi.server.logCalls=true
- stop per fermare il demon
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
8
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
15
Un esempio: ActRemoteHello
• Il solito servizio di saluto personalizzato
• Composto da:– Hello: interfaccia remota
– HelloClient: client
– HelloImpl: oggetto attivabile• deriva da Activatable
– SetupRemoteHello:• registra l’oggetto HelloImpl (o meglio il suo stub) all’activator
(rmid) con le informazioni necessarie per permetterne la attivazione
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
16
Il diagramma di ActRemoteHello
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
9
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
17
La interface remote: Hello.java
public interface Helloextends java.rmi.Remote {
String dimmiQualcosa( String daChi )throws java.rmi.RemoteException;
}
• Unico metodo remoto– lancia una eccezione
remota
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
18
La implementazione: HelloImpl.java (1)
import java.rmi.*;import java.rmi.activation.*;public class HelloImpl extends Activatable
implements Hello {// Costruttore per costr. regist. ed exportpublic HelloImpl( String codebase,
MarshalledObject data )throws RemoteException,
ActivationException {super( codebase, data, false, 0 );System.out.println( "Primo costruttore" );
}// Costruttore per attivazione ed esportazionepublic HelloImpl( ActivationID id,
MarshalledObject data )throws RemoteException {
super( id, 0 );System.out.println( "Secondo costruttore" );
} // continua….
• Estende Activatable
• Primo costruttore– solo per istanziare e
attivare (non usato)
• Secondo costruttore– fornito per permettere
la attivazione a rmid in caso di chiamata di metodi remoti
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
10
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
19
La implementazione: HelloImpl.java (2)
/*** Metodo remoto : restituisce una stringa*/
public String dimmiQualcosa( String daChi )throws RemoteException {
System.out.println( "Saluto " + daChi );return "Ciao!";
}}// end classe HelloImpl
• Implementazione del metodo remoto– dichiarato in
Hello.java
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
20
La registrazione:SetupRemoteHello.java (1)
import java.rmi.*;import java.rmi.activation.*;import java.util.Properties;public class SetupRemoteHello {public static void main( String args[] ) {
System.setSecurityManager( new RMISecurityManager() );
String home = "/ProgettiJava/ActRemoteHello";try {Properties props = new Properties(); props.put("java.security.policy", home+"/policyall"); ActivationGroupDesc.CommandEnvironment
ace = null; ActivationGroupDesc helloGroup = new
ActivationGroupDesc(props, ace);ActivationGroupID agi =
ActivationGroup.getSystem().registerGroup(helloGroup);
// continua…
• Set SM
• Proprietà delle JVM lanciate da rmid– solo per test: policyall
• Creazione del gruppo– descrittore– group ID dalla
registrazione
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
11
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
21
La registrazione:SetupRemoteHello.java (2)
String location = "file:" + home;
MarshalledObject data = null;
ActivationDesc desc = new ActivationDesc (agi, "HelloImpl", location, data);
Hello hi = (Hello)Activatable.register(desc); System.out.println("Ho lo stub per HelloImpl"); Naming.rebind("RemoteHello", hi); System.out.println(".. e lo esporto sul registry"); } catch ( Exception e ) {
e.printStackTrace();}
System.out.println("Salute a tutti!"); System.exit(0);
}}
• URL per la posizione dello stub
• Dati da passare alla classe
• Creazione del descrittore di attivazione
• Registrazione sull’activator del descrittore di attivazione– restituisce lo stub
– … di cui va fatto il bind su rmiregistry
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
22
Il client: HelloClient.java
import java.rmi.*;public class HelloClient {
public static void main( String args[] ) {String host = "localhost";String nome = "Pippo";
if ( args.length > 0 ) host = args[0];if ( args.length > 1 ) nome = args[1];try {
Hello obj = (Hello)Naming.lookup( "rmi://" + host +
"/RemoteHello" );System.out.println( "Ricevuto:"
+ obj.dimmiQualcosa( nome ) );} catch ( Exception e ) {
e.printStackTrace();}
}}
• Client identico alla versione non activatable
• Parametri:– args[0]: hostname
– args[1]: nome del client
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
12
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
23
Esecuzione: eseguo rmid (1)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
24
Esecuzione: eseguo rmiregistry (2)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
13
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
25
Esecuzione: lancio di setup (3)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
26
Esecuzione: lancio del client (4)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
14
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
27
Esecuzione: cosa avviene sul server (5)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
28
Esecuzione: altra esecuzione client (6)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
15
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
29
Esecuzione: cosa avviene sul server (7)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
30
La situazione sulla macchina (1)
• Pur essendo in esecuzione rmid, non c’è nessuna JVM per l’oggetto server
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
16
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
31
La situazione sulla macchina (2)
• Alla esecuzione del client…
• .. fa seguito la attivazione di una JVM da parte di RMI per l’oggetto HelloImpl
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
32
La persistenza dei dati
• Particolarmente importante:– nel caso sia necessario prevedere il recovery da crash
– oppure nel caso in cui l’oggetto remoto decida di diventare inattivo dopo un certo periodo di tempo,
• ma alla prima invocazione remota vuole essere disponibile
• recuperando i dati in precedenza calcolati
• A questo scopo si usano i dati da fornire durante la attivazione– che possono essere usati dal costruttore chiamato per la
attivazione
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
17
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
33
Un esempio: PersActRemoteHello
• Oramai “stranoto” servizio da offrire:– unica variante: in risposta fornisce anche i dati di tutti gli
utenti che hanno invocato il metodo dimmiQualcosa() dell’oggetto remoto
– quindi necessario:• concatenare in una stringa tutti i nomi passati come parametri alle
invocazioni remote
• prevedere il salvataggio dei dati nel caso in cui l’oggetto cada e venga rieseguito
• A questo scopo usiamo un file:– dove, ad ogni invocazione, HelloImpl va a scrivere la stringa
che compone il suo stato
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
34
Il diagramma di PersActRemoteHello
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
18
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
35
La interface remote: Hello.java
public interface Helloextends java.rmi.Remote {
String dimmiQualcosa( String daChi )throws java.rmi.RemoteException;
}
• Identica al caso precedente
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
36
La implementazione: HelloImpl.java (1)
import java.rmi.*;import java.rmi.activation.*;import java.io.*;public class HelloImpl extends Activatable
implements Hello {public HelloImpl( String codebase,
MarshalledObject data )throws RemoteException, ActivationException {
super( codebase, data, false, 0 );System.out.println( "Primo costruttore " );try {fileDati = (File) data.get();
if ( fileDati.exists() )this.restoreState();
elsecallsFrom = "Starting...";
} catch (Exception e) {System.out.println(“Lettura file");
}} // continua…
• Primo costruttore– solo per istanziare e
attivare (non usato)
– identico al secondo
• Preleva il riferimento al file inserito in data– se esiste il file
• allora chiama restoreState()
• altrimenti inizializza la variabile di istanza callsFrom
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
19
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
37
La implementazione: HelloImpl.java (2)
public HelloImpl(ActivationID id, MarshalledObject data )
throws RemoteException {super( id, 0 );System.out.println( "Secondo costruttore " );try {fileDati = (File) data.get();
if ( fileDati.exists() )this.restoreState();
else callsFrom = "[Starting...]";} catch (Exception e) {
System.out.println(“Lettura file");}
}public String dimmiQualcosa( String daChi )
throws RemoteException {System.out.println( "Saluto " + daChi );this.saveState( daChi );return "(dopo "+ callsFrom+")"+"Ciao!";
} // continua…
• Secondo costruttore– struttura identica al
primo
• Metodo remoto– usa saveState() per
aggiungere il nome del chiamante
– restituisce la intera stringa di chiamate oltre a “Ciao!”
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
38
La implementazione: HelloImpl.java (3)
private void restoreState() throws IOException, ClassNotFoundException {
File f = fileDati;FileInputStream fis = new FileInputStream( f );ObjectInputStream ois = new
ObjectInputStream(fis);callsFrom = (String) ois.readObject();ois.close();
}
// continua
• Usa la variabile di istanza fileDati
– apre uno stream in da file e
– uno stream in input
– legge una stringa e la inserisce nella variabile di istanza callsFrom
– e chiude
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
20
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
39
La implementazione: HelloImpl.java (4)
private void saveState( String currentCall ) {try {File f = fileDati;
FileOutputStream fos = new FileOutputStream( f );
ObjectOutputStream oos = new ObjectOutputStream( fos );
callsFrom = callsFrom + " -" + currentCall;oos.writeObject( callsFrom );oos.close();
} catch ( Exception e ) {System.out.println( "Errore in scrittura" );
}}
File fileDati;String callsFrom;
}
• Usa la variabile di istanza fileDati
– apre in output uno stream dal file stream
– aggiorna lo stato callsFrom ..
– … e lo scrive su file
• Variabili istanza– file per lo stato
persistente
– stato delle chiamate
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
40
La registrazione:SetupRemoteHello.java (1)
import java.rmi.*;import java.rmi.activation.*;import java.util.Properties;public class SetupRemoteHello {public static void main( String args[] ) {
System.setSecurityManager( new RMISecurityManager() );
String home = "/ProgettiJava/PersActRemoteHello";try {Properties props = new Properties(); props.put("java.security.policy", home+"/policyall"); ActivationGroupDesc.CommandEnvironment
ace = null; ActivationGroupDesc helloGroup = new
ActivationGroupDesc(props, ace);ActivationGroupID agi =
ActivationGroup.getSystem().registerGroup(helloGroup);
// continua…
• Set SM
• Proprietà delle JVM lanciate da rmid– solo per test: policyall
• Creazione del gruppo– descrittore– group ID dalla
registrazione
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
21
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
41
La registrazione:SetupRemoteHello.java (2)
String location = "file:" + home;MarshalledObject data = new
MarshalledObject (new File("/ProgettiJava/PersActRemoteHello/dati.dat"));
ActivationDesc desc = new ActivationDesc (agi, "HelloImpl", location, data);
Hello hi = (Hello)Activatable.register(desc); System.out.println("Ho lo stub per HelloImpl"); Naming.rebind("RemoteHello", hi); System.out.println(".. e lo esporto sul registry"); } catch ( Exception e ) {
e.printStackTrace();}
System.out.println("Salute a tutti!"); System.exit(0);
}}
• URL per la posizione dello stub
• Dati da passare alla classe (File)
• Creazione del descrittore di attivazione
• Registrazione sull’activator del descrittore di attivazione– restituisce lo stub
– … di cui va fatto il bind su rmiregistry
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
42
Il client: HelloClient.java
import java.rmi.*;public class HelloClient {
public static void main( String args[] ) {String host = "localhost";String nome = "Pippo";
if ( args.length > 0 ) host = args[0];if ( args.length > 1 ) nome = args[1];try {
Hello obj = (Hello)Naming.lookup( "rmi://" + host +
"/RemoteHello" );System.out.println( "Ricevuto:"
+ obj.dimmiQualcosa( nome ) );} catch ( Exception e ) {
e.printStackTrace();}
}}
• Client identico alla versione activatable non persistente
• Parametri:– args[0]: hostname
– args[1]: nome del client
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
22
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
43
Esecuzione: eseguo rmid (1)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
44
Esecuzione: eseguo rmiregistry (2)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
23
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
45
Setup ed esecuzione vari client (3)
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
46
Cosa accade sul server (4)
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
24
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
47
Simuliamo un “crash”…(come se ce ne fosse bisogno)
• Uccidiamo la JVM di HelloImpl…Oops!
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
48
Alla successiva chiamata…
ASD: Sistemi Distribuiti (Prof. Scarano) 20/05/2002
25
AS
D: S
iste
mi D
istr
ibui
ti.
Vi.t
tori
o S
cara
no
49
E sul server è stata istanziata un’altra JVM