1

これは可能ですか?(Java 6 を想定)

私の要点を説明するために考案された/単純化された例は次のとおりです。

  • 明確に定義された、決して変更されない RMI インターフェイス (単一の JAR ファイル、テンプレート パラメーターなし) があります。
  • ホスト X で実行されている RMIRegistry。
  • ホスト Y から (ホスト X 上の RMIRegistry) に registry.rebind() する RMI サービス。と
  • ホスト Z から RMI 呼び出しを実行する RMI クライアント

可能であれば、RMI サービス (ホスト Y のプロセス) でプロパティ "java.rmi.server.codebase" を指定するにはどうすればよいですか?

ホスト A と B が同じマシンである場合、この構成は「java.rmi.server.codebase」が「file:///C:/rmiCodebase/myCommonInterface.jar」のときに機能します。

ホスト A と B が別々のマシンにある場合、再バインド時に次の例外が発生します (ホスト Y に同じ「java.rmi.server.codebase」が設定されています)。

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
java.lang.ClassNotFoundException: 

ホスト A と B が別々のマシンにあり、インターフェース JAR を Web サーバー経由で使用できるようにする場合 (「java.rmi.server.codebase」は「http://Y/rmiCodebase/myCommonInterface.jar」または「 http://Z/rmiCodebase/myCommonInterface.jar")、再バインド時にこのわずかに異なるエラーが発生します。

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
java.rmi.AccessException: Registry.Registry.rebind disallowed; origin /10.0.190.25 (host Y) is non-local host

私は少し混乱しています - すべての RMI サービスが RMIRegistry と同じ物理ホスト上で実行されなければならない場合、非常に制約があるようです (私が成功したのはこれだけです)

結局のところ、私はマシン Z がマシン Y で実行されているサービスに対して RMI 呼び出しを行えるようにしたいだけです。マシン Y と Z の両方で実行されているプロセスに myCommonInterface.jar を提供しています。マシン X が共通の (リモート) インターフェースを使って何かをしなければならないようにしたい!

次のリンクは役に立ちますが、この質問への回答には役立ちません: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html

4

3 に答える 3

0

正確には具体的な答えではありませんが、制限を示唆しています。

http://download.oracle.com/javase/6/docs/api/java/rmi/registry/Registry.html

レジストリの実装では、そのメソッドの一部またはすべてへのアクセスを制限することを選択できます(たとえば、レジ​​ストリのバインディングを変更するメソッドは、ローカルホストから発信された呼び出しに制限される場合があります)。Registryメソッドが特定の呼び出しに対するアクセスを拒否することを選択した場合、その実装はAccessExceptionをスローする可能性があります。これは、リモートクライアントによってキャッチされると(RemoteExceptionを拡張するため)ServerExceptionにラップされます。

于 2010-10-28T10:48:05.860 に答える
0

これは可能ですか?

いいえ、できません。Registry.bind()/rebind()/unbind() および Naming.bind()/rebind()/unbind() の Javadoc を参照してください。

ただし、RMI レジストリの代わりに LDAP サービスを使用できます。

マシン Z が、マシン Y で実行されているサービスに対して RMI 呼び出しを行えるようにしたいだけです

では、なぜ質問なのですか?マシン Z がマシン Y でレジストリを検索する際の問題は何ですか?

于 2010-10-28T06:21:50.857 に答える
0

私の使用例は非常に単純でした (基本的に、RMI を分散システムに命令する方法として使用しました) が、レジストリーを一緒に使用することを避けることができました。

Map-Reduce-ミニフレームワークに使用することになった回避策を次に示します。

前:

In client:    
    remoteMaster = (Master) remoteRegistry.lookup("master");
    // Add self to remote registry (BAD!)
    Worker stub = (Worker) UnicastRemoteObject.exportObject(this, 15213);
    remoteMaster.bind("workerName", stub);

後:

(この回避策では、レジストリを使用せずに RemoteObject を手動で保存します)

In Master:
     List<Worker> workers = new List<Worker>();

     public void registerWorker(String name, Worker stub) throws RemoteException {
          worker.add(stub);
      }

リモート インスタンスを保存したら、他のオブジェクトと同様に、それを渡したり呼び出したりできます。

このアプローチは、レジストリを一時的な保管場所としてのみ使用している場合 (私はそうでした) にのみ有用であることに注意してください。これは、レジストリに追加せずにローカルに保持することで「アクセス制限」を回避しているためです。

私の(少しハッキーな)ソリューションを文書化するだけで、コメントを歓迎します。

于 2013-05-03T01:27:46.730 に答える