java distributed objects 3
Post on 31-Dec-2015
48 Views
Preview:
DESCRIPTION
TRANSCRIPT
©Msayuki Iwai
Table of contentsTable 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 の世界
©Msayuki Iwai
Distibuted objectsDistibuted objects の目指す世界の目指す世界• タスクの依頼• 自由な連携 take
readwrite
take
write
©Msayuki Iwai
Local Method InvocationLocal Method Invocation
• Local Method InvocationLocalClass localClass=new LocalClass();
outputObj=localClass.method(inputObj);
– inputObj は primitive 型でない限りcall by reference として渡される。
LocalRuntime
LocalMainClass
192.168.0.1
©Msayuki Iwai
RMIRMI :: Remote Method InvocationRemote Method Invocation
LocalRuntime
LocalMainClass
192.168.0.1
RemoteClass
RemoteRuntime
method
192.168.0.2
Remote Class の method をCallbyreference で呼びたいのが RMI
©Msayuki Iwai
RMI:RMI: BB の側にの側に CC のクラスファイルがない場合のクラスファイルがない場合
• Interface を利用した Cast だけではだめ
• B は C を保持しておく必要がないが最終的には C の情報が必要 ->NetworkClassLoader
A B
ObjectOutputStream
C Cserializable C’
C の情報をダウンロード
interface
0100101001010
NetworkClassServer NetworkClassLoaderC
C
VM_A VM_B
©Msayuki Iwai
RMI:RMI: すこし立ち止まってすこし立ち止まって• クラスサーバは果たして
LocalRuntime にある必要はあるのか?
A B
ObjectOutputStream
C Cserializable C’
C の情報をダウンロード
interface
0100101001010
NetworkClassServer NetworkClassServerC
C
VM_A VM_B
©Msayuki Iwai
RMI:Marshalled ObjectRMI:Marshalled Object
• MarshalledObject=serialized object+ そのロード元 ( 可能な場合 ) となるコードベース URL
• B は C を知る必要がない :webserver は何処にあってもよい:動作は VM_B 上
A BObjectOutputStream
C serializable C’
C クラスの解決情報C
CC
websrver
Chttp/get
VM_A VM_B
©Msayuki Iwai
RMI: MarshalledObjectRMI: 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 */}
©Msayuki Iwai
RMI:Object I/O StreamRMI:Object I/O Stream のの 22 つの問題つの問題– オブジェクト単位 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);
これって変更されるのRemoteの Account クラスだよねAccount クラスってRemoteに最新のものあるの?
©Msayuki Iwai
RMIRMI ::• Socket/ObjectStream レベルのことは Stab が行う。• Stab クラスは rmic –v1.2 ServerClass のコマンド
で生成– 実は MarshalledObject を利用してRMIは実装されている。– コードベースのため Webserver が必要– スタブオブジェクトが必要:動作は VM_A 上
VM_A VM_B
A B
RMI
CUnicastRemoteObject
C’C_stub C_stub
WEBSERVER
C クラスCは必要ない
インタフェースC’C
©Msayuki Iwai
RMI:SocketProgrammingRMI:SocketProgramming ではない。ではない。
================= サーバ側 VM_A===================public class AccountImple extends 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 プログラミングあらたな問題
©Msayuki Iwai
Remote Remote インタフェースの実装インタフェースの実装
public interface MoneyRemote extends Remote {
public void increment() throws RemoteException;
public void printMoney() throws RemoteException;
public int getMoney() throws RemoteException;
}
©Msayuki Iwai
MoneyLocalClientMoneyLocalClientpublic class MoneyLocalClient {
public static void 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(); remotemoney.increment(); //remote//remote 呼び出し呼び出し remotemoney.printMoney();remotemoney.printMoney(); //remote//remote 呼び出し呼び出し } catch (Exception e) { System.out.println("err: " + e); e.printStackTrace(); } }
}
©Msayuki Iwai
MoneyRemoteImplMoneyRemoteImplpublic class MoneyRemoteImpl extends UnicastRemoteObjectUnicastRemoteObject
implements MoneyRemote {
// ここの public 必須 <- なぜか理由を考えてみてね。public MoneyRemoteImpl() throws RemoteException {super();}
int money = 0;
public void increment() throws RemoteException {money++;
}
public void printMoney() throws RemoteException {System.out.println("Remote Money is:" + money);
}
public int getMoney() throws RemoteException {return money;
}
}
©Msayuki Iwai
RemoteMainRemoteMainpublic class RemoteMain {
public static void 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();}}
}
©Msayuki Iwai
コマンドコマンド• 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
©Msayuki Iwai
わざとわざと codebasecodebase でエラーを起す。でエラーを起す。• 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 に開発コードがないことを確認
©Msayuki Iwai
rmiregistryrmiregistry の正体の正体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();
}
}
}
©Msayuki Iwai
万能万能 rmirmi サーバを作成する。サーバを作成する。
public interface Compute extends Remote {
Object executeTask(Task t) throws RemoteException;
}
©Msayuki Iwai
TaskTask
import java.io.Serializable;
public interface Task extends Serializable {
Object execute();}
©Msayuki Iwai
TaskMillisTaskMillis
public class TaskMillis implements Task {
public Object execute() {
//execute は Object を返しますので、プリミティブ・タイプの long ではなく、そのラッパーのLong が返り値
return new Long(System.currentTimeMillis());}
}
©Msayuki Iwai
ComputeEngineComputeEnginepublic class ComputeEngine extends UnicastRemoteObject implements Compute
{ public ComputeEngine() throws RemoteException { super(); }
public Object executeTask(Task t) { return t.execute();t.execute(); }
public static void 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(); } }}
©Msayuki Iwai
ComputeClientMillisComputeClientMillispublic 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();
}
}
}
©Msayuki Iwai
実行コマンド実行コマンド• 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
©Msayuki Iwai
ComputeClientPrimeComputeClientPrimeublic 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();
}
}
}
©Msayuki Iwai
TaskPrimeTaskPrimepackage jp.ac.sfc.keio.sfc.tailor.rmi.compute;
import java.math.BigInteger;
public class TaskPrime implements Task {
String primenum="69127";
public Object execute() {return new Boolean(getPrime(primenum));}
private boolean 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(" 素数ではありません "); return false; } else if (n.compareTo(BigInteger.valueOf(2)) == 0) { System.out.println(" 素数です "); return false; }
BigInteger r = n.mod(BigInteger.valueOf(2)); if (r.compareTo(BigInteger.ZERO) == 0) { System.out.println(" 除算可能な数は 2"); System.out.println(" 素数ではありません "); return false; } 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(" 素数ではありません "); return false; } } System.out.println(" 素数です ");
return true;}
public static 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;}
public void setPrimenum(String primenum) {this.primenum = primenum;}
}
©Msayuki Iwai
素数計算をさせる素数計算をさせる• 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
©Msayuki Iwai
MissionMission• AttendanceTask クラスを作成しなさい。
• execute() メッソッドに• サーバの私に• 学籍番号 , ログイン名 , 名前• を println する機能を実装
• 岩井の立てている comp クラスに対して• 通信を行え。
• rmi:// 岩井のマシンの IP アドレス /Compute
©Msayuki Iwai
Jini: RmiregistryJini: Rmiregistry のホスト名の発見のホスト名の発見• SocketProgramming は主に相手のホ
スト名 /IP をあらかじめ知っている。• RMI は rmiregistry をおいている。
– Rmiregistry のホスト名と– そのため通信相手の登録名を知っていればい
い– Ex “Accoount_Iwai”
• どうやって Rmiregistry のホスト名をどうやって見つけるのか?
©Msayuki Iwai
Jini:Doscovery and JoinJini:Doscovery and Join
• サービスが登録される時
LookupService
サービス サービス
① 自分のIPをネットワークにマルチキャストで流す
②感知
③感知確認のUnicast 応答 (ディスカバリ)
④サービス情報の登録(ジョイン)
AB
C
C
©Msayuki Iwai
Jini:Service LookupJini:Service Lookup
LookupService
サービス サービス
⑦サービス間と直接やり取り(RMI)
⑥利用プログラムの入手
④サービス情報検索
⑤要求がある事を通知( activation?)
AB
C C
C
LookupService の発見(前ページ①~③)までは一緒
©Msayuki Iwai
サーバ側サーバ側 CC クラスクラス
public class AccountImle extends UnicastRemoteObjectimplements Account {public int getMony() throws
RemoteException {return mony;
}}
©Msayuki Iwai
サーバ側サーバ側 AA クラスクラス
public class MainClassimplements 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); // 登録
}}
©Msayuki Iwai
クライアント側 クライアント側 BB クラスクラス
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種類
©Msayuki Iwai
Jini:LeaseJini:Lease• Lookupに登録されたObject
はたまっていく一方なのか? → LookupService がわの都合で定期的に強制削除されます。
LookupService
そこでずっと登録してほしければサービス側から常にLease延長要求をだす。
サービス
Lease renew
サービス障害
Lease expire
©Msayuki Iwai
JavaSpacesJavaSpaces ::
• 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)
©Msayuki Iwai
Java SpacesJava Spaces• write(obj)• read()• readIfExist()• take()• taleIfExist()• notify()• snapshot()
• 問題点– ObjectHeavyEater クラスを作成されたら– 広域ネットワークでつかえるか?
©Msayuki Iwai
Napster:ログインプロセスNapster:ログインプロセス• どうやって広域ネットワークで相手と通信するか?
リダイレクトサーバ群 ログインサーバ群
サーバンド
②ログインサーバの要求
① 自らのサーバント情報の構築
③ログインサーバの指定
④ID、PASS
⑤自らのサーバント情報の登録
©Msayuki Iwai
NapsterNapster :検索プロセス:検索プロセス
ログインサーバ
サーバンド
②検索結果
①検索要求
③詳細要求
④サーバンドのIP、Portなど
⑤自らのサーバントコネクト要求
サーバント⑥直接ダウンロード
©Msayuki Iwai
NapsterNapster :ダウンロードプロセス:ダウンロードプロセス
ログインサーバ
サーバンド
②逆転送要求+自分のIPアドレス
① 自らのサーバントコネクト要求
サーバント
③逆転送要求+相手サーバントIPアドレ
ス
④サーバントへのアップロード開始接続要求
©Msayuki Iwai
GnutellaGnutella :GnutellaNetへの参:GnutellaNetへの参加加WEBやキャッシュから neighbor を見つけるその Neighbor のさらに neighbor をおくってもらう。自分の子供が 7人になるまで安定させる。
©Msayuki Iwai
GnutellaGnutella :用語:用語• Ping
– ネットワーク上でホストを探す。ピングのデスクリプターを受け取ったサーバントは1つ以上の Pong のデスクリプターを返す。
• Pong– Pingへの返答。接続されたサーバントのア
ドレス、及び、ネットワークへと利用可能なデータの総量 とみなされる情報を含む。
• Push – ファイアウォール化されたサーバントが、
ネットワークへのファイルベースのデータを提供することを可能にするメカニズム
©Msayuki Iwai
Gnutella:Gnutella: 用語用語• Query
– 分散型ネットワークを検索するために必要となる主要なメカニズム。もしローカルのデータの中に検索にふさわしいものが見つかったら、クエリーのデスクリプターを受け取ったサーバントはクエリーヒットを返信。
• QueryHit – クエリーの返信。一致したクエリーのマッチ
ングを行うデータを手 \に入れるために、このデスクリプターは十分な情報を持つ受け取り人を提供
©Msayuki Iwai
Gnutella:Gnutella: The Grid Self-The Grid Self-Organizing ProtocolsOrganizing Protocols
• 各サーバントに論理的に東西南北のコネクションの概念を持たせる。
• 自分を基点とする場合は東西南北も4方向へ伝達
• 北から受けたメッセージは東西南へ• 南から受けたメッセージは東西北へ• ….
©Msayuki Iwai
Gnutella:Gnutella: The Grid Self-The Grid Self-Organizing ProtocolsOrganizing Protocols
格子の欠損に弱い
©Msayuki Iwai
JXTA:rendezvous-peerJXTA:rendezvous-peer
• 待ち合わせ場所を使った間接通信
Peer1
rendezvous-peerrendezvous-peer2
Peer3
Peer4
Peer5
Peer6
rendezvous-peerrendezvous-peer7
TTL3 TTL2
TTL1
©Msayuki Iwai
JXTA:rendezvous-peerJXTA:rendezvous-peer
Peer1
rendezvous-peerrendezvous-peer2
Peer3
Peer4
Peer5
Peer6
rendezvous-peerrendezvous-peer7
rendezvous-peerrendezvous-peer は徐々に賢くなる。は徐々に賢くなる。
下流に転送もするおいら Peer5 とP
eer6のこと知っているよ。
©Msayuki Iwai
JXTA:router-PeerJXTA:router-Peer• NAT の中にいるPeerを外側にPeerと同等な世界に引き上げる仲立ち• 内と外の電送手段の差異を吸収
Peer1
Router Peer
Peer2
Message1
Router-peer に対する定期的問い合わせで見つかれば peer1は Peer2 からのMessageをみれる。
©Msayuki Iwai
JXTA:優れた抽象化!JXTA:優れた抽象化!
• Peer Discovery Protocol • ピアの発見• Peer Resolver Protocol
クエリの送受信• Peer Information Protocol • ピアの状態• Peer Membership Protocol • メンバーシップグループ の管理• Pipe Binding Protocol
ピア間のパイプ構築• Peer Endpoint Protocol
ピア間の経路の情報
top related