1 / 39

Java

Java. Remote Method Invocation. Distributed Computing with RMI. Remote Method Invocation (RMI) technology, First introduced in JDK 1.1 Elevates network programming to a higher plane. The world of distributed object computing. . Goals.

baruch
Télécharger la présentation

Java

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java Remote Method Invocation

  2. Distributed Computing with RMI • Remote Method Invocation (RMI) technology, • First introduced in JDK 1.1 • Elevates network programming to a higher plane. • The world of distributed object computing.

  3. Goals • To use the same syntax and semantics used for non-distributed programs in the distributed programs • This is done by carefully mapping Java classes and objects to work in a distributed (multiple JVM) computing environment.

  4. Comparison

  5. Comparison

  6. Interfaces: The Heart of RMI • Important principle on which RMI is based: • The definition of behavior and the implementation of that behavior are separate concepts the code for this is also separate and runs on separate JVMs. • This way it fits with the needs of a distributed system where clients are concerned about the definition of a service • Servers are focused on providing the service. • In RMI, the definition of a remote service is coded using a Java interface. • The implementation of the remote service is coded in a class. • Therefore, the key to understanding RMI is to remember that interfaces define behavior and classes define implementation.

  7. RMI architecture • The first class is the implementation of the behavior, and it runs on the server. • The second class acts as a proxy for the remote service and it runs on the client. • This is shown in the diagram.

  8. RMI architecture

  9. RMI architecture • Java RMI is comprised of three layers that support the interface • The first layer is the Stub/Skeleton Layer. • The second layer is the Remote Reference Layer (RRL). • The third layer is the transport layer..

  10. The RMI architecture

  11. Stub and Skeleton Layer • This layer is responsible for managing the remote object interface between the client and server. • The stub and skeleton layer of RMI lie just beneath the view of the Java developer. In this layer, RMI uses the Proxy design pattern. • In the Proxy pattern, an object in one context is represented by another (the proxy) in a separate context. • The proxy knows how to forward method calls between the participating objects. The following class diagram illustrates the Proxy pattern.

  12. Stub & Skeleton layer

  13. Stub & Skeleton layer • In RMI's use of the Proxy pattern, the stub class plays the role of the proxy, and the remote service implementation class plays the role of the RealSubject. • A skeleton is a helper class that is generated for RMI to use. The skeleton understands how to communicate with the stub across the RMI link. The skeleton carries on a conversation with the stub; it reads the parameters for the method call from the link, makes the call to the remote service implementation object, accepts the return value, and then writes the return value back to the stub. • RMI uses reflection to make the connection to the remote service object. • Skeleton classes and objects are compatible in in JDK 1.1 and JDK 1.1 system implementations.

  14. Remote Reference Layer • This layer is responsible for managing the "liveliness" of the remote objects. It also manages the communication between the client/server and virtual machine s, (e.g., threading, garbage collection, etc.) for remote objects. • The Remote Reference Layers defines and supports the invocation semantics of the RMI connection. This layer provides a RemoteRef object that represents the link to the remote service implementation object. • The stub objects use the invoke() method in RemoteRef to forward the method call. The RemoteRef object understands the invocation semantics for remote services. • The JDK 1.1 implementation of RMI provides only one way for clients to connect to remote service implementations: a unicast, point-to-point connection. Before a client can use a remote service, the remote service must be instantiated on the server and exported to the RMI system. (If it is the primary service, it must also be named and registered in the RMI Registry).

  15. Remote reference layer • The Java 2 SDK implementation of RMI adds a new semantic for the client-server connection. In this version, RMI supports activatable remote objects. When a method call is made to the proxy for an activatable object, RMI determines if the remote service implementation object is dormant. If it is dormant, RMI will instantiate the object and restore its state from a disk file. Once an activatable object is in memory, it behaves just like JDK 1.1 remote service implementation objects. • Other types of connection semantics are possible. For example, with multicast, a single proxy could send a method request to multiple implementations simultaneously and accept the first reply (this improves response time and possibly improves availability). In the future, Sun may add additional invocation semantics to RMI.

  16. Transport Layer • This is the actual network/communication layer that is used to send the information between the client and server over the wire. It is currently TCP/IP based. If you are familiar with RPC, it is a UDP-based protocol which is fast but is stateless and can lose packets. TCP is a higher-level protocol that manages state and error correction automatically, but it is correspondingly slower than UDP • The Transport Layer makes the connection between JVMs. All connections are stream-based network connections that use TCP/IP. • Even if two JVMs are running on the same physical computer, they connect through their host computer's TCP/IP network protocol stack. • You will need an operational TCP/IP configuration on your computer to run the Exercises. • The following diagram shows the use of TCP/IP connections between JVMs.

  17. Transport layer

  18. Transport Layer • TCP/IP provides a persistent, stream-based connection between two machines based on an IP address and port number at each end. Usually a DNS name is used instead of an IP address; this means you could talk about a TCP/IP connection between flicka.magelang.com:3452 and rosa.jguru.com:4432. In the current release of RMI, TCP/IP connections are used as the foundation for all machine-to-machine connections. • On top of TCP/IP, RMI uses a wire level protocol called Java Remote Method Protocol (JRMP). JRMP is a proprietary, stream-based protocol that is only partially specified is now in two versions. • The first version was released with the JDK 1.1 version of RMI and required the use of Skeleton classes on the server. • The second version was released with the Java 2 SDK. It has been optimized for performance and does not require skeleton classes. Some other changes with the Java 2 SDK are that RMI service interfaces are not required to extend from java.rmi.Remote and their service methods do not necessarily throw RemoteException. • Sun and IBM have jointly worked on the next version of RMI, called RMI-IIOP, which will be available with Java 2 SDK Version 1.3. The interesting thing about RMI-IIOP is that instead of using JRMP, it will use the Object Management Group (OMG) Internet Inter-ORB Protocol, IIOP, to communicate between clients and servers.

  19. Transport layer • The OMG is a group of more than 800 members that defines a vendor-neutral, distributed object architecture called Common Object Request Broker Architecture (CORBA). • CORBA Object Request Broker (ORB) clients and servers communicate with each other using IIOP. With the adoption of the Objects-by-Value extension to CORBA and the Java Language to IDL Mapping proposal, the ground work was set for direct RMI to CORBA integration. This new RMI-IIOP implementation supports most of the RMI feature set, except for: • java.rmi.server.RMISocketFactory • UnicastRemoteObject • Unreferenced • The DGC interfaces • The RMI transport layer is designed to make a connection between clients and server, even in the face of networking obstacles. • While the transport layer prefers to use multiple TCP/IP connections, some network configurations only allow a single TCP/IP connection between a client and server (some browsers restrict applets to a single network connection back to their hosting server). • In this case, the transport layer multiplexes multiple virtual connections within a single TCP/IP connection.

  20. Naming Remote Objects • During the presentation of the RMI Architecture, one question has been repeatedly postponed: "How does a client find an RMI remote service? " Now you'll find the answer to that question. Clients find remote services by using a naming or directory service. This may seem like circular logic. How can a client locate a service by using a service? In fact, that is exactly the case. A naming or directory service is run on a well-known host and port number. • RMI can use many different directory services, including the Java Naming and Directory Interface (JNDI). RMI itself includes a simple service called the RMI Registry, rmiregistry. The RMI Registry runs on each machine that hosts remote service objects and accepts queries for services, by default on port 1099. • On a host machine, a server program creates a remote service by first creating a local object that implements that service. Next, it exports that object to RMI. When the object is exported, RMI creates a listening service that waits for clients to connect and request the service. After exporting, the server registers the object in the RMI Registry under a public name.

  21. Naming Remote Objects • On the client side, the RMI Registry is accessed through the static class Naming. It provides the method lookup() that a client uses to query a registry. The method lookup() accepts a URL that specifies the server host name and the name of the desired service. The method returns a remote reference to the service object. The URL takes the form: • rmi://<host_name> [:<name_service_port>] /<service_name> • where the host_name is a name recognized on the local area network (LAN) or a DNS name on the Internet. The name_service_port only needs to be specified only if the naming service is running on a different port to the default 1099.

  22. Using RMI • It is now time to build a working RMI system and get hands-on experience. • A working RMI system is composed of several parts. • Interface definitions for the remote services • Implementations of the remote services • Stub and Skeleton files • A server to host the remote services • An RMI Naming service that allows clients to find the remote services • A class file provider (an HTTP or FTP server) • A client program that needs the remote services Assuming that the RMI system is already designed, you take the following steps to build a system: • Write and compile Java code for interfaces • Write and compile Java code for implementation classes • Generate Stub and Skeleton class files from the implementation classes • Write Java code for a remote service host program • Develop Java code for RMI client program • Install and run RMI system

  23. Example of RMI • The example used in this article is an amortization schedule application. • The client requests a local schedule object from the server through a remote object and passes an amount and duration of a loan to the server. • The server instantiates a local schedule object with the amount and duration along with the interest rate the server knows about. • Then the schedule object is serialized and returned back to the client. • The client can then print the object or modify it at this point. The client has its own private copy of the schedule object. • There is an illustration that serves as a reference for the parts of the RMI application.

  24. Example of RMI program

  25. Creating the Interface Definitions File • The first thing that you must do to develop an RMI application is to define the remote interface. The interface defines what remote methods/variables are going to be exported from the remote object. Usually the interface defines methods only because variables have to be declared final (i.e., constant) if they are in an interface definition. • The remote interface needs to import the RMI package, and every exported method must throw an RMI remote exception to manage errors during invocation. Below is the code for the mathCalc.java interface definition file in our example.

  26. Example /**************************************************** * module: mathCalc.java ****************************************************/ import java.lang.*; import java.rmi.*; public interface mathCalc extends java.rmi.Remote { public schedule amortizeSchedule( float ammount, int duration ) throws java.rmi.RemoteException; public void printRate() throws java.rmi.RemoteException; } If you are familiar with using Java and interfaces, converting your local objects to remote objects can be done very quickly with minor modifications to your source. You need to include the Java RMI package and manage RMI remote exceptions on all your exported local methods.

  27. Creating the Interface Implementation File • Once the interface definition file is created, you need to define the actual code that supports the interface on the server. • Below is an example of the mathCalcImp.java interface implementation file used to provide that support.

  28. Example /**************************************************** * module: mathCalcImp.java ****************************************************/ import java.rmi.*; import java.rmi.server.*; class mathCalcImp extends UnicastRemoteObject implements mathCalc { float interestRate = (float)7.5; mathCalcImp() throws java.rmi.RemoteException { } public schedule amortizeSchedule( float ammount, int duration ) throws java.rmi.RemoteException { System.out.println("Amortizeing Schedule."); return( new schedule( interestRate, ammount, duration ) ); } public void printRate() throws java.rmi.RemoteException { System.out.println("Current Interest Rate is " + interestRate ); } }

  29. Example • Notice the implementation file imports the package java.rmi.*. It also imports the java.rmi.server.* package. • This is so you can extend the UnicastRemoteObject class to support remote clients. • This class manages client/server and peer/peer connection support for RMI. • Today there is no MulticastRemoteObject class, but it should appear in some JDK 1.2 release. There is, however, enough support in JDK 1.1 to allow you to write your own MulticastRemoteObject class to support multicast remote clients. • Notice how the file defined above implements mathCalc, the remote interface definition that was defined earlier. Each method in the implementation file that is going to be externalized needs to throw a remote exception.

  30. Object Serialization • The amortizeSchedule() method prints a message on the server and instantiates a new local schedule object that is returned to the client. The schedule object is a local object that will be serialized and marshaled into a data stream to be sent back to the client. • Now the serialization of remote objects is the next step. To begin that, the schedule.java.local class is presented below.

  31. void print() { System.out.println("Schedule Created."); System.out.println("Calculation information based on:"); System.out.println(" Rate [%" + interestRate + "]" ); System.out.println(" Ammount [$" + usrAmmount + "]" ); System.out.println(" Duration [ " + loanDuration + "]" ); System.out.println(" Total Loan [$" + totalLoanAmt + "]" ); int couponNum = 0; float balanceRemaining = totalLoanAmt; float monthlyPayment = 0; System.out.println(); System.out.println( "Payment Monthly Payment Ammount Balance Remaining"); System.out.println( "------- ----------------------- -----------------"); while( balanceRemaining > 0 ) { couponNum++; monthlyPayment = totalLoanAmt/loanDuration; if( balanceRemaining < monthlyPayment ) { monthlyPayment = balanceRemaining; balanceRemaining = 0; } else { balanceRemaining = balanceRemaining - monthlyPayment; } System.out.println( couponNum + " " + monthlyPayment + " “ + balanceRemaining ); } /while } /print } /**************************************************** * module: schedule.java ****************************************************/ import java.lang.*; import java.util.*; import java.io.*; class schedule implements Serializable { float totalLoanAmt; float usrAmmount; float interestRate; int loanDuration; schedule( float rate, float ammount, int duration ) { interestRate = rate; usrAmmount = ammount; loanDuration = duration; totalLoanAmt = ammount + (ammount / rate); }

  32. Object Serialization • If you are passing local objects around through remote interfaces, you have to make the defining local class serializable. • Notice that the schedule class implements the serializable interface, but it does not have to provide any code. • This is because Java manages the serialization of serializable interfaces for you. If we were to implement externalizable instead of serializable, then the schedule.java class would have to provide the serialize/deserialize methods. • This would require the schedule class to serialize and deserialize its own data. If you try to pass a local object that has not implemented the serializeable/externalizeable interface, • Java will throw a marshaling exception on the server/client. Note: Be careful when marking a class serializable, because Java will try to "flatten" everything related to that cl., inheritance classes, instances within the class, etc.). • As an example, I would not recommend trying to serialize anything like the root drive on your disk. There is also a lot of overhead involved in the serialization/deserialization process. Use serialization with care.

  33. Creating the Stubs/Skeletons • Now that the interface and implementation files have been created, you need to generate the stubs and skeleton code. • This is done by using the rmic compiler provided by the JDK. • The following command will generate the stub and skeleton .class files, but it will not create the .java files. • If you want to see the Java-generated code, use the -keepgenerated option. • This will leave the .java files files around, but don't try to modify these files. • The rmic compiler also has a -show option that runs it as an AWT application. Command Line > rmic mathCalcImp • After running the rmic compiler, you should see mathCalcImp_Skel.class and mathCalcImp_Stub.class. • These classes are where your references to the remote objects will resolve to in the client's address space. • The RRL will manage the mapping of these objects to the server's address space.

  34. Creating the Client • Now we need to create the client-side application that will use the remote objects. • The client code imports the java.rmi package along with the java.rmi.RMISecurityManager. • The first thing the client needs to do is register a security manager with the system. • The RMI package provides an RMI security manager, but if you like writing security managers, you can register your own. • If a security manager is not registered with the system, Java will only allow resolution of classes locally. • If you are writing an applet instead of an application, the security manager has already been registered for you by the browser. You cannot register another security manager for the applet. • Once you have registered the security manager, you need to create a URL string that is comprised of the server name and remote object name you are requesting. • This will enable the client to look up the remote object on the server via the rmiregistry. • Your client code will call the Naming.lookup method that makes a request to the server to return a remote object reference. • Notice the object returned from the Naming.lookup method is cast to the actual interface class. • This is because the lookup call returns a reference of type Object, an abstract type that needs to be casted to a concrete class (e.g., the interface definition file, mathCalc).

  35. The sample code for calcClient.java. /**************************************************** * module: calcClient.java ****************************************************/ import java.util.*; import java.net.*; import java.rmi.*; import java.rmi.RMISecurityManager; public class calcClient { public static void main( String args[] ) { mathCalc cm = null; int i = 0; System.setSecurityManager( new RMISecurityManager()); try { System.out.println("Starting calcClient"); String url = new String( "//"+ args[0] + "/calcMath"); System.out.println("Calc Server Lookup: url =" + url); cm = (mathCalc)Naming.lookup( url ); if( cm != null ) { String testStr = "Requesting Current Interest Rate..."; // Print Current Interest Rate from the server cm.printRate(); // Amortize a schedule using the server interest // rate. float amount = (float)10000.50; int duration = 36; schedule curschd = cm.amortizeSchedule( amount, duration ); // Print the schedule curschd.print(); } else { System.out.println("Requested Remote object is null."); } } catch( Exception e ) { System.out.println("An error occured"); e.printStackTrace(); System.out.println(e.getMessage()); } } }

  36. The URL name lookup format for an RMI object via the registry looks like this: rmi://www.myserver.com/myObject or //www.myserver.com/myObject • If the client is successful in retrieving the remote reference, it can invoke remote methods on the remote object at this point. • The example makes a call to print the interest rate on the server, and it makes a request to amortize a schedule. • If the amortize schedule is successful, the client gets a local copy of the schedule object. • Then the client can call routines in the schedule object, modify the object, etc. • This is the client's private copy of the object, and the server has no knowledge of any changes to this object made by the client. Local objects are by copy, and remote objects are by reference.

  37. Creating the Server • The server has very simple code that is similar to the client. • Below is the calcServ.java code for the server: /**************************************************** * module: calcServ.java ****************************************************/ import java.util.*; import java.rmi.*; import java.rmi.RMISecurityManager; public class calcServ { public static void main( String args[] ) { System.setSecurityManager( new RMISecurityManager()); try { System.out.println("Starting calcServer"); mathCalcImp cm = new mathCalcImp(); System.out.println("Binding Server"); Naming.rebind("calcMath", cm ); System.out.println("Server is waiting"); } catch( Exception e ) { System.out.println("An error occured"); e.printStackTrace(); System.out.println(e.getMessage()); } } }

  38. Creating the server • The server has the same requirements as the client has regarding the security manager. Once the server has registered properly with the security manager, the server needs to create an instantiation of the mathCalcImp implementation objec • This is the actual remote object the server exports. Since the server uses the rmiregistry, you must bind (i.e., alias) an instance of the object with the name that will be used to look up the object. • Note: The server sample uses rebind instead of bind. • This is to avoid the following problem with bind; i.e., • if you start your server and bind an object to the registry then later start a newer version of the server, the bind will not take place because a previous version already exists. • When your client references the server, it will get the original reference to the object and not the latest. • Also, when the client tries to reference the remote object, the server will throw an exception because the object is no longer valid. • If you instead use rebind, then each time you start a new server, it will bind the latest object for the name lookup and replace the old object. • You can export as many objects as you like. For the sake of simplicity, the example only exports one object. • Additionally, you can have a factory class that returns object references or you can use the registry to look up multiple names of objects. • You normally only need one registry running, but Java does not preclude running multiple registries on different ports. • The client needs to use the correct lookup method to gain access to the correct registry on a port number. • If you are looking at this server application and wondering how it continues to run after it has seemingly completed its mission, the answer is that the main thread goes away at this point. • However, when the server calls the registry to bind the object, it creates another thread under the covers that blocks waiting in a loop for a registry derigstration event. This keeps the server from terminating. • If you don't use the registry, the server example needs to be modified to stay alive to support the references to remote objects.

  39. Building the Sample • You need to compile the client and the server code by doing the following: javac calcClient.java javac calcServ.java • Starting the Sample • Now you are ready to run the sample RMI application. The first thing to do is to start the rmiregistry on the server. Ensure that your CLASSPATH is set up so that the registry can find your server classes in its path. Start the rmiregistry as follows: start rmiregistry (optional port : default port 1099 ) [The optional port number can be left out, in which case it defaults to 1099. If this is not the desired port, specify one as in "start rmiregistry 1095". Ed.] • Next, start the server as follows: start java calcServ • The server will start and print a message that it is waiting for requests. • Now you are ready to start the client application as follows: start java calcClient www.myserver.com • At this point you should see a request come into the server to print the interest rate and request a remote object reference. The client will then display the contents of the schedule object returned from the server.

More Related