close

Java Remote Method Invocation

Ugrás a navigációhoz Ugrás a kereséshez

Az RMI ( Java Remote Method Invocation ) egy olyan mechanizmus, amelyet a Java kínál egy metódus távoli meghívására . A szabványos Java futási környezet része, és egyszerű mechanizmust biztosít a szerverkommunikációhoz az elosztott Java-alkalmazásokban. Ha más technológiák közötti kommunikációra van szükség, az RMI helyett CORBA -t vagy SOAP -ot kell használni.

Az RMI-t a programozásban való könnyű használhatóság jellemzi, mivel kifejezetten Java-hoz készült; objektumátadást biztosít hivatkozáson keresztül (a SOAP nem engedélyezi), elosztott szemétgyűjtést (Distributed Garbage Collector) és tetszőleges típusátadást (a funkciót a CORBA nem biztosítja).

Az RMI-n keresztül a Java programok exportálhatnak egy objektumot , így az objektum elérhetővé válik a hálózaton keresztül, és a program egy TCP-porton vár kérésekre . Ezt követően a kliens csatlakozhat és meghívhatja az objektum által biztosított metódusokat.

A felhívás a következő lépésekből áll:

  • Paraméterek rendezése (a Java szerializációs funkciójával).
  • A metódus meghívása (a kliensé a szerveren). A hívó válaszra vár.
  • A végrehajtás befejeztével a szerver sorba rendezi a visszatérési értéket (ha van), és elküldi a kliensnek.
  • Az ügyfélkód megkapja a választ, és úgy folytatódik, mintha a hívás helyi lett volna.

Kontextus

A JDK 1.1-es verziója óta a Java saját ORB -vel rendelkezik : RMI (Remote Method Invocation). Bár az RMI általános értelemben ORB, nem CORBA-kompatibilis modell. Az RMI a Java nyelven natív, vagyis az alapnyelv kiterjesztése. Az RMI teljes mértékben a Java Object Serialization magjára támaszkodik, csakúgy, mint a hordozhatóság megvalósítására, valamint az objektumok más rendszereken való betöltésére és eltávolítására szolgáló mechanizmusokra stb.

Az RMI használata nagyon természetes minden Java programozó számára, mivel nem kell teljesen más új technológiát tanulnia, mint amivel fejleszteni fog. Az RMI-nek azonban vannak korlátai a Java-val való szoros integráció miatt, amelyek közül a fő az, hogy ez a technológia nem teszi lehetővé az interakciót más nyelven írt alkalmazásokkal.

Az RMI, mint a Java kiterjesztése, egy programozási technológia, amelyet arra terveztek, hogy a problémákat végrehajtható kód írásával és rendszerezésével oldja meg. Így az RMI egy sajátos pontot jelent a programozási technológiák terén a C, C++, Smalltalk stb. mellett.

A fő különbség az RPC és az RMI használata között az, hogy az RMI a Java programozási nyelven alapuló távoli eljáráshívási mechanizmus, amely támogatja az objektumok közötti interakciót, míg az RPC nem támogatja ezt a funkciót.

Építészet

Az RMI architektúra négyszintű modellnek tekinthető.

Első réteg

Az első réteg az alkalmazási réteg, és az ügyfél- és kiszolgálóalkalmazások tényleges megvalósításának felel meg. Itt zajlanak a távoli objektumok elérésére és exportálására irányuló magas szintű hívások. Minden olyan alkalmazásnak, amely azt szeretné, hogy metódusai elérhetők legyenek a távoli ügyfelek számára, deklarálniuk kell ezeket a metódusokat egy , a java.rmi.Remote kiterjesztésű felületen . Egy ilyen interfész alapvetően egy objektum távolról elérhetőként való "megjelölésére" szolgál. A metódusok megvalósítása után az objektumot exportálni kell. Ez megtehető implicit módon, ha az objektum kiterjeszti az UnicastRemoteObject osztályt (java.rmi.server csomag), vagy megteheti explicit módon ugyanazon csomag exportObject() metódusának meghívásával.

Második réteg

A 2. réteg a proxyréteg vagy a vázcsonk réteg. Ez a réteg az, amely közvetlenül érintkezik az alkalmazási réteggel. Minden távoli objektum hívása és művelete, paramétereikkel és visszatérési objektumaival együtt ebben a rétegben történik.

Harmadik réteg

A 3. réteg a távoli referenciaréteg, és a távoli hívások szemantikai részének kezeléséért felelős. Feladata továbbá az objektumreplikáció felügyelete és a megvalósítás-specifikus feladatok végrehajtása távoli objektumokkal, mint például a szemantikai perzisztencia és a megszakadt kapcsolatok helyreállításának megfelelő stratégiái. Ebben a rétegben folyamorientált kapcsolat várható a szállítási rétegtől.

Negyedik réteg

A 4. réteg a szállítási réteg. Feladata a szükséges kapcsolatok létrehozása és az adatok egyik gépről a másikra történő szállításának irányítása. Az RMI mögöttes szállítási protokoll a Java Remote Method Protocol (JRMP), amelyet csak a Java programok "értenek".

Elemek

Minden RMI-alkalmazás általában 2 részre oszlik:

  • Egy kiszolgáló, amely néhány távoli objektumot hoz létre, hivatkozásokat hoz létre, hogy elérhetővé tegye őket, és várja, hogy a kliens meghívja őket.
  • Egy ügyfél, amely hivatkozást kap a kiszolgálón lévő távoli objektumokra, és meghívja azokat.

Példa

Az RMI-kiszolgáló egy távoli objektum meghatározásából áll, amelyet az ügyfelek használni fognak. Távoli objektum létrehozásához meg kell határozni egy interfészt , és a távoli objektum egy osztály lesz, amely megvalósítja az interfészt. Nézzük meg, hogyan hozhat létre példaszervert 3 lépésben:

  • Határozza meg a távoli interfészt. Távoli interfész létrehozásakor:
    • A felületnek nyilvánosnak kell lennie.
    • A java.rmi.Remote felületről kell örökölnie, jelezve, hogy bármely Java virtuális gépről hívható.
    • Minden távoli metódusnak el kell dobnia a java.rmi.RemoteException kivételt a throws záradékában, az általa kezelhető kivételeken kívül.
nyilvános  felület  A MyRemoteInterface  kiterjeszti a  java -t . rmi . A távoli 
{ 
  public  void  myMethod1 ()  Java -t dob  . rmi . RemoteException ; public int myMethod2 () dobja a java -t . rmi . RemoteException ; }
      

  • Valósítsa meg a távoli interfészt
public  class  A MyRemoteClass  
 kiterjeszti a  java -t . rmi . szerver . Az UnicastRemoteObject  
 implementálja a  MyRemoteInterface -t 
{ 
 public  MyRemoteClass ()  java -t dob  . rmi . RemoteException { szuper (); //Az alaposztály konstruktorának meghívása (UnicastRemoteObject) // Konstruktor kódja }
 
    
   
 
 
 public  void  myMethod1 ()  java -t dob  . rmi . RemoteException { // Ide tesszük a kívánt kódot System . ki . println ( "Az 1. módszerben vagyok ()" ); }
 
   
   
 

 public  int  myMethod2 ()  dobja a  java -t . rmi . RemoteException 
 { 
   return  5 ;  // Ide tesszük a kívánt kódot 
 }

 public  void  otherMethod () 
 { 
   // Ha egy másik metódust definiálunk, akkor az // nem hívható 
   meg távolról, mivel nem a távoli felületről 
 }
 
 public  static  void  main ( String []  args ) 
 { 
   try 
   { 
     MyRemoteInterface  mir  =  new  MyRemoteClass (); 
     java . rmi . Elnevezés . rebind ( "rmi://"  +  java . net . InetAddress . getLocalHost (). getHostAddress ()  + 
                             ":"  +  args [ 0 ]  +  "/TestRMI" ,  mir ); 
   } 
   fogás  ( Kivétel  e ) 
   { 
     e . printStackTrace (); 
   } 
 } 
}
  • Mint látható, a MyRemoteClass osztály az általunk korábban definiált MyRemoteInterface felületet valósítja meg. Ezenkívül az UnicastRemoteObject-től örökli, amely egy Java osztály, amelyet szuperosztályként használhatunk távoli objektumok megvalósításához.
  • Ezután az osztályon belül definiálunk egy konstruktort (ami a RemoteException kivételt dobja, mert azt az UnicastRemoteObject szuperosztály is dobja), és az általa megvalósított interfész(ek) metódusait.
  • Végül a fő metódusban meghatározzuk a kódot a megosztani kívánt távoli objektum létrehozásához, és a távoli objektumot láthatóvá tesszük az ügyfelek számára a Naming osztály és annak rebind(...) metódusa segítségével.

Megjegyzés: A kényelem kedvéért a main() metódust ugyanabba az osztályba helyeztük. Meghatározható egy külön osztály, amely felelős a távoli objektum regisztrálásáért.

  • Fordítsa le és futtassa a szervert

A szervert már meghatároztuk. Most össze kell állítanunk az osztályokat a következő lépésekkel:

    • Összeállítjuk a távoli felületet. Ezenkívül egy JAR-fájlba csoportosítjuk, hogy mind a kliensen, mind a szerveren jelen legyen:
javac MyRemoteInterface.java
jar cvf objRemotes.jar MyRemoteInterface.class
    • Ezután összeállítjuk az interfészeket megvalósító osztályokat. És mindegyikhez létrehozzuk a Stub és Skeleton fájlokat, hogy fenntartsuk a távoli objektumra való hivatkozást, az rmic paranccsal:
set CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;.
javac MyRemoteClass.java
rmic -d . MyRemoteClass

Munkakönyvtárunkban láthatjuk, hogy az RMI architektúra stub-skeleton rétegének megfelelően két .class fájl automatikusan létrejött (MiClaseRemota_Skel.class és MiClaseRemota_Stub.class).

  • A szerver futtatásához kövesse az alábbi lépéseket:
    • Elindul az RMI naplózás, amely lehetővé teszi a távoli objektumok naplózását és keresését. A rendszerleíró adatbázis felelős a megosztandó távoli objektumok kezeléséért, és az ügyfelek kérésére megkeresi azokat. A Java-val terjesztett rmiregistry alkalmazással fut, amelyhez opcionálisan átadhatjuk a csatlakozáshoz szükséges portot (alapértelmezés szerint 1099).

Windows esetén ezt kell végrehajtani:

indítsa el az rmiregistry 1234-et

És Linux esetében:

nyilvántartás és
    • Végül elindul a szerver:
java -Djava.rmi.server.hostname=127.0.0.1 MyRemoteClass 1234
  • Hozzon létre egy RMI klienst

Most egy klienst fogunk meghatározni, amely hozzáfér az általunk létrehozott távoli objektum(ok)hoz. Ehhez a következő lépéseket követjük:

    • Határozza meg az osztályt a szükséges távoli objektumok lekéréséhez

A következő osztály egy MyRemoteInterface típusú objektumot kap, amelyet a szerverünkön implementálunk:

public  class  MyRMIClient 
{

 privát  MyRMIClient (){}; 

 public  static  void  main ( String [ ]  args ) 
 { 
   try 
   { 
     MyRemoteInterface  mir  =  ( MyRemoteInterface ) java . rmi . Elnevezés . keresés ( "rmi://"  +  
                             args [ 0 ]  +  ":"  +  args [ 1 ]  +  "/RMITeszt" );
     
     // A myMethod1() kinyomtatása annyiszor, ahányszor a myMethod2() visszaadja 
     az  ( int  i = 1 ; i <= myr . myMethod2 (); i ++ )  
         myr . myMethod1 (); 
   } 
   fogás  ( Kivétel  e ) 
   { 
     e . printStackTrace (); 
   } 
 } 
}

Amint láthatja, ez egyszerűen abból áll, hogy meg kell keresni a távoli objektumot a távoli gép RMI-nyilvántartásában. Ehhez a Naming osztályt és annak lookup(...) metódusát használjuk.

    • Fordítsa le és futtassa a klienst

Miután már meghatároztuk az ügyfelet, a fordításhoz a következőket tesszük:

set CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;.
javac MyRMIClient.java

Ezután az ügyfél futtatásához a következőket tesszük:

java MyClientRMI 127.0.0.1 1234

A távoli osztály csonkfájljának elérhetőnek kell lennie. Ehhez vagy átmásoljuk a kliensre, és beillesztjük a CLASSPATH-jába, vagy eltávolítjuk a szerver CLASSPATH-jából, és beírjuk az elérési útját a szerver java.rmi.codebase-jába (ha nem távolítják el a szerver CLASSPATH-jából, akkor a java opció. rmi.codebase, és a kliens nem fogja tudni elérni a csonkot). Ha megnézzük azt az ablakot, ahol az RMI szerver fut, látni fogjuk, hogyan találták meg a távoli objektumot, és hogyan hajtották végre a metódusait:

Lásd még

Külső linkek