26

私の質問:ローカルで実行されている 2 つ以上の JVM インスタンス間で通信するには、どのような方法をとればよいですか?

問題の説明:
特定のタスクを互いに完全に分離するために別個の JVM インスタンスを必要とするプロジェクト用のシステムを開発しています。

実行中、「親」JVM は、実行を期待する「子」JVM を作成し、結果を (比較的単純な POJO クラスまたは構造化された XML データの形式で) 返します。これらの結果は、SysErr/SysOut/SysIn パイプを使用して転送されるべきではありません。これは、子が実行の一部としてこれらを既に使用している可能性があるためです。

子 JVM が一定時間内に結果を返さない場合、親 JVM は子プロセスに信号を送って処理を停止するか、子プロセスを強制終了できるようにする必要があります。それ以外の場合、子 JVM はタスクの完了時に正常に終了する必要があります。

これまでの調査:
役立つ可能性のある技術がいくつかあることは承知しています。

  • Java の RMI ライブラリを使用する
  • ソケットを使用してオブジェクトを転送する
  • Cajo、Hessian などの配布ライブラリの使用

...しかし、これらのオプションのいずれかまたは他のオプションを追求する前に、他の人がどのようなアプローチを検討するかを聞くことに興味があります.

これに関する助けやアドバイスをありがとう!

編集:
転送するデータの量 -比較的小さいですが、ほとんどの場合、子の実行結果を表す文字列を含むほんの一握りの POJO になります。大量の情報に対して非効率的な解決策がある場合、これが私のシステムで問題になる可能性はほとんどありません。転送される金額はかなり静的である必要があるため、これはスケーラブルである必要 はありません。

この場合、転送のレイテンシーは重大な問題ではありませんが、結果の「ポーリング」が必要な場合は、大きなオーバーヘッドなしでかなり頻繁に行うことができるため、後でこれに加えて応答性の高い GUI を維持できます (例: プログレス バー)

4

11 に答える 11

6

あなたの質問に対する直接の回答ではなく、代替案の提案です。OSGIを検討しましたか?

同じ jvm 内で、Java プロジェクトを互いに完全に分離して実行できます。その利点は、プロジェクト間の通信がサービスによって非常に簡単になることです (コア仕様の PDFページ 123 を参照)。この方法では、データと呼び出しがすべて同じ jvm にあるため、いかなる種類の「シリアル化」も行われません。

さらに、サービスの品質に関するすべての要件 (応答時間など) がなくなります。サービスを使用したいときに、サービスが稼働しているか停止しているかを気にするだけで済みます。そのために、Declarative Services と呼ばれる非常に優れた仕様があります ( Enterprise Spec PDF page 141 を参照) 。

トピック外の回答で申し訳ありませんが、他の人がこれを代替案と見なす可能性があると思いました.

アップデート

セキュリティに関するあなたの質問に答えるために、私はそのようなシナリオを考えたことがありません. OSGI 内で「メモリ」の使用を強制する方法があるとは思えません。

ただし、異なる OSGI ランタイム間で JVM の外部で通信する方法があります。これは、リモート サービスと呼ばれます ( 7 ページのEnterprise Spec PDFを参照)。彼らはまた、そのようなことを行う際に考慮すべき要因についても良い議論をしています (13.1 誤謬を参照してください)。

Apache Felix(OSGIの実装)の人々は、iPOJOを使用した分散サービス(サービスを簡単に使用できるようにするラッパー)と呼ばれるiPOJOでこれを実装していると思います。私はこれを使ったことがないので、間違っていたら無視してください。

于 2011-02-19T18:16:36.317 に答える
5

akkaは別のオプションであり、他の Java アクター フレームワークと同様に、アクター モデルから派生した通信やその他の機能を提供します。

于 2011-02-19T21:12:07.550 に答える
5

KryoNet はシリアライゼーションに特化しており、非常に軽量であるため (リモート メソッド呼び出しも利用できます! 現在使用しています)、ローカル ソケットでKryoNetを使用しますが、ソケット切断タイムアウトを無効にします。

RMI は基本的に、リモート型があり、リモート型がインターフェイスを実装するという原則に基づいて機能します。このインターフェイスは共有されています。ローカル マシンで、RMI ライブラリを介してインターフェイスを、RMI ライブラリからメモリ内に「注入された」コードにバインドします。その結果、インターフェイスを満たしながらリモート オブジェクトと通信できるものが得られます。

于 2011-02-19T18:03:17.193 に答える
4

標準入力/標準出力を使用できない場合は、ソケットを使用します。ソケットの上にある種のシリアライゼーション レイヤーが必要です (stdin/stdout の場合と同様)。RMI は非常に使いやすく、非常に効果的なそのようなレイヤーです。

RMI を使用していて、パフォーマンスが不十分であることがわかった場合は、より効率的なシリアライザーに切り替えます。多くのオプションがあります

Web サービスや XML には近づきません。これは完全に時間の無駄のように思えます。RMI よりも労力がかかり、パフォーマンスが低下する可能性があります。

于 2011-02-19T17:59:59.227 に答える
3

もはやRMIが好きな人はあまりいないようです。

オプション:

  1. ウェブサービス。例: http: //cxf.apache.org
  2. JMX。さて、これは実際にはテーブルの下でRMIを使用する手段ですが、機能します。
  3. その他のIPCプロトコル。あなたはヘシアンを引用しました
  4. ソケット、または共有メモリを使用して自分でロールバックします。(親でマップされたファイルを開き、子でもう一度開きます。同期のために何かが必要です。)

注目すべき例は、Apache ant(何らかの目的であらゆる種類のJVMをフォークする)、Apache maven、およびTanukisoftデーモン化キットのオープンソースバリアントです。

個人的に、私はWebサービスに非常に慣れているので、それは私が物事を釘に変える傾向があるハンマーです。典型的なJAX-WS+JAX-BまたはJAX-RS+JAX-Bサービスは、CXFを使用した非常に小さなコードであり、すべてのデータのシリアル化と逆シリアル化を管理します。

于 2011-02-19T17:17:39.727 に答える
3

上で述べましたが、JMX の提案を少し拡張したいと思います。私たちは実際にあなたが計画していることをほぼ正確に行っています(あなたのさまざまなコメントから収集できるものから)。さまざまな理由で jmx を使用することにしましたが、そのいくつかをここで説明します。1 つには、jmx はすべて管理に関するものであるため、一般に、やりたいことには完全に適合します (特に、他の管理タスクに jmx サービスを使用することを既に計画している場合)。jmx インターフェースに加えた努力は、jvisualvm のような Java 管理ツールを使用して呼び出すことができる API として 2 つの役割を果たします。これは、あなたが望むものに最も関連する次のポイントにつながります. 新しいアタッチ APIjdk 6以降では非常に甘いです。これにより、実行中の jvm を動的に検出して通信できます。これにより、たとえば、「コントローラー」プロセスがクラッシュして再起動し、既存のすべてのワーカー プロセスを再検索できます。これは非常に堅牢なシステムの素質です。jmx は基本的に内部で rmi を使用することは前述しましたが、rmi を直接使用する場合とは異なり、すべての接続の詳細を管理する必要はありません (たとえば、一意のポートの処理、発見可能性など)。アタッチ API は、あまりドキュメント化されていないため、jdk の隠れた宝石のようなものです。最初にこれを調べたとき、API の名前を知らなかったので、jvisualvm と jconsole の「魔法」がどのように機能するかを理解するのは非常に困難でした。やっとこんな記事が出てきた独自のプログラムで動的にアタッチ API を使用します。

于 2011-02-20T03:05:15.420 に答える
2

上記で多くのことが議論されています。しかし、ソケット、rmi、jms のいずれであっても、関連する多くの汚い作業があります。私はラッターアドバイスakkaと思います。メッセージを使用して相互に通信するアクター ベースのモデルです。

すばらしい点は、アクターが同じ JVM または別の JVM に配置でき (構成が非常に少ない)、あとは akka が処理してくれることです。これを行うよりもクリーンな方法を見たことがありません:)

于 2013-05-09T09:23:09.803 に答える
2

JVM 間の潜在的なリモート通信用に設計されていますが、 Nettyはローカル JVM インスタンス間でも非常にうまく機能することがわかると思います。

これはおそらく、Java 用のこのタイプのライブラリの中で最もパフォーマンスが高く、堅牢で、広くサポートされているライブラリです。

于 2011-02-19T18:12:30.210 に答える
1

通信するデータがそれほど大きくない場合は、jGroupsを試してください。

于 2011-02-19T18:01:42.390 に答える
0

http://code.google.com/p/protobuf/はいかがですか 軽量です。

于 2011-02-19T19:40:41.473 に答える
0

あなたが言及したように、明らかにネットワーク経由でオブジェクトを送信できますが、別の JVM を起動することは言うまでもなく、コストがかかります。

1 つの JVM 内で異なる世界を分離したい場合の別のアプローチは、異なるクラスローダーでクラスをロードすることです。ClassA@CL1!=ClassA@CL2 (CL1 および CL2 によって兄弟クラスローダーとしてロードされる場合)。

classA@CL1 と classA@CL2 の間の通信を有効にするには、3 つのクラスローダーを使用できます。

  • process1 をロードする CL1
  • process2 をロードする CL2 (CL1 と同じクラス)
  • 通信クラス (POJO およびサービス) をロードする CL3。

ここで、CL3 を CL1 と CL2 の親クラスローダにします。

CL3 によってロードされるクラスでは、CL1 のクラスと CL2 のクラス間の POJO の軽量通信送受信機能 (send(Pojo)/receive(Pojo)) を持つことができます。

CL3 では、CL1 および CL2 登録からの実装が POJO を送受信できるようにする静的サービスを公開します。

于 2011-02-19T17:07:40.880 に答える