1 / 65

Java Distributed Objects 3

Java Distributed Objects 3. Masayuki Iwai tailor@ht.sfc.keio.ac.jp. Table of contents. 第 1 回 10 月 11 日木曜日 5 限 Distibuted objects の目指す世界 Rmi 以前 tutorial Rmi tutorial 第 2 回 10 月 19 日金曜日 6 限 Rmi Advanced tutorial Rmi tutorial custom socket package Activatable 第 3 回 10 月 17 日木曜日 5 限

Télécharger la présentation

Java Distributed Objects 3

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 Distributed Objects3 Masayuki Iwai tailor@ht.sfc.keio.ac.jp

  2. Table of contents • 第1回10月11日木曜日5限 • Distibuted objectsの目指す世界 • Rmi 以前 tutorial • Rmi tutorial • 第2回10月19日金曜日6限 • Rmi Advanced tutorial • Rmi tutorial • custom socket package • Activatable • 第3回10月17日木曜日5限 • Jini programming • Java Space programming • Distributed Objectsの世界

  3. Distibuted objectsの目指す世界 • タスクの依頼 • 自由な連携 take write take read write

  4. Local Method Invocation LocalMainClass LocalRuntime 192.168.0.1 • Local Method Invocation LocalClass localClass=new LocalClass(); outputObj=localClass.method(inputObj); • inputObjはprimitive型でない限りcall by referenceとして渡される。

  5. RMI:Remote Method Invocation RemoteClass LocalMainClass method LocalRuntime RemoteRuntime 192.168.0.1 192.168.0.2 Remote Classのmethodを Callbyreferenceで呼びたいのがRMI

  6. RMI:Bの側にCのクラスファイルがない場合RMI:Bの側にCのクラスファイルがない場合 • Interfaceを利用したCastだけではだめ • BはCを保持しておく必要がないが最終的にはCの情報が必要->NetworkClassLoader Cの情報をダウンロード C NetworkClassServer NetworkClassLoader interface C C C’ A serializable B C 0100101001010 ObjectOutputStream VM_A VM_B

  7. RMI:すこし立ち止まって • クラスサーバは果たしてLocalRuntimeにある必要はあるのか? Cの情報をダウンロード C NetworkClassServer NetworkClassServer interface C C C’ A serializable B C 0100101001010 ObjectOutputStream VM_A VM_B

  8. RMI:Marshalled Object • MarshalledObject=serialized object+そのロード元 (可能な場合) となるコードベース URL • BはCを知る必要がない:webserverは何処にあってもよい:動作はVM_B上 C http/get websrver Cクラスの解決情報 C C C C C’ A serializable B ObjectOutputStream VM_A VM_B

  9. RMI: MarshalledObjectの実装 public final class MarshalledObject implements Serializable { /** * @serial Bytes of serialized representation. If <code>objBytes</code> is * <code>null</code> then the object marshalled was a <code>null</code> * reference. */ private byte[] objBytes = null; /** * @serial Bytes of location annotations, which are ignored by * <code>equals</code>. If <code>locBytes</code> is null, there were no * non-<code>null</code> annotations during marshalling. */ private byte[] locBytes = null; /** * @serial Stored hash code of contained object. * * @see #hashCode */ }

  10. RMI:Object I/O Streamの2つの問題 • オブジェクト単位 public class Account implements Serializable{ public void setMoney(){….} public Money getMony(){….} public void addMony(){….} public void subMony(){….} } =================書き出す側 VM_A=================== Socket s = ss.accept(); ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); Account acc= Bank.getAccount(me); oos.writeObject(acc); s.close(); =================読み出す側 VM_B=================== ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); Account acc= (Account) (ois.readObject()); acc.addMony(1000); AccountクラスってRemoteに最新のものあるの? これって変更されるのRemoteのAccountクラスだよね

  11. RMI: • Socket/ObjectStreamレベルのことはStabが行う。 • Stabクラスはrmic –v1.2 ServerClassのコマンドで生成 • 実はMarshalledObjectを利用してRMIは実装されている。 • コードベースのためWebserverが必要 • スタブオブジェクトが必要:動作はVM_A上 C クラスCは必要ない WEBSERVER インタフェースC’ UnicastRemoteObject C C C’ A C_stub C_stub B RMI VM_A VM_B

  12. RMI:SocketProgrammingではない。 =================サーバ側 VM_A=================== public class AccountImpleextends UnicastRemoteObject implements IAccount{ } AccountImple acc= Bank.getAccountImple (me); Naming.rebind(“registryhostname/Account_Iwai”,acc); 起動方法 >>java MainClass java.rmi.server.codebase=http://codebasehost/accout.jar =================クライアンド側 VM_B=================== String location = "rmi://registryhostname/Account_Iwai" ; acc=(IAccount)Naming.lookup(location); acc.addMony(1000); Socketプログラミングあらたな問題

  13. Remote インタフェースの実装 publicinterface MoneyRemote extendsRemote { publicvoid increment() throws RemoteException; publicvoid printMoney() throws RemoteException; publicint getMoney() throws RemoteException; }

  14. MoneyLocalClient publicclass MoneyLocalClient { publicstaticvoid main(String argv[]){ MoneyRemote remotemoney; //インタフェースのみの宣言である点に注意 //codebaseがなければキャスト例外を起すはず try { String location = "rmi://localhost/MoneyServer" ; remotemoney=(MoneyRemote)Naming.lookup(location); System.out.println("Remote obj: " + remotemoney ); System.out.println("money local client:"+remotemoney.getMoney()); remotemoney.increment(); //remote呼び出し remotemoney.printMoney();//remote呼び出し } catch (Exception e) { System.out.println("err: " + e); e.printStackTrace(); } } }

  15. MoneyRemoteImpl publicclass MoneyRemoteImpl extendsUnicastRemoteObjectimplementsMoneyRemote { //ここのpublic必須 <- なぜか理由を考えてみてね。 publicMoneyRemoteImpl() throws RemoteException { super(); } int money = 0; publicvoid increment() throws RemoteException { money++; } publicvoid printMoney() throws RemoteException { System.out.println("Remote Money is:" + money); } publicint getMoney() throws RemoteException { return money; } }

  16. RemoteMain publicclass RemoteMain { publicstaticvoid main(String argv[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { MoneyRemoteImpl money = new MoneyRemoteImpl(); money.increment(); Naming.rebind("rmi://localhost/MoneyServer", money); //実は名前は何でもよい。 System.out.println("MoneyServer bound in registry"); money.printMoney(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } }

  17. コマンド • Stubの生成 • rmic -v1.2 jp.ac.sfc.keio.sfc.tailor.rmi.test.remote.MoneyRemoteImpl • Stubはクライアントにコピーが必要 • Codebaseのためのjar化 • jar cvf 1rmiMoneyRemoteImpl.jar jp\ac\sfc\keio\sfc\tailor\rmi\test\ • Rmiregistryの起動 • jar cvf 1rmiMoneyRemoteImpl.jar jp\ac\sfc\keio\sfc\tailor\rmi\test\ • サーバの起動 • java -Djava.rmi.server.codebase=http://www.ht.sfc.keio.ac.jp/~tailor/rg/1rmiMoneyRemoteImpl.jar -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.test.remote.RemoteMain • クライアントの起動 • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.test.local.MoneyLocalClient

  18. わざとcodebaseでエラーを起す。 • java -Djava.rmi.server.codebase=http://www.ht.sfc.keio.ac.jp/~tailor/rgX/ -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.test.remote.RemoteMain • Rmiregistryのcodebaseに開発コードがないことを確認

  19. rmiregistryの正体 package jp.ac.sfc.keio.sfc.tailor.rmi.registry; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import jp.ac.sfc.keio.sfc.tailor.rmi.test.remote.MoneyRemoteImpl; public class RegistryMain { /** * rmiregistryが何をしているか知るプログラム */ public static void main(String[] args) { MoneyRemoteImpl money; try { money = new MoneyRemoteImpl(); money.increment(); Registry reg = LocateRegistry.createRegistry(1099); reg.bind("MoneyServer", money); } catch (RemoteException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } catch (AlreadyBoundException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } } }

  20. 万能rmiサーバを作成する。 public interface Compute extends Remote { Object executeTask(Task t) throws RemoteException; }

  21. Task import java.io.Serializable; public interface Task extends Serializable { Object execute(); }

  22. TaskMillis public class TaskMillis implements Task { public Object execute() { //executeはObjectを返しますので、プリミティブ・タイプのlongではなく、そのラッパーのLongが返り値 return new Long(System.currentTimeMillis()); } }

  23. ComputeEngine publicclass ComputeEngine extends UnicastRemoteObject implements Compute { publicComputeEngine() throws RemoteException { super(); } public Object executeTask(Task t) { returnt.execute(); } publicstaticvoid main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { String name = "rmi://localhost/Compute"; Compute engine = new ComputeEngine(); Naming.rebind(name, engine); System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } }

  24. ComputeClientMillis public class ComputeClientMillis { static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { String name = "rmi://localhost/Compute"; Compute comp = (Compute) Naming.lookup(name); // ここからは、処理に応じて変わる。これは、サーバ時計を表示する例。 Long millis = (Long) (comp.executeTask(new TaskMillis())); System.out.println("Remote Date : " + new Date(millis.longValue())); System.out.println("Local Date : " + new Date()); } catch (Exception e) { System.err.println("ComputePi exception: " + e.getMessage()); e.printStackTrace(); } } }

  25. 実行コマンド • rmic -v1.2 jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeEngine • jar cvf 2rmiCompute.jar jp\ac\sfc\keio\sfc\tailor\rmi\compute\ • start rmiregistry • java -Djava.rmi.server.codebase=http://www.ht.sfc.keio.ac.jp/~tailor/rg/2rmiCompute.jar -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeEngine • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeClientMillis

  26. ComputeClientPrime ublic class ComputeClientPrime { public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { String name = "rmi://localhost/Compute"; Compute comp = (Compute) Naming.lookup(name); TaskPrime taskprime =new TaskPrime(); //taskprime.setPrimenum("69143"); taskprime.setPrimenum(args[0]); // ここからは、処理に応じて変わる。これは、サーバ時計を表示する例。 Boolean ansprime = (Boolean) (comp.executeTask(taskprime)); System.out.println("prime : " + ansprime.booleanValue()); } catch (Exception e) { System.err.println("ComputePi exception: " + e.getMessage()); e.printStackTrace(); } } }

  27. TaskPrime package jp.ac.sfc.keio.sfc.tailor.rmi.compute; import java.math.BigInteger; publicclass TaskPrime implements Task { String primenum="69127"; public Object execute() { returnnew Boolean(getPrime(primenum)); } privateboolean getPrime(String prime) { BigInteger n = new BigInteger(prime); if (n.compareTo(BigInteger.ZERO) <= 0) { System.out.println("自然数を入力して下さい"); System.exit(1); } System.out.println("入力された数は " + n.toString()); if (n.compareTo(BigInteger.ONE) == 0) { System.out.println("素数ではありません"); returnfalse; } elseif (n.compareTo(BigInteger.valueOf(2)) == 0) { System.out.println("素数です"); returnfalse; } BigInteger r = n.mod(BigInteger.valueOf(2)); if (r.compareTo(BigInteger.ZERO) == 0) { System.out.println("除算可能な数は 2"); System.out.println("素数ではありません"); returnfalse; } BigInteger s = this.bigIntegerSqrt(n); for (BigInteger d = BigInteger.valueOf(3); d.compareTo(s) <= 0; d = d.add(BigInteger.valueOf(2))) { r = n.mod(d); if (r.compareTo(BigInteger.ZERO) == 0) { System.out.println("除算可能な数は " + d.toString()); System.out.println("素数ではありません"); returnfalse; } } System.out.println("素数です"); returntrue; } publicstatic BigInteger bigIntegerSqrt(BigInteger x){ BigInteger b1 = new BigInteger(x.toString()), b2 = (b1.pow(2).add(x)).shiftRight(1).divide(b1); while(b2.compareTo(b1) < 0){ b1 = new BigInteger(b2.toString()); b2 = (b1.pow(2).add(x)).shiftRight(1).divide(b1); } return b1; } public String getPrimenum() { return primenum; } publicvoid setPrimenum(String primenum) { this.primenum = primenum; } }

  28. 素数計算をさせる • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeClientPrime 69143 • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeClientPrime 69149 • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeClientPrime 69151 • java -Djava.security.policy=securitypolicy.txt jp.ac.sfc.keio.sfc.tailor.rmi.compute.ComputeClientPrime 69157

  29. Mission • AttendanceTaskクラスを作成しなさい。 • execute()メッソッドに • サーバの私に • 学籍番号,ログイン名,名前 • をprintlnする機能を実装 • 岩井の立てているcompクラスに対して • 通信を行え。 • rmi://岩井のマシンのIPアドレス/Compute

  30. Activation

  31. RMI準備

  32. Jini: Rmiregistryのホスト名の発見 • SocketProgrammingは主に相手のホスト名/IPをあらかじめ知っている。 • RMIはrmiregistryをおいている。 • Rmiregistryのホスト名と • そのため通信相手の登録名を知っていればいい • Ex “Accoount_Iwai” • どうやってRmiregistryのホスト名をどうやって見つけるのか?

  33. Jiniのレイヤ構造 Jini RMI/HTTP Socket TCP/UDP/IP

  34. Jiniの特徴で本日話すこと • Discovery • Lease

  35. Jini:Doscovery and Join ①自分のIPをネットワークにマルチキャストで流す ②感知 ④サービス情報の登録(ジョイン) ③感知確認のUnicast応答 (ディスカバリ) • サービスが登録される時 C LookupService サービス サービス C B A

  36. Jini:Service Lookup ⑤要求がある事を通知(activation?) ④サービス情報検索 ⑥利用プログラムの入手 ⑦サービス間と直接やり取り(RMI) LookupServiceの発見(前ページ①~③)までは一緒 C LookupService A B サービス サービス C C

  37. サーバ側 Cクラス public class AccountImle extends UnicastRemoteObject implements Account{ public int getMony() throws  RemoteException { return mony; } }

  38. サーバ側 Aクラス public class MainClass implements DiscoveryListener, Serializable { lookupDiscovery = new LookupDiscovery(“Bank”); lookupDiscovery.addDiscoveryListener(this); public void discovered(DiscoveryEvent evnt) { ServiceRegistrar[] regs = evnt.getRegistrars(); AccountImple acc = new AccountImple(); ServiceItem item = new ServiceItem(null, acc , attrs ); regs[i].register(item, Lease.FOREVER); //登録 } }

  39. クライアント側 Bクラス ServiceTemplate tmpl = new ServiceTemplate(null, classes , null); acc = (Account)(regs[i].lookup(tmpl)); acc. getMony(); //テンプレートにそうものが見つからなかった //場合は通知依頼を登録できる。 reg[i].notify(template, transitions, tellme, mo, Lease.ANY); 何の通知を依頼できるか? 新規登録、ステータス変化、消去の3種類

  40. Jini:Lease • Lookupに登録されたObjectはたまっていく一方なのか? →LookupServiceがわの都合で定期的に強制削除されます。 LookupService Lease expire Lease renew 障害 サービス サービス そこでずっと登録してほしければ サービス側から常にLease延長要求をだす。

  41. JavaSpaces: • Spaceプログラミングモデル • たまっていくオブジェクトの概念を使った分散システム構築方法 • Linda • author = "D. Gelernter", • title = "{Generative Communication in Linda}", • note = " ACM Transactions on Programming • Languages and Systems, 7(1):80--112, 1985.", • year = "1985" • T-Spaces(ibm)

  42. Java Spaces 分散された仮想オブジェクト置き場 内部的にはJiniのLease機構 take write take read write

  43. Java Spaces • write(obj) • read() • readIfExist() • take() • taleIfExist() • notify() • snapshot() • 問題点 • ObjectHeavyEaterクラスを作成されたら • 広域ネットワークでつかえるか?

  44. Napster:ログインプロセス どうやって広域ネットワークで相手と通信するか? ログインサーバ群 リダイレクトサーバ群 ③ログインサーバの指定 ④ID、PASS ②ログインサーバの要求 ⑤自らのサーバント情報の登録 サーバンド ①自らのサーバント情報の構築

  45. Napster:検索プロセス ログインサーバ ①検索要求 ③詳細要求 ④サーバンドのIP、Portなど サーバンド ②検索結果 サーバント ⑤自らのサーバントコネクト要求 ⑥直接ダウンロード

  46. Napster:ダウンロードプロセス ログインサーバ ③逆転送要求+相手サーバントIPアドレス ②逆転送要求+自分のIPアドレス サーバンド サーバント ①自らのサーバントコネクト要求 ④サーバントへのアップロード開始接続要求

  47. Gnutella:GnutellaNetへの参加 WEBやキャッシュからneighborを見つける そのNeighborのさらにneighborをおくってもらう。 自分の子供が7人になるまで安定させる。

  48. Gnutella:用語 • Ping • ネットワーク上でホストを探す。ピングのデスクリプターを受け取ったサーバントは1つ以上のPongのデスクリプターを返す。 • Pong • Pingへの返答。接続されたサーバントのアドレス、及び、ネットワークへと利用可能なデータの総量 とみなされる情報を含む。  • Push • ファイアウォール化されたサーバントが、ネットワークへのファイルベースのデータを提供することを可能にするメカニズム

  49. Gnutella:用語 • Query • 分散型ネットワークを検索するために必要となる主要なメカニズム。もしローカルのデータの中に検索にふさわしいものが見つかったら、クエリーのデスクリプターを受け取ったサーバントはクエリーヒットを返信。 • QueryHit • クエリーの返信。一致したクエリーのマッチングを行うデータを手\に入れるために、このデスクリプターは十分な情報を持つ受け取り人を提供

More Related