Programmazione distribuita 1
Architettura client-server È il modo classico di progettare applicazioni distribuite su rete Server offre un servizio "centralizzato" attende che altri (client) lo contattino per ottenere un servizio Client esempio: web server si rivolge ad apposito/i server per ottenere certi servizi esempio: browser www (Netscape, Explorer, ) 2
Middleware Per programmare un sistema distribuito vengono forniti servizi specifici, come estensione del sistema operativo Il middleware viene posto tra il sistema operativo e le applicazioni 3
Architettura del server Single-threaded quando accetta una connessione, la serve fino a che questa viene chiusa Multi-threaded quando accetta una connessione, genera il socket relativo e lo fa gestire da un task 4
RMI Remote Method Invocation Possono essere invocati metodi su oggetti remoti Aspetti innovativi passaggio dei parametri per valore e indirizzo possibilità di scaricare (download) automaticamente dalla rete le classi necessarie per la valutazione remota 5
Architettura client-server usando RMI Caso tipico Server crea oggetti remoti, li rende visibili e aspetta che i client invochino metodi su di essi Client ottiene riferimenti a oggetti remoti e invoca metodi su di essi RMI fornisce il meccanismo con cui server e clients comunicano per costituire l'applicazione distribuita tipicamente client ottiene servizi dal server invocando metodi di oggetti remoti con una sintassi identica a quella per gli oggetti locali (residenti sulla stessa JVM), ma con una semantica un po diversa 6
Funzionalità di RMI (1) Localizzazione di oggetti remoti Gli oggetti remoti sono registrati presso un registro di nomi (rmiregistry) che fornisce una "naming facility", oppure Le operazioni passano come parametri e/o restituiscono riferimenti a oggetti remoti Comunicazione con oggetti remoti gestita da RMI, per i programmi accedere a oggetti remoti non fa differenza rispetto agli oggetti "normali" 7
Funzionalità di RMI (2) Dynamic class loading essendo possibile passare oggetti ai metodi di oggetti remoti, e poiche` (come vedremo) gli oggetti (non remoti) vengono passati per valore, RMI oltre a trasmettere i valori dei parametri, consente di trasferire il codice degli oggetti a run time È un esempio di codice mobile 8
Vincoli Le interfacce che definiscono le funzionalita`degli oggetti remoti (cioe`resi accessibili da altri oggetti non locali tramite il sistema RMI) devono ereditare da java.rmi.remote I metodi definiti in tali interfacce devono dichiarare l'eccezione java.rmi.remoteexception 9
Modus operandi Grazie all'eredità multipla fra le interfacce, i metodi definiti in una qualsiasi interfaccia MyInterface che non era stata pensata per oggetti remoti possono essere forniti in maniera remota creando una nuova interfaccia che eredita da MyInterface e dall interfaccia predefinita Remote 10
Architettura "esterna" viene usato anche un normale server web per caricare (dinamicamente) le classi (in bytecode), da client a server e da server a client 11
Architettura "interna" Il client colloquia con un proxy locale del server, detto stub lo stub rappresenta il server sul lato client implementa l'interfaccia del server è capace di fare forward di chiamate di metodi il client ha un riferimento locale all'oggetto stub Esiste anche un proxy del client sul lato server, detto skeleton è una rappresentazione del client chiama i servizi del server sa come fare forward dei risultati lo skeleton ha un riferimento all'oggetto 12
Architettura di RMI programma CLIENT Livello applicazioni programma SERVER Stubs Skeletons chiamata di un metodo Java virtual machine Rete IP risposta Java virtual machine rmiregistry 13
Creazione di interfaccia remota package distrib1.rmi; import java.rmi.*; public interface PerfectTimeIntrfc extends Remote { long get PerfectTime() throws RemoteException; } n'interfaccia remota. deve essere pubblica. deve estendere java.rmi.remote. ogni metodo deve dichiarare java.rmi.remoteexception. ogni oggetto remoto passato come parametro o valore di ritorno deve essere dichiarato di tipo interf. remota 14
Dal lato server occorre Dichiarare la classe dell oggetto server, affinche`esso sia accessibile via RMI, in modo che estenda UnicastRemoteObject e implementi l'interfaccia remota definisca esplicitamente il costruttore, che deve dichiarare RemoteException nella clausola throws creare e installare RMISecurityManager, che gestisce RMI sul lato server creare uno o più oggetti remoti registrare almeno uno di questi nel "registry" Per eventuali altri oggetti si possono ottenere riferimenti a essi come risultato di chiamate di metodi di quelli gia` registrati, evitando cosi` di passare ancora attraverso il registry 15
Registry È un task concorrente, sotto Windows lanciato con start rmiregistry o (se si è sicuri di essere i soli a usare il registry) all'interno del codice del server col comando LocateRegistry.createRegistry(); È un programma di rete che ascolta su una porta, per default "1099" Occorre dargli comando per realizzare il binding tra il l'oggetto locale esportato come remoto e il nome che a esso dà il client 16
package distr1.java; import java.rmi.*; import java.rmi.server.*; import java.rmi.registry.*; import java.net.*; public class PerfectTime extends UnicastRemoteObject implements PerfectTimeIntrfc { public long getperfecttime() throws RemoteException; return System.currentTimeMillis(); } public PerfectTime() throws RemoteException { super(); //inutile, peraltro } public static void main (String{} args) throws Exception { System.setSecurityManager(new RMISecurityManager()); PerfectTime pt = new PerfectTime(); Naming.rebind ("//pc-morze/perfecttime", pt); System.out.println("Ready to do time"); } } evita il rischio di "bind"qualora esista già un oggetto registrato con lo stesso nome stringa di registrazione: un URL con la forma [rmi:][//][host][:port][/name] 17
Vita degli oggetti remoti Se main() termina, l'oggetto remoto registrato continua ad esistere finchè rmiregistry resta running Ecco perché è necessario fare rebind (potrebbe esistere un oggetto con lo stesso nome) Si può anche fare Naming.unbind() (" "); 18
Uso dell'oggetto remoto package distrib1.rmi; import java.rmi.*; import java.rmi.registry.*; public class DisplayPerfectTime { public static void main(string[] args) throws Exception { System.setSecurityManager(new RMISecurityManager()); //lega oggetto locale a remoto PerfectTime t=(perfecttime) Naming.lookup("//pc-morze/PerfectTime"); for(int i=0; i<10; i++) System.out.println("Perfect time = "+ t.getperfecttime()); } } 19
Semantica: passaggio dei parametri nell'invocazione di un metodo remoto m(obj) se obj remoto (i.e., esportato al sistema RMI), normale semantica (passato riferimento remoto) se oggetto non remoto, m opera su una copia serializzata (passaggio per valore con deep copy) di obj; eventuali modifiche alla copia di obj hanno effetto solo sulla copia, non sull'originale tipi primitivi passati comunque per valore 20
Serializzazione Oggetti passati a, o ritornati da, un oggetto remoto devono implementare l'interfaccia Serializable se invece si passano riferimenti remoti, basta estendere Remote Stubs e skeletons effettuano automaticamente la serializzazione e deserializzazione si dice che fanno il "marshal" (schieramento) di argomenti e risultati 21
Che cosa dobbiamo fare noi? Il tool rmic (rmi compiler) crea i files necessari per stub e skeleton rmic distrib1.rmi.perfecttime genera due classi: PerfectTime_Stub.class PerfectTime_Skel.class 22
Ciclo di sviluppo di una semplice applicazione Definizione dell interfaccia remota Deve estendere java.rmi.remote Definizione del codice del client deve richiede al registry un riferimento all oggetto remoto lo assegna ad una variabile che ha l interfaccia remota come tipo Definizione del codice dell oggetto remoto deve implementare l interfaccia remota deve estendere la classe java.rmi.server. UnicastRemoteObject Creazione di stub e skeleton si usa il comando rmic Definizione del codice del server istanzia l oggetto remoto e lo registra presso il registry 23
Security manager e file di policy Perchè client e server possano istanziare correttamente le classi scaricate, è necessario configurare il security manager Questo impedisce alle classi scaricate di eseguire azioni non legali SecurityManager è una classe in java.lang che offre metodi per controllare la possibilità di accesso a varie risorse (file, socket,...) RMI usa un security manager per controllare i permessi di uso dei socket da parte di un applicazione Un utente può definire le politiche di sicurezza editando un file di policy 24
Esempi di file di policy grant { permission java.net.socketpermission *, connect ; //il client puo` collegarsi a qssi host, dominio o port permission java.net.socketpermission *, accept ; //il server accetta connessioni da qssi indirizzo e port permission java.io.filepermission /tmp/*, read ; //puo` leggere file (fuori dalle sue sottodirectory) //solo su /tmp/* } grant { permission java.security.allpermission; //massimamente permissiva, accettabile in fase di test, //non in produzione } 25