本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

JXTA 2: ハイパフォーマンス、大規模スケーラブルP2Pネットワーク

新しいJXTAリリースで現実的な変更がなされ、実世界のトポロジーに対応

Sing Li (westmakaha@yahoo.com), Author, Wrox Press
Photo of Sing Li
Sing LiはWrox Pressから出版されている多数の本の著者で、Professional Apache Tomcat 、Early Adopter JXTA 、Professional Jini などを執筆しています。技術雑誌に頻繁に寄稿しており、P2P発展に関する熱心なエバンジェリスト(伝道者)でもあります。コンサルタント兼ライターであるSingの連絡先はwestmakaha@yahoo.comです。

概要: 一般的なJavaベース・リファレンス実装を備えたオープンソースP2Pネットワーク構築基盤として、JXTA 2は2番目の主要リリースです。大掛かりな設計変更がなされ、高機能、大規模にスケーラブルで、かつ保守管理が容易なP2Pネットワークが構築できるようになりました。この記事は2年前に発表されたSing LiのJXTAシリーズ、 P2Pを相互運用可能にする 、を元にして、新しいプラットフォームの主な変更点を説明します。

日付:  2003年 11月 11日
レベル:  中級 この記事の原文:  英語
アクティビティー: 1374 ビュー
お気軽にご意見・ご感想をお寄せください: 


オープンソースのピアツーピア(P2P)コミュニティや分散コンピューティング・コミュニティはJXTA 1.0に熱狂的な歓迎をしてきました(参考文献で以前のdeveloperWorks でのJXTXの記事を見てください)。JXTAプラットフォーム開発チームはJXTAが相互運用可能で、将来のP2Pネットワーク・アプリケーションを構築する基盤としての標準になり得るし、なるべきであると主張してきましたが、この主張をテストしようとする独立系のオープンソース・プロジェクトの広がりによってJXTAコミュニティは発展してきました。

蓄積された経験から学ぶ

過去2年間、JXTAプラットフォーム設計チームは精力的にJXTA開発コミュニティを支援し、基本的な設計概念やJXTAプラットフォームAPIが提供する機能を使うにあたってのベスト・プラクティスをよりよく理解できるように協力してきました。設計チームにはアプリケーション開発コミュニティからフィードバックやその経験が貴重なコメントや助言として寄せられました。こうしたフィードバックは現実世界での展開の試みの結果ですが、そこにはこのプラットフォームの元設計の限界やAPIライブラリの不備への指摘、また一貫性の無さへの指摘や、現実世界でのP2Pアプリケーションを構築する上でJXTAをより応用性あるものにするための具体的で現実的な要求などが含まれています。こうした貴重な経験の蓄積は実際に動作するリファレンス実装をまず持ち込むことで初めて現実になったのですが、その意味ではJXTAの最初のバージョンは意図した目的を達成したと言えます。

JXTAプラットフォーム・チームはこうしたフィードバックに基づき、JXTA 2の設計、実装での主要な目標を一式として設定しました。表1は優先目標と、JXTA 2の実装がその目標をどう達成するかを簡単に示したものです(JXTA 1とJXTA 2で違いがあるところは強調表示されています)。


表1. JXTA 2設計目標と実装
目標JXTA 2実装
今日の典型的ネットワーク設定上での大規模なスケーラビリティ
  • JXTA 2ではランデブー・スーパーピア・ネットワークという概念を導入し、伝搬トラフィックを減らすことで大きくスケーラビリティを改善する(大規模スケーラビリティに向けてを参照)
  • ランデブー・スーパーピア・ネットワーク内でSRDI(shared resource distributed index)を実装し、緩い一貫性を持つフォールト・レジリアントな(障害耐性のある)分散ハッシュ表(共有リソース分散インデックス参照)を生成する
  • ローカルのノード単位と全ネットワーク両方でリソース利用を大幅に改善する
  • 大型スーパーコンピューターを使用し、非常に大規模なJXTA 2ネットワークの相互動作をシミュレートし、何十万ノードものネットワークのスケーラビリティを保証する
パフォーマンスの改善
  • ローカルのノード単位と全ネットワーク両方で、リソース割り振りや再利用を改善する
  • 以下によりローカル最適化を図る:プラットフォーム・メモリー・フットプリントの厳密な制御、スレッド処理の効率改善、プロトコル・スタック内での複数バッファー・コピー繰り返しの除去、ローカル・キャッシュに保存されたアドバタイズメントへの制御、ディスカバリーを実行せずにパイプに関連付けられたパイプ・アドバタイズメントを獲得する機能、等々
  • 以下によりネットワーク・リソースを改善する:TCPコネクションのバック・チャネルを使用した既存ネットワーク接続の有効利用、ネットワーク・アドレス変換ピアへの新しいTCPリレー(NAT・・ネットワーク・アドレス変換デバイスのサイドバーを見てください)、全アドバタイズメントでなくアドバタイズメントのインデックスのみをSRDIで伝搬、有線プロトコル形式のビット節約バイナリの導入
  • (現在はカスタム化されたXindice btreeデータベースで行われている)ローカル・アドバタイズメント・ストレージとインデックス化で、前バージョンでのファイルシステム・ベースのストレージ方式よりもパフォーマンスを改善する
  • HTTPトランスポート(現在では1.0、1.1両方をサポートし、下のTCPコネクションをより効率的に利用している)
  • ルーティング・ヒント・サポート(アドバタイズメントのルート解決を迅速化するために追加されている)
開発者への分かりやすさの改善数え切れないほどのAPIの再設計や改善がなされ、APIが理解しやすくなり、一貫性も大きく改善されています。主なAPI変更としては次のようなものです
  • メッセージの生成と取り扱い
  • メッセージ要素の操作
  • 非同期ディスカバリー処理での柔軟性の改善
  • プログラマチック・コンフィギュレーターのサポート
  • リレー、ランデブー、ルーター、トランスポート機能の明確な分離
  • 現在のネットワークでのファイアーウォール、リレー、プロキシー要素の表現用語の統一
  • グループIDのIDファクトリー(前バージョンでは手動で生成するには面倒な作業でした)
  • ピア相互間にストリーム・ベースのAPIを提供するJxtaSocket(JavaプラットフォームのソケットAPIに類似)
  • ピア相互間を通過するメッセージに双方向パイプ機能を提供するJxtaBiDiPipe
信頼性の改善全体としてのネットワークの信頼性を改善するために、ピアの状況適応動作が変更されました(ネットワークの使用可能性に関してはランデブーとリレーが最も重要なサービスなので、ほとんどの変更はこの2つに関係しています)
  • ランデブー・コネクションのフェイルオーバー
  • リレー・コネクションのフェイルオーバー
  • ランデブーの動的ディスカバリーと追跡
  • リレーの動的ディスカバリーと追跡
  • 一定時間後にランデブーが一つも発見されない場合は、エッジ・ピアがランデブーになる
管理しやすさの改善ピアに対する詳細リモート・モニタリングのサポート。JXTA 2には拡充された計測、メータリング機能が備わっています。これはネットワーク調整やパフォーマンス/スケーラビリティ改善を図る上での重要な要素であるベンチマーキングに必須です。モニタリング用のGUIユーティリティもあり、JXTAピアをより操作管理しやすくするための長期計画の始まりを象徴しています。
モバイル機能Java 2モバイル版(JXME)でのJXTA実装に対するプロキシー機能の提供

ネットワーク・アドレス変換デバイス

ネットワーク・アドレス変換デバイス (NAT)は複数のコンピューターやターミナルが、(送出パケット、受信パケットのネットワークアドレスを変換することにより)一つのネットワーク・アドレスでインターネットに接続できるようにします。こうしたデバイスはホーム・ユーザーや、遠隔で作業するビジネス・ユーザーの間で広く使われており、よく高速インターネット・ルーター やインターネット・シェアリング・デバイス などと呼ばれるものです。

この記事ではJXTA 2での重要な変更点、大規模スケーラビリティを可能にした変更点を詳細に見ていきます。また新しいプラットフォーム・コンフィギュレーションAPIで実地コーディングも行い、JXTAシェルのサイレント・スタートアップ・ハーネス(静的起動ハーネス 自分独自のJXTAアプリケーションでそのまま再利用できるハーネス)を作ります。そして最後に新しいシェルコマンドのいくつかを使ってみて、JXTA 2ネットワークでリソースがどのように位置し、インデックスを付けられているかを見てみます。

大規模スケーラビリティに向けて

実世界のネットワーク・トポロジーは時間と共に発展しますが、その発展具合は普通、ソフトウェア・システム設計者の手の及ばない、外部インフラや経済的な要因に影響を受けるものです。JXTA 1では、下にある物理的ネットワーク・トポロジーを使用するにあたってかなり純粋、理論的な手法をとっていましたが、JXTA 2では対照的に非常に現実的な手法を用いており、現在最も普通のネットワーク・トポロジーの上でハイ・パフォーマンスかつスケーラブルなネットワーク構成ができるようにしています。

JXTA 2ではランデブー・スーパーピア・ネットワークという概念を取り入れていますが、これはエッジ・ピア、ランデブー・ピア 混在の中に、分離された形のP2Pネットワークを動的かつ状況に適応した形で構成するものです。伝搬はより安定な(かつ、より少数の)ランデブー・ピアの間でのみ起こります。この制約のおかげでスケーラビリティが大幅に高まり、また全ネットワーク規模でのメッセージ・ストームやフラッディングは非常に起こりにくくなります。

この新しいオーバーレイ・ネットワークがどう実装されているか、もっと詳しく見てみましょう。

エッジ・ピアとランデブー・スーパーピア

JXTA 2では、エッジ・ピアは最も過渡的なもので、頻繁に加わったり離れたりします。JXTA ネットワークでは大部分のピアはエッジ・ピアだと想定しています。エッジ・ピアはクエリー・リクエストを転送しませんし、自身のローカル・アドバタイズメント・キャッシュを保持するとは限りません。大部分のエッジ・ピアはローカル・キャッシュを保持しますが、携帯電話やPDA、ページャー(ポケベル)など限定機能の機器ではキャッシュができるとは限らないのでJXMEのJxtaProxyサービスが必要になります(JXMEについては参考文献を参照してください)。

一部のエッジ・ピアはランデブー・ネットワークと直接接続できますが、大部分はリレーやJxtaProxyとして動作する中間ピアを経由して接続します。エッジ・ピアがP2Pネットワークに参加するのには、一つのランデブーとつながる方法さえ分かっていれば良いのです。普通、エッジ・ピアは既知のランデブーのリスト(シード ・ランデブーと呼ばれる)を保持しており、新しいランデブーを動的に発見します。これによってのピアが代替ランデブーにフェールオーバー可能になり、ネットワーク全体としての信頼性を向上しています。

ランデブー・ピアはエッジ・ピアほど過渡的なものではなく、より安定(一旦ネットワークに接続されると、そのまま接続されたまま)とされています。JXTAネットワークでは、どの瞬間をとらえてもエッジ・ピアの方がランデブー・ピアよりもはるかに多いという想定です。ランデブー・ピアは本来直結ピアです。つまりネットワーク上の他のランデブーとの接続にリレーやJxtaProxyを必要としません。どのランデブー・ピアも(ある特定のJXTAグループにおいて)ランデブー・スーパーピア・ネットワークのメンバーです。ランデブー・ピアは、自身が他のランデブーに対して持っているインデックスのキャッシュでは解決できないクエリーを転送します。ランデブー・ピアはネットワーク中でアクセス可能な全リソースを、緩い一貫性を持つDHT(distributed hash table 分散ハッシュ表)に保持しています。どのランデブー・ピアもネットワーク上で既知のランデブーの動的ビューを保持しており、ネットワーク・トポロジーが変化すると代替ラインデブーに接続またはフェール・オーバーします。

どのJXTAピアもエッジ・ピア、ランデブー・ピアどちらになることもできます。実際、エッジ・ピアは長期間どのランデブーにも接続できないと、やがてデフォルトでランデブー・ピアになります。またネットワーク上のランデブー・ピアはどれもクエリーを発行できるので、エッジ・ピア機能は実際上ランデブー・ピア機能のサブセットと言うこともできます。一般的に、JXTA 2ネットワークでは下にある物理ネットワーク・トポロジーやカスタム化されたユーザー設定に制約を受けながら、その制約に合わせて現実的な形で対象性が適用されます。

共有リソース分散インデックス

JXTA 2ネットワークの動作は分散クエリー解決の能力に依存します。(この概念についてはサイドバーP2Pネットワークの本質を見てください)。JXTA 2ではランデブー・スーパーピア・ネットワークが、緩い一貫性を持つDHTを構成して分散クエリーを解決します。

JXTA 2はSRDI(共有リソース分散インデックス )と呼ばれる分散アルゴリズムを使ってネットワーク中のリソースの概念的なインデックスを生成、保持します。JXTAではリソースはアドバタイズメント(基本的にはXMLドキュメント)形式のメタデータで表現されます。SRDIは全ネットワークに渡るこうしたアドバタイズメントを、指定した属性でインデックス化するために使われます。ここで保持される分散インデックスはハッシュ表と似ていて、インデックス化された属性がハッシュ・キー、実際のアドバタイズメントを含むソース・ピアへの戻りマッピングがハッシュ値です。こうした属性によって、ランデブー・ネットワークのどこででもクエリーが可能です。この方式により、SRDIは要求されたアドバタイズメントのあるピアの位置を特定し、ネットワーク中のアドバタイズメント・クエリーに答えることができます。例えばあるピアが、何千ものノードからなるネットワークに「LotteryServiceという名前のパイプ」のクエリーを送信したとします。SRDIのおかげでこのクエリーを素早く解決し、「LotteryServiceパイプ」アドバタイズメントを持つピアに答えさせることができるのです。

SRDIの下では、リモートでアドバタイズメントを公開する必要はもうありません。ピアに保存されたアドバタイズメントのインデックスのみが公開されるのです。このインデックス情報は接続された、単一のランデブー経由でDHT(ランデブー・スーパーピア・ネットワーク)に「押し出され」ます。

緩い一貫性を持つDHT

JXTA 2ネットワークは常時存在し、ネットワーク全体に渡って動的な分散データ構造として動作します。つまり全JXTAグループ内で公開されたアドバタイズメントのインデックスを含む仮想ハッシュ表という分散構造です。エッジ・ピアは属性一式(表のハッシュ・キー)を渡すことで、いつでもハッシュ表をクエリーできます。要求された値(つまり要求されたアドバタイズメントを含むピア)に対して鍵をハッシュすることで、ネットワーク(実はランデブー・スーパーピア・ネットワーク)がクエリーを解決します。これを図1に示します。


図1. 緩い一貫性を持つDHTとしてのランデブー・スーパーピア・ネットワーク
図1. 緩い一貫性を持つDHTとしてのランデブー・スーパーピア・ネットワーク

図1で、エッジ・ピア1(EP1)はローカルでパイプを生成し、アドバタイズメントを保存します。インデックスはSRDI経由で更新され、DHTはこのアドバタイズメントがあることを知ります。ある時間の後、エッジ・ピア2(EP2)がEP1のパイプへのクエリーを実行します。ランデブー・スーパーピア・ネットワークはそのクエリーを解決し、EP1にそのアドバタイズメントに対する要求を通知します。その結果、EP1は要求されたアダバタイズメントをEP2へのレスポンスとして送信します。

このDHTを生成するために、各ピアはアドバタイズメントをローカルでキャッシュし、ローカルで保存されたアドバタイズメントにはすべてインデックスが付けられます。このインデックスはランデブー・ノードに押し出されます(JXTA 2エッジ・ピアは一度に一つのランデブー・ノードにのみ接続します)。ランデブー・スーパーピア・ネットワークはその混合されたインデックスを含むDHTを保持します。クエリーは常にランデブーに送信されます(図2)。


図2. DHTとして動作するランデブー・スーパーピア・ネットワークでのクエリー解決
図2. DHTとして動作するランデブー・スーパーピア・ネットワークでのクエリー解決

図2に示すステップは以下の通りです。

  1. EP1がパイプを生成し、ローカルにアドバタイズメントを保存します。
  2. インデックスがローカルで更新され、そのインデックス更新が接続されたランデブー(R1)に押し出されます。
  3. SRDIインデックス伝搬により、更新を受け取るランデブー(R1)がスーパーピア・ネットワークで選択されたランデブー(R3とR5)に新しいインデックス情報を複製します(この選択と複製過程については、ランデブー・ピアビューとRPVウォーカーを見てください)。
  4. その後、EP2がEP1のパイプをクエリーします。このクエリーはEP2に唯一接続されているランデブー、R4に送信されます。
  5. R4はそのクエリーの属性をハッシュし、スーパーピア・ネットワークの別のランデブー、R3にリクエストを転送します。
  6. R3はEP1のインデックス更新をR1経由で受け取ると即時にEP1に対してEP2の要求を通知します。
  7. EP1は要求されたパイプ・アドバタイズメントを含むレスポンスを直接EP2に送ります。この時点でクエリーが解決されました。
  8. 今度はEP2がパイプ・アドバタイズメントを保存することになり、再度サイクルが始まります。

ここまで、JXTA 2ランデブー・ネットワークが保持するDHTが常に完全な一貫性をもって保持されるかのように説明してきました。ところがDHT実装に寄与しているランデブー群は(エッジ・ピアほど頻繁ではありませんが)P2Pネットワークに加わったり離れたりするので、現実的には一貫性は保持できません。ランデブーが離れる時は、そのランデブーが保持しているインデックス一式は(担当のピアが再度公開するまで)暫くの間アクセスできなくなります。JXTA 2は適応型方式を採り入れることで緩い一貫性を持つDHTを保持し、本質的に過渡性の強いP2Pネットワークに対応します。

JXTA 2の方式は、(連結ピアが無くなることで、別々なピアの島ができて)ネットワークが突然分割されても、(別々なピアの島を連結するピアが現れて)他のネットワークと新たに統合されても、DHTが動作し続けることを保証するものです。JXTA 2の方式はランデブー・ピアビュー (RPV)やプラグ可能ランデブー・ウォーカーの概念を含むものです。

ランデブー・ピアビューとRPVウォーカー

スーパーピア・ネットワークの各ランデブーはRPVを保持します。RPVはそのピアに既知のランデブーを、各ランデブー固有のピアIDの順で並べたリストです。DHTアルゴリズムで使われるハッシュ機能はどのピアでも同じで、(ローカルで解決できない)クエリー・リクエストの転送先としてのランデブーを決定するのに使われます。

あるランデブーに到達不能になると、そのランデブーはピアのRPVから除去されます。スーパーピア・ネットワークの各ランデブーは、RPVからランダムに選んだランデブー群に対して、既知のランデブーのランダムなサブセットを定期的に送信します。これはPRVがやがて全ネットワークで確実に収束し、下の物理ネットワークでどんな分割や統合がされても、確実に対応できるようにするために行われます。ネットワーク中の異なるランデブーに保持されているRPVは、任意の時間どの瞬間においても、お互いに一貫性が無い可能性があることには注意してください。

DHTを保持しながら、SRDIは受信されるインデックス情報を、固定のハッシュ機能に基づいてスーパーピア・ネットワーク上の選択されたランデブー・ピアに保存します。緩い一貫性に対応して、インデックス情報はRPVに隣接のランデブー・ピアにも冗長的に複製されます(RPVは既知のランデブーを汎用の固有ピアIDの順で並べたリストであることを思い出してください)。これにより、もしターゲットのランデブーがクラッシュした場合でも、クエリー中にそのインデックス情報にハッシュできる可能性はまだ非常に高いことが保証されることになります。

クエリーを解決する時には、ランデブー自身のRPVに対してハッシュ機能が実行されます。複数の既存ランデブーが接続を切られたり、複数の新しいランデブーがスーパーピア・ネットワークに加わったりするのはごく普通にあり得るので、ハッシュがクエリーを即座に解決しない場合はRPVウォーカーが導入され、クエリーを限定数の、他のランデブーに転送します。この限定範囲ウォーカーで使われているアルゴリズムは「プラグ可能」に、つまり、より特定なネットワークの状態に合わせてカスタム化できるように設計されています。図3はインデックス情報の冗長ストレージを示しています。


図3. インデックス情報のSRDI冗長ストレージ
図3. インデックス情報のSRDI冗長ストレージ

この図では、入ってくるインデックス情報をハッシュ機能がR5にマップします。R1はエッジ・ピアからインデックス情報を受け取るランデブーで、そのインデックス情報をR5に送るのと同時に、R4とR6にも複製することでインデックス情報を得やすくします。もし例えばR3が保存してあるインデックスと合致するクエリーを受け取ると、ハッシュが実行され、そのクエリーをR3のRPVにあるR5に送ります。ただし、もしその間にR5が無くなってしまった場合にはRPVは縮小し、R5が元あったギャップを閉じます。これで前のR6が新しいR5になります。

もしR6が要求されたインデックス情報を持っていないとすると、ネットワークのトポロジーは大幅に変わった可能性があります。この場合にはRPVウォーキング・アルゴリズムが機能し始めます。ウォーカーがRPVリストを歩き回って情報を検索します。

次に、ランデブー・スーパーピア・ネットワークを実際に設定、操作してみます。まずその前に、JXTA 2で改善されたAPIのいくつかとシェルを見てみます。


主なコンフィギュレーターAPIの改善

APIで改善された領域の主なものに自動コンフィギュレーションのサポートがあります。ようやくプラットフォームAPIを使ってプログラム的にPlatformConfigファイル(ピア・アドバタイズメント)を生成し、JXTAプラットフォームを開始できるようになりました。以前はユーザーがいちいち設定する必要があった、気が重くなるようなパラメーターの山は完全に見えないようになった、ということです。

自動コンフィギュレーションをどう行うかにより、いくつかのAPIがあります。コンフィギュレーションに関連したAPIの大部分はnet.jxta.util.configパッケージにあります。net.jxta.util.config.ConfiguratorクラスはJXTA2コンフィギュレーション・プログラミングを簡単化する汎用のラッパー・クラスですが、多くの場合に有効なものです。net.jxta.util.config.Configuratorは、実際には同じパッケージにある、下位レベルクラスを使ってコンフィギュレーションを行います。

(この記事を執筆中にはまだ入手できませんでしたが)JXTAの来る2.2版では、こうしたコンフィギュレーションAPIは外部のnet.jxta.ext.configパッケージの下に統合されます。(エッジ・ピアか、ランデブー・ピアか、リレーかといった)特定の役割を持つピアのプロファイルのおかげで、プログラム的なコンフィギュレーションがより容易になるはずです。

コンフィギュレーションの主目的は、起動されるべきピアを記述したピア・アドバタイズメントを生成することです。デフォルトで、ピアのアドバタイズメントは.JXTAディレクトリにPlatformConfigとして保存されます。


サイレント・スタートアップのためのJXTAコンフィギュレーション・プログラミング

ここでの実験のためには、ランデブー・ピア5つとエッジ・ピア1つからなる、計6つのJXTAピアを起動する必要があります。作業を簡単にするために6つのピアをすべて同じマシンで実行することにします。これには本来、すべてのコンフィギュレーション・パラメーターをJXTAのGUIから手動で入力するような力業(ちからわざ)が必要で、それを全部記述したらこの記事と同じくらいの量になってしまうでしょう。

複雑になるのを避けるため、com.ibm.devworks.jxta2.shell.ShellStarterと言われる、スターター・クラスを作ります。このクラスがすることは

  1. コマンドラインのパラメーターを読み、独自の名前とトランスポート・パラメーターでランデブー・ピアまたはエッジ・ピアをコンフィギュレーションします。
  2. net.jxta.util.configパッケージを使ってピア・アドバタイズメントを生成し、保存します。
  3. 新しいコンフィギュレーションでシェルを起動します。

ステップ1と2は既存のピア・アドバタイズメントが見つからない時にのみ行われます。

リスト1はcom.ibm.devworks.jxta2.shell.ShellStarterクラスのコードの一部です。全コードのダウンロードについては参考文献を見てください。


リスト1. コピー・コレクターでの簡易版メモリー割り振り
                
public class ShellStarter {
private static final String TLS_PRINCIPAL_PROP = "net.jxta.tls.principal";
    private static final String TLS_PASSWORD_PROP = "net.jxta.tls.password";
    private static final String ADDR_SEP = ":";
    private static final String PORT_PRE = "97";
    ...    
    public ShellStarter() {
    }
    
    public static void main(String[] args) throws Exception {
     ...  
     String tpFname = 
       PlatformConfigurator.getPlatformConfigFileName();
     File tpFile = 
       new File(PlatformConfigurator.getPlatformConfigFileName());
     
     // only perform config if not already configured
     if (!tpFile.exists())   {          
     tcpAddress = args[1];
     rdvNode = args[3];
     int rdvNodeNum = Integer.parseInt(rdvNode);     
     myPort = Integer.parseInt(PORT_PRE + args[2] + PORT_POST);
     Vector rdvList = new Vector();
     if (rdvNodeNum < 10) 
        rdvList.add(TCP_PRE + tcpAddress + ADDR_SEP + PORT_PRE 
          + rdvNode + PORT_POST);
     
     pa = PlatformConfigurator.createTcpEdge(
     args[0], // peername
     "A dwPeer - " + args[0], // description
     tcpAddress, // ip
     myPort,  // ports
     rdvList    , // rdvs
     USER_NAME,
     USER_PASS
     );

     // disable multicast
      // pass in to preserve settings
     TcpConfigurator tc = new TcpConfigurator(pa);
     tc.setMulticastState(false);
     // enable incoming connection
     tc.setServer(tcpAddress);
     tc.setServerEnabled(true);
     tc.save(pa);   // save to pa only, not file
     
     // configure the rendezvous
     if (isRdv) {
      // pass in to preserve rdv settings created by PlatformConfig
     RdvConfigurator rdv = new RdvConfigurator(pa);
     rdv.setIsRendezVous(true);
     rdv.save(pa);
     
     }
     PlatformConfigurator.save(pa);
     } // if config exists
     System.setProperty(TLS_PRINCIPAL_PROP, USER_NAME);
     System.setProperty(TLS_PASSWORD_PROP, USER_PASS);
     Boot.main(args);
    
     }
}

リスト1ではピア・アドバタイズメントを作るのにnet.jxta.util.config.PlatformConfiguratorクラスをどう使うかを、強調表示したコードで示しています。このピア・アドバタイズメントはシェルのインスタンスを(GUIコンフィギュレーターを使わず)サイレント起動するのに使います。まずコマンドライン引数付きのPlatformConfigurator.createTcpEdge()ヘルパー・メソッドを呼んでエッジ・ピアを作ります。ただしエッジ・ピアはデフォルトでマルチキャストをイネーブルにしてしまうので、ここでのように1台のマシンで行う場合にはマルチキャストをディスエーブルにします。net.jxta.util.config.TcpConfiguratorクラスを使ってマルチキャストを止めます。同じTcpConfiguratorを使って、入力されるTCPコネクションをイネーブルにします。そして最後に、コマンドラインがこれをランデブー・ノードとして規定しているかを確認します。ランデブー・ノードとして規定しているならば、net.jxta.util.config.RdvConfiguratorインスタンスを使ってこのピアをランデブー・ピアとして設定します。net.jxta.tls.principalnet.jxta.tls.passwordシステム・プロパティの設定でログイン・プロンプトをバイパスしていることには注意してください。

ShellStarterのコマンドラインは次のようなパラメーターをとります。

ShellStarter <peer name> <local IP or hostname> <port index> <rdv port index> [edge | rdv]

ここで生成する各エッジ・ピア、ランデブー・ピアは同じホスト上で実行しますが、使用するTCPポートは異なります。<port index>パラメーターは、そのピアがポート97?1(「?」はインデックス)で実行していることを意味します。これで9701、9711、9721など、合計10のピア、ランデブーが設定できることになります。例えばピア名rdv1のランデブーをポート9711のIP 192.168.23.17に生成するには次のコマンドラインを使います。

ShellStarter rdv1 192.168.23.17 1 99 rdv

インデックス99のポートを使うと、このランデブーには既知のシード・ランデブーが無いということになります。

ポート9701の同じIPに、上記ランデブーをシードとしてpeer1と呼ばれるエッジ・ピアを生成するには次のコマンドラインを使います。

ShellStarter peer1 192.168.23.17 0 1 edge

JXTA 2での新しいシェル・コマンド

JXTA 2シェルのディストリビューションにはいくつか新しいコマンドがありますが、開発者にとって一番重要なのはkdbコマンドです。このコマンドで、プラットフォーム実行中にJXTAの各種コンポーネントへのデバッグ・ログをオン/オフできます。

kdbコマンドはメニュー駆動で、16のコンポーネントどれに対してもログ優先レベルを設定できます(ですから分量はいろいろですが、デバッグ情報を生成します)。

新しいrouteコマンドはJXTAのルート・テーブル情報を表示したり操作するのに使えます。

ランデブー・スーパーピア・ネットワークの動作理解の助けになるJXTA 2シェルのコマンドで特に役に立つものとして、新しいrdvコマンドもあります。このコマンドにはたくさんのオプションがありますが、そのいくつかはこの記事での実験で詳細に説明しています。

テスト・ディレクトリの下にそれぞれrdv1からrdv5まで5つのランデブー起動ディレクトリがあります。peer1と呼ばれるピア起動ディレクトリもあります。各ディレクトリにはShellStarterのパラメーター化に対応するrunshell.batファイルがあります。IPアドレスを変更するには、これらのファイルを編集します。図4はこのネットワークのコンフィギュレーションを示します。


図4. 実験用のJXTA 2ネットワークを構成する
図4. 実験用のJXTA 2ネットワークを構成する

システムを開始するにはまず、すべてのランデブーを1から5の順に起動しますが、この際1つが完全に起動するのを待ってから次を起動するようにします。次にpeer1を起動します。


RPVとウォーカー・アクションを見る

rdvコマンド(サイドバーの「JXTA 2での新しいシェル・コマンド」を見てください)を使うと、どのランデブーが保持するRPVも見ることができます。

rdv -rpv

一例として、次はここでのrdv1の結果です。

rdv5
rdv4
rdv3
rdv2

RPVの順序はそのピアのピアID順に従います。これでRPVウォーカーが実際に動いている様子が見られるようになりました。rdvコマンドにはストリング・インデックス化サービスを実行するオプションがあります(テストと診断目的専用)。このサービスを起動するには6つのピアそれぞれで次のコマンドを実行します。

rdv -start

ここで、ランデブーにストリングを作ります。ここではrdv4に「treasure」を作ります。

JXTA> rdv -add treasure

次のlistオプションを使って、rdv4がこのストリングを含んでいることを確認できます。ここではrdv4に「treasure」を作ります。

JXTA> rdv -list treasure

RPVウォーカーが動いているところを見てみましょう。peer1で次のストリングを検索します。

JXTA>rdv -search treasure
Sending test message
rdv has sent search query for treasure
JXTA>rdv received from : jxta://uuid-59616261646162614A78746150325
03369170C5E92004D0DB2E48AAA571741C803
                        found: treasure

treasureストリングはrdv4にあることがすぐ発見されます。ピアIDが実際にrdv4のものであることは、rdv4whoamiをタイプすることで確認できます。

Lrdv4シェル・ウィンドウを見ると、rdv4から直接応答が送信されていることも分かります。

Replying search query= treasure
send reply  sent

他のランデブーではクエリーが転送されているのが分かります。

Forwarding search query= treasure

つまりこうです。「treasure」をクエリーするとランデブー・ウォーカーが起動され、ランデブー・スーパーピア・ネットワークを「歩き」ます。ランデブー・クライアントとして、このリクエストは結合された唯一のランデブーであるrdv1に渡されます。これはrdv1から始まるウォークで、これによってクエリーの伝搬が始まります。「treasure」ストリングを持たないランデブーは、(任意に設定された生存時間で、ホップカウント制限が10、またループ検出の対象となる)リクエストをrdv4に達するまで転送しますが、これは各ランデブーがウォーカーを経由して他の既知のランデブー・ポイントにリクエストを転送することで行われます。rdv4はクエリーを受け取ると、直接peer1に応答します。


SRDIの動作を見る

rdvシェルコマンドを使うことで、RPVやランデブー・ウォーキングの機構を簡単に実験することができます。SRDIが動いているところを実際に見るには、SRDIメッセージ・ロギング機構のLOGレベルをDEBUGに設定してから、なにかSRDIのアクションを動かします(つまりピアにアドバタイズメントを生成します)。

診断ストリング・インデックス・サービスからの疑似メッセージを避けるために、初めはサービスを停止します。rdv1からrdv5、peer1のサービスも停止します。

rdv -stop

それから各ピアで、kdb コマンドを使ってSRDIのメッセージのLOGレベルをDEBUGに変更します。

JXTA>kdb
KDB Main Menu
1   Change LOG configuration
q   Quit
MAIN> 1
LOG Menu
1   Global          2   EndpointRouter
3   Endpoint        4   HTTP
5   TCP             6   TLS
7   Rendezvous      8   Discovery
9   Resolver        10  Pipe
11  Relay           12  Messengers
13  Messages        14  Quota Listener
15  SRDI            16  CM
q   Quit
LOG> 15
Level [w,i,f,d,e,q or ?])> d
LOG Menu
1   Global          2   EndpointRouter
3   Endpoint        4   HTTP
5   TCP             6   TLS
7   Rendezvous      8   Discovery
9   Resolver        10  Pipe
11  Relay           12  Messengers
13  Messages        14  Quota Listener
15  SRDI            16  CM
q   Quit
LOG>
            

ここで、peer1でアドバタイズメントを生成しますが、このアドバタイズメントはSRDIインデックス情報をrdv1に押し出し、DHTで複製されるようにします。一番簡単にこれを行うには新しいピアグループ(実際にはピアグループ・アドバタイズメント)を作ります。

newpgrp -n supergroup

その後rdv1から出てくるメッセージを見れば、次のようなSRDIメッセージが見えるはずです。

<DEBUG 14:36:07,078 Srdi:521> Pushing deltas in group NetPeerGroup
<DEBUG 14:36:07,078 Srdi:494> waiting 30000ms before sending 
deltas in group NetPeerGroup

ハッシングや冗長インデックス複製が起きるにつれ、他のランデブーもrdv1が送る他のSRDIメッセージを受け取るはずです。


まとめ

日々の活動の中で、P2Pネットワーキングの影響は大きく、非常に多くのユーザーが影響を受けるものです。有効なP2Pアプリケーション作成の基盤を、完全に分離して設計するのは不可能です。使いやすい基盤の構築には、ユーザーからのフィードバックを検討したり継続的な要求解析を行ったり、また再考しつつ設計を繰り返すことがどれも非常に重要です。JXTAはこの考えに忠実に沿ったものです。JXTAの第2世代は、初期にJXTAを採用したユーザー層からの現実的な要求に応えて進化したものです。

核となるランデブー・ピアを通して相互結合されたエッジ・ピアとその上にオーバーレイされたネットワークを実際的に分離することで、JXTA 2では今日普通のネットワーク・トポロジー上に展開することがずっと容易になっています。「フラット」な構成では普通に起きてしまうようなメッセージのブロードキャスト・ストームやフラッディングも起きにくくなっています。

JXTA 2で核となるランデブー・ピア・ネットワークは緩い一貫性を持つDHTを持っています。P2Pネットワーク上で利用可能なリソースはすべてインデックスを付けられており、このDHTのおかげで動的に取り出すことができます。DHTが保持するインデックスはSRDIです。最初のバージョンとは対照的に、アドバタイズメントが全ネットワークを伝搬することはなく、インデックス情報のみが要求に応じて伝搬されます。この手法のおかげで、クエリー解決には少し余計に計算が必要にはなりますが、ネットワークの帯域利用は劇的に改善されています。

JXTAプラットフォームAPIも成熟しつつある領域です。ピア・コンフィギュレーションAPIが完全動作可能となったので、JXTAデフォルトの(かつ、しばしば混乱させられる)ピア・コンフィギュレーターを起動することなく、サイレントに起動するアプリケーションを開発することができるようになりました。ここの実験では、サイレントなシェル起動スクリプトを作る際にこのAPIを使ってみました。新しいシェル・コマンドであるrdvを使うことで、ランデブー・スーパーピア・ネットワークが動いている様子を見ることができました。DEBUGログレベルをkdbシェル・コマンドをで設定することで、SRDIのメッセージングや操作も見ることができました。

スケーラブル、ハイ・パフォーマンスでかつ(一番重要な)使いものになるP2Pネットワークを構築するという目標は追求し続ける必要があります。JXTA 2はその方向に向かっての正しい一歩と言うことができます。


参考文献

  • この記事のソースコードをダウンロードしてください。

  • JXTAプラットフォームの最初のリリースに関して説明したSing Li による別のシリーズ、P2Pを相互運用可能にする を見てください。
    • 第1回 Jxtaの物語ではProject JXTAの概要を説明しています。P2Pアプリケーションを作るのがどう簡単になり、また不必要なポリシーや特定なアプリケーション操作モデルを強制せずに簡単なアプリケーションを作るにはどうすべきかを説明しています。
    • 第2回 Jxtaコマンド・シェルではJXTAシェルを実際に使いながら学びます。シェルのコマンド・セットを学び、Javaプログラミング言語を使って自分独自のカスタム・コマンドを書くことでシェルの機能を拡張します。
    • 第3回 Jxtaシステムの作成ではTCP/IPネットワークでのJXTAの拡張を説明し、JXTAがクライアント / サーバー・ネットワークにありがちな制約に拘束されないことを説明しています



  • JXTAの最新の仕様やドキュメンテーション、ソース、バイナリなどについては公式サイトJXTA communityを見てください。

  • Bernard Traversatなどによるホワイト・ペーパーProject JXTA 2.0 Super-Peer Virtual Network(2003年5月Project JXTA)では、ランデブー・スーパーピア・ネットワーク内部の動作を非常に詳細に説明しています。

  • JXMEをどう展開し、モバイル・デバイスをどのようにしてJXTAやJabberクライアントにするかをMichael Juntao YuanがMobile P2P messaging, Part 2: Develop mobile extensions to generic P2P networks(developerWorks 2003年1月)で説明しています。

  • JXMEについてより詳しい記事として、Roman VichrによるTips & tricks: JXTA(developerWorks 2002年4月)でのモバイル・デバイスの説明を見てください。

  • Todd SundstedによるdeveloperWorks でのシリーズThe practice of peer-to-peer computing(2001年3月-2002年1月)は基本的なP2Pコンピューティングの原則の背景を説明した記事です。

  • developerWorks のJava technologyゾーンにはJavaプログラミングのあらゆる側面に関する記事が豊富に用意されています。

著者について

Photo of Sing Li

Sing LiはWrox Pressから出版されている多数の本の著者で、Professional Apache Tomcat 、Early Adopter JXTA 、Professional Jini などを執筆しています。技術雑誌に頻繁に寄稿しており、P2P発展に関する熱心なエバンジェリスト(伝道者)でもあります。コンサルタント兼ライターであるSingの連絡先はwestmakaha@yahoo.comです。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=218799
ArticleTitle=JXTA 2: ハイパフォーマンス、大規模スケーラブルP2Pネットワーク
publish-date=11112003
author1-email=westmakaha@yahoo.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。