Lập trình phân tán với java RMI

12 722 7
Lập trình phân tán với java RMI

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Trang 222 Chng 10: LP TRÌNH PHÂN TÁN VI JAVA RMI ( REMOTE METHOD INVOKE) Lp trình phân tán vi RMI là mt trong nhng vn  nóng bng ca nn công nghip phn mm ngày nay.  giúp các bn có các kin thc c bn v lp trình phân tán và công ngh lp trình phân tán RMI. Chng này ta tho lun v các khía cnh ó. Sau khi hc xong chng này ngi hc có th: Hiu c khái nim v lp trình phân tán và công ngh RMI ng dng công ngh RMI  xây dng các ng dng phân tán Chuyn tham s cho phng thc triu gi t xa và nhn kt qu tr v t phng thc triu gi t xa I. RMI và lp trình phân tán i tng Thông thng mã lnh ca mt chng trình khi thc thi c tp trung trên cùng t máy, ây là cách lp trình truyn thng. S phát trin nh v bão ca mng máy tính c bit là mng Internet toàn cu, ã khin các chng trình truyn thng này không còn áp ng c yêu cu na. Các chng trình bây gi yêu cu phi có s hp tác x lý, tc là mã lnh ca nó ã không tp trung trên mt máy mà c phân tán trên nhiu máy. Khi t ng dng có mã lnh thc thi c phân tán trên nhiu máy thì chng trình ó c i là chng trình phân tán và vic lp trình  to ra các chng trình này c gi là lp trình phân tán. Có rt nhiu công ngh lp trình phân tán nh: DCOM, CORBA, RMI, EJB trong ó RMI là công ngh thun Java và d lp trình nht. Thông thng nu các i tng c tp trung trên cùng mt máy thì bn có th triu gi các phng thc ca nó bng cách gu cho nó mt thông báo, câu hi t ra là làm th nào  có th triu gi các phng thc ca mt i tng nm trên mt máy khác. ây chính là ni dung ca lp trình phân tán mã lnh RMI (Remote Method Invoke – tm ch là triu gi phng thc t xa). RMI là cách thc giao tip gia các i tng Java có mã lnh cài t (bao gm c phng thc và thuc tính) nm trên các máy khác nhau có th triu gi ln nhau. Hình sau mô hình triu gi i tng phân tán. Trên máy A các i tng A1, A2 i các phng thc ca nhau c gi là triu gi phng thc cc b (local method invoke) ây là cách lp trình hng i tng truyn thng vn s dng, tng t các i ng B1, B2, B3 là các i tng cc b. Tuy nhiên các i tng Java có th triu gi phng thc ca mt i tng nm trên mt máy khác da vào giao thc triu gi t xa RMI. Trong mô hình di ây thì li triu gi phng thc ca i tng B2 ( nm trên máy B) ti tng A1 ( nm trên máy A) là li gi phng thc t xa. Trang 223 II. Gi phng thc t xa và các vn  phát sinh Vic triu gi mt phng thc t xa thot nhìn có vn gin nhng thc t li phc tp hn triu gi phng thc cc b. Các i tng trên hai máy khác nhau hot ng trên hai tin trình khác nhau (có hai không gian a ch khác nhau) nên vic tham chiu bin a chi tng là khác nhau. Ví d khi bn truyn mt i tng cho mt phng thc triu gi t xa thì thc s bn truyn mt tham chiu i tng n phng thc t xa, tuy nhiên vùng nh thc s ca i tng li nm trên mt máy khác. Li gi phng thc cc b luôn tr v kt qu thông qua ngn xp trong khi li gi phng thc  xa kt qu tr v phi thông qua kt ni mng chính vì vy các s c v truyn thông luôn có th sy ra, nh vy vic bt và kim soát li trong các ng dng phân tán là rt t. III. Vai trò ca các lp trung gian  i vi li gi phng thc cc b, các tham s truyn vào phng thc cng nh t qu tr v t phng thc c thc hin thông qua ngn xp (stack) trong khi li gi phng thc t xa phi c óng gói và chuyn qua mng.  n gin và trong sut i vi ngi lp trình i tng Java trên hai máy khác nhau không triu gi phng thc ca nhau mt cách trc tip mà thông qua lp trung gian. p trung gian tn ti  c hai phía: phía máy khách (ni gi phng thc ca i tng  xa) và máy ch (ni i tng thc sc cài t). Phía máy khác lp trung gian này c gi là stub (lp móc), phía máy ch lp trung gian c gi là skeletion (lp ni). Ta có th hình dung lp trung gian stub và skel là hai ngi trung gian giúp các i ng  xa có th giao dch c vi nhau. Máy A A1 A2 Máy B B1 B2 B3 Máy C C Hình 1: Mô hình triu gi các phng thc t xa Trang 224 Trong hình trên bn có i tng C1 c cài t trên máy C. trình biên dch Java giúp ta to ra hai lp trung gian C1_stub và C1_skel. Lp C1_stub c mang v máy A. Khi A1 trên máy A triu gi phng thc ca i tng C1 nó s chuyn li gi phng thc cho lp trung gian C1_stub. Lp trung gian C1_stub có trách nhim óng gói các tham  chuyn tham s qua mng n phng thc c triu gi ca i tng C1. Trên máy C lp trung gian C1_Skel có nhim v nhn các tham s và chuyn vào vùng a ch thích p sau ó gi phng thc tng ng. Kt qu tr v (nu có) ca phng thc do C1 tr  sc lp C1_Skel óng gói và chuyn ngc v cho trình khách. Trên máy khách lp trung gian C1_Stub chuyn giao kt qu cui cùng li cho A1. Bng c ch này A1 luôn ngh rng i tng C1 ang tn ti ngay trên cùng máy vi nó nh các i tng cc b khác. Hn na nh có lp trung gian C1_Stub mà khi kt ni mng gp s c thì lp trung gian stub s luôn bit cách thông báo li n i tng A1. Thc t làm cách nào A1 tham chiu c n C1, mt khi không có i tng C1 c cài t trên máy A? C1_Stub trên máy A ch thc hin vic chuyn tham s, nhn kt qu tr v nu có và thc hin các giao thc mng, nó không phi là hình nh ca C1.  làm c u này i tng C1 cn cung cp mt giao din tng ng vi các phng thc mà các i tng trên máy khác có th triu gi. Chúng ta tip tc làm sáng tìêu này khi nói  giao din t xa. IV. Cài t i tng phân tán 1. Giao din t xa Khi bn mun to ra mt s vt t xa thì bn che mt n cài t nn bng cách truyn qua mt giao din. Vy khi khách thu c mt tham chiu n i tng t xa thì thc cht ó là mt giao din. Máy A C1_stub A1 A1 B1_stub Máy C C1_skel C1 Máy B B1 B1_skel Hình 2: Gi phng thc ca i tng thông qua lp trung gian Trang 225 Khi to ra mt giao din t xa, thì bn phi tuân theo các hng dn sau: Giao din t xa phi là mt giao din public, tc là khi to ra mt giao din t xa ta phi thêm t khoá public vào trc nh ngha giao din. Bng không, khi bn tham chiu n i tng t xa bn s thu c mt ngoi l Giao din t xa phi là giao din c k tha t giao din Remote i phng pháp trong giao din t xa phi khai báo RemoteException trong mnh  throws bên bt c ngoi l nào khác, tc là tt c các phng thc trong giao din t xa u phi ném ra ngoi l RemoteException u tham s truyn cho phng thc hoc giá tr nhn v t thc triu gi t xa là mt i tng thì i tng ó phi trin khai giao din Remote hoc giao din Serializable Thông thng bn thng thy mt giao din t xa có cu trúc nh sau: import java.rmi.*; public interface RemoteInterface extends Remote{ [public] ReturnDataType method1([DataType arg1,][ DataType arg2,] ) throws RemoteException; [public] ReturnDataType method2() throws RemoteException; } Ví d 1-1: Sau ây là mt giao din t xa n gin ca ng dng HelloRMI HelloRMI.java import java.rmi.*; public interface HelloRMI extends Remote{ public String sayHello() throws RemoteException; } Nhìn vào giao din này ta thy nó ging bt k giao din nào khác ngoi tr nó c  rng t giao din Remote và tt c các phng thc trong giao din này u phi nem ra ngoi l RemoteException, bn hãy nh rng tt c các phng thc c khai báo trong giao din s tng là public, th nên trong giao din trên bn có th b t khoá public khi khai báo phng thc sayHello. Bn tin hành biên dch javac HelloRMI.java bn s thu c tp tin HelloRMI.class 2. Trin khai giao din t xa Sau khi bn to ra giao din t xa, công vic tip theo mà bn cn phi làm là trin khai tt c các phng thc trong giao din t xa. Ví d 1-2: Sau ây là cài t ca giao din t xa HelloRMI HelloRMIImpl.java import java.rmi.*; public class HelloRMIImpl implements HelloRMI { public String sayHello() throws RemoteException { return "Hello RMI"; } } Vn t ra là làm th nào  cài t i tng HelloRMI lên mt máy (máy 2) và gi phng thc sayHello() ca HelloRMI t máy khác (máy 1)? Nhã nêu  trên ta không i c phng thc sayHello ca HelloRMI mt cách trc tip mà cn có thêm hai lp trung gian là HelloRMIImpl_Stub và HelloRMIImpl_Skel. Da vào lp Trang 226 HelloRMIImpl.class, trình biên dch rmic.exe ca Java s giúp ta to ra hai lp trung gian Stub và Skel. Bn m ca s DOS – Prompt và gõ vào dòng lnh Rmic HelloRMIImpl.class t qu bn s thu c hai tp HelloRMIImpl_Stub.class và HelloRMIImpl_Skel.class 3. Cài t, ng kí i tng t xa Bc tip theo sau khi bn cài t giao din t xa là công vic ng ký nó vi trình rmiregistry theo mu sau: Ví d 1-4: Ví d sau là chng trình ng ký và cài t i tng HelloRMIImpl vi trình ch rmiregistry. Setup.java import java.rmi.server.*; import java.rmi.*; import java.net.*; public class Setup { public static void main(String[] args) { // to ra mt th hin ca i tng t xa HelloRMI h=new HelloRMIImpl(); try { // Khai báo i tng có kh nng triu gi t xa UnicastRemoteObject.exportObject(h); // ng ký nó vi trình rmiregistry Naming.bind("//localhost/hello, h); // có th thay phng thc bind bi phng thc rebind nh sau: // Naming.rebind("//localhost/hello, h); } catch (MalformedURLException ex) { } catch (AlreadyBoundException ex) { } catch (RemoteException ex) { } } } Công vic u tiên bn phi làm khi cài t i tng t xa là to ra mt th hin a i tng t xa. HelloRMI h=new HelloRMIImpl(); bn có th thay bng dòng lnh HelloRMIImpl h=new HelloRMIImpl(); Tip theo bn gi phng thc tnh exportObject ca lp UnicastRemoteObject  máy o java bit i tng h (HelloRMI) là i tng có kh nng truy xut t xa. UnicastRemoteObject.exportObject(h); u ý  s dng c lp UnicastRemoteObject bn phi khai báo import java.rmi.server.*; u chng trình Trang 227 c cui cùng là bn t cho i tng h mt cái tên gi nh và ng ký tên này i bng ký rmiregistry. Phng thc tnh ca lp Naming s thc hin u này Naming.bind("[rmi:]//hostname[:port]/name, h); Phng thc bind có hai tham s: tham s th nht là mt chui nh v URL, i s th hai là bn thân i tng cn ng ký Chui nh v URL có nh dng nh sau: [rmi:]//hostname[:port]/name Trong ó: mri là tên giao thc,ây là phn tu chn, mc nh giao thc là rmi nên bn có th b qua. Hostname là tên ca máy ch hoc a ch IP ca máy ch ni i tng phân tán ang n ti. Port là s hiu cng ca chng trình rmiregistry, ây là tham s tu chn, nu b qua tham s này thì cng mc nh là 1009 Name là tên gi nh ca i tng phân tán Phng thc bind si vào vòng lp vô hn ch kt ni t máy kách. Các chng trình phía máy khách s da vào chui nh v URL mà ta ng ký vi trình rmiregistry  truy tìm tham chiu n i cn dùng. n có th khi ng bng ký rmiregistry này âu? Bn m ca s DOS-Prompt và cho chy chng trình rmiregistry này t dòng lnh nh sau: C:\JDK1.4\bin\rmiregistry.exe u trong WintNT thì bn có th chy nó nh mt dch v bng dòng lnh start C:\JDK1.4\bin\rmiregistry.exe Sau khi khi ng chng trình rmiregistry bng mt trong hai cách bn không thy phn hi gì c bi vì ây là chng trình chy di dng dch v (service). Mc nh rmiregistry lng nghe các kt ni trên cng 1009. Bn có th chnh ng khác cho nó. Ví d lnh sau s khi ng rmiregistry trên cng 2004 C:\Jdk1.4\bin\rmiregistry.exe 2004 Chú ý: Trong java 1 hostname không th là localhost, ngha là nu bn mun th nghim trên máy cc b thì bn phi truyn cho nó mt a ch IP chng hn nh 127.0.0.1 hoc tên ca máy ( bit tên ca máy ca mình bn vào Control Panel\Net Work chn th Indentification và bn s thy tên máy ca mình trong phn Computer Name) RMI s không làm vic chng nào bn cha cài h giao thc TCP/IP. u bn ang kim th trên máy cc b thì bn có thng ký vi trình rmiregistry dn gin nh sau: Naming.bind(“hello”,h); u bn ng ký mt i tng mi vi mt cái tên gi nhã c s dng cho mt i tng khác bn s nhn c mt ngoi l AlreadyBoundException.  ngn cn u này bn nên dùng phng thc Naming.rebind() thay cho phng thc Naming.bind() vì Naming.rebind() b sung mt cái tên mi nu nó cha có và thay th mt cái tên ã tn ti i mt i tng mi. Cho dù phng thc main() kt thúc thì i tng t xa bn to ra và ng ký cho nó t cái tên vn còn ó chng nào mà rmiregistry vn còn ang chy và bn không gi Trang 228 phng thc Naming.unbind() thì s vt này vn còn ó. Bi lý do này, khi bn phát trin ng dng ca mình thì bn cn phi tt rmiregistry và cho chy li nó mi khi bn biên dch i i tng t xa. n không nht thit phi khi ng rmiregistry nh mt tin trình ngoài. Nu bn bit ng ng dng ca mình là ng dng duy nht s dùng sng ký. Thì bn có th bt u nó  bên trong chng trình ca mình bng dòng lnh: LocateRegistry.createRegistry(Port); ây Port là s hiu cng. u này là tng ng vi vic chy rmiregistry Port t du nhc ca DOS-Prompt 4. Vit trình khách triu gi phng thc ca i tng cài t t xa Trình khách triu gi i tng phân tan RMI có th là mt trong các kiu ng dng sau: ng dng console ng dng có giao din  ho ng dng Servlet trang JSP … u duy nht bn phi làm trong chng trình khách là tra cu và ly v giao din  xa t trình ch. Tó tri vic triu gi phng thc t xa ging nh là triu i phng thc ca bt ki tng cc b nào khác. Sau ây là mu chng trình phía trình khách triu gi i tng phân tán RMI import java.rmi.*; import java.rmi.registry*; public Client { public static void main(String args[]) throws RemoteException { // ly v tham chiu i tng phân tán bng phng thc Naming.lookup() RemoteInterface r=(RemoteInterface)Naming.lookup(“[rmi:]//hostname[:port]/name”); // triu gi các phng thc ca i tng t xa } } Ví d 1-5: Sau ây là trình khách triu gi i tng HelloRMI Client.java import java.rmi.*; import java.rmi.registry*; public Client { public static void main(String args[]) throws RemoteException {// ly v tham chiu i tng phân tán bng phng thc Naming.lookup() HelloRMI r=( HelloRMI)Naming.lookup(“//localhost/hello”); // triu gi phng thc sayHello ca i tng t xa System.out.println(HelloRMI.sayHello()); } } Trang 229   truy tìm i tng  xa, chng trình máy khách gi phng thc Naming.lookup(); Phng thc này ch yêu cu i s là chui cho bit a ch ca máy ch và tên ng ký ca i tng. RemoteInterfacer=(RemoteInterface)Naming.lookup(“[rmi:]//hostname[:port]/name”); Mc nh phng thc Naming.lookup() tr v mt tham chiu Object nên bn cn phi ép kiu sang giao din t xa. Bn có th hình dung phng thc Naming.lookup() óng vai trò nh mt dch v tìm kim i tng trên máy ch, nó liên lc vi trình rmiregistry trên máy ch và yêu cu tr  tham chiu i tng cho bn s dng. Còn Naming.bind() óng vai trò nh dch v ng ký. Biên dch và chy trình khách Javac Client.java t c sn sàng, bn hãy chy chng trình khách nh sau: Java Client t qu thu c là li chào “Hello RMI” Hình 3 din t c ch gi phng thc t xa ca các i tng RMI mt cách tng quát: ng ký i tng vi trình rmiregistry bng cách gi phng thc Naming.bind() hoc Naming.rebind(). Máy khách mun gi phng thc ca i tng trên máy ch trc ht cn phi gi phng thc Naming.lookup()  truy tìm tham chiu n i tng  xa theo tên. ng ký s tr v tham chiu ca i tng  xa thông qua giao din t xa. a vào giao din t xa mà trình khách có th gi các phng thc ca i tng  xa. Khi mt phng thc c gi, li gi sc chuyn n lp trung gian _Stub. Lp trung gian này có nhim vóng gói các tham s và chuyn n lp trung gian _Skel trên trình ch. p trung gian trên máy ch s tip nhn các tham s gi n t trình khách và trc tip yêu cu i tng thc thi phng thc và chuyn kt qu (nu có) v cho trình khách. . Ví d 2: Vit lp Calculator, lp này có các phng thc add, less, mul, div dùng  thc hin các phép toán tng ng cng, tr, nhân và chia c 1: to ra giao din t xa - M mt trình son tho bt k gõ vào ni dung nh sau: M¸y kh¸ch M¸y chñ rmiregistry HelloRMIIm pl Naming.bin d Naming.rebi nd Client Naming.looku p 1 2 3 HelloRMI HelloRMIImpl_Stub HelloRMIImpl_Skel 4 5 6 Trang 230 //Calculator.java import java.rmi.*; public interface Calculator extends Remote { float add(float a, float b) throws RemoteException; float less(float a, float b) throws RemoteException; float mul(float a, float b) throws RemoteException; float div(float a, float b) throws RemoteException; } - Ghi li vào th mc C:\NetWork\Server - M ca s DOS-Prompt và gõ vào dòng lnh biên dch nh sau: c 2: Cài t giao din t xa - M trình son tho bt k gõ vào ni dung sau: // CalculatorImpl.java import java.rmi.RemoteException; public class CalculatorImpl implements Calculator { public float add(float a, float b) throws RemoteException { return a+b; } public float less(float a, float b) throws RemoteException { return a-b; } public float mul(float a, float b) throws RemoteException { return a*b; } public float div(float a, float b) throws RemoteException { return a/b; } } - Ghi li vi cái tên CalculatorImpl.java - M ca s DOS_Prompt và gõ vào dòng lnh sau  biên dch Trang 231 sau khi biên dch bn thu c tp tin CalcultatorImpl.class c 3 To ra các lp trung gian _Stub và _Skel n m ca s DOS_Prompt và gõ vào dòng lnh Sau khi thc hin xong lnh này bn s thu c hai lp trung gian là CalcultatorImpl_Stub và CalcultatorImpl_Skel trong cùng th mc C:\network\server c 4: ng ký i tng t xa vi trình rmiregistry - Bn m trình son tho bt k và gõ vào ni dung nh sau: // CalculatorSetup.java import java.rmi.server.*; import java.rmi.*; public class CalculatorSetup { public static void main(String[] args) throws Exception{ Calculator c=new CalculatorImpl(); UnicastRemoteObject.exportObject(c); Naming.rebind("rmi://localhost/Cal",c); } } - Ghi li vi cái tên CalculatorSetup.java trong vào th mc c:\network\server - M ca s DOS_Prompt gõ vào dòng lnh sau: [...]...c 5: Kh i ng d ch v ng ký tên rmiregistry n m c a s DOS-Prompt, chuy n vào th m c C:\NetWork\Server và gõ vào dòng l nh sau: Ch ng trình ang ký ã c kh i ng c 6: Kh i ng trình setup n m c a s DOS-Prompt khác gõ vào dòng l nh Chú ý: N u b n không chuy n vào th m c C:\NetWork\Server tr ang ký thì b n s nh n cm tl i Trang 232 c khi kh i ng d ch Ch ng 11: JAVA JSP (JAVA SERVLET) Trang 233 . lp trình  to ra các chng trình này c gi là lp trình phân tán. Có rt nhiu công ngh lp trình phân tán nh: DCOM, CORBA, RMI, EJB trong ó RMI. Trang 222 Chng 10: LP TRÌNH PHÂN TÁN VI JAVA RMI ( REMOTE METHOD INVOKE) Lp trình phân tán vi RMI là mt trong nhng vn  nóng bng

Ngày đăng: 29/09/2013, 09:20

Hình ảnh liên quan

Hình 1: Mô hình tri u gi các ph ng th ct xa - Lập trình phân tán với java RMI

Hình 1.

Mô hình tri u gi các ph ng th ct xa Xem tại trang 2 của tài liệu.
Trong hình trên bn có it ng C1 c cà it trên máy C. trình biê nd ch Java giúp ta t o ra hai l p trung gian C1_stub và C1_skel - Lập trình phân tán với java RMI

rong.

hình trên bn có it ng C1 c cà it trên máy C. trình biê nd ch Java giúp ta t o ra hai l p trung gian C1_stub và C1_skel Xem tại trang 3 của tài liệu.
B n có th hình dung ph ng th c Naming.lookup() óng vai trò nh td ch v tìm ki m i tng trên máy ch , nó liên l c v i trình rmiregistry trên máy ch  và yêu c u tr - Lập trình phân tán với java RMI

n.

có th hình dung ph ng th c Naming.lookup() óng vai trò nh td ch v tìm ki m i tng trên máy ch , nó liên l c v i trình rmiregistry trên máy ch và yêu c u tr Xem tại trang 8 của tài liệu.

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan