オープンソースのピアツーピア(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実装 |
|---|---|
| 今日の典型的ネットワーク設定上での大規模なスケーラビリティ |
|
| パフォーマンスの改善 |
|
| 開発者への分かりやすさの改善 | 数え切れないほどのAPIの再設計や改善がなされ、APIが理解しやすくなり、一貫性も大きく改善されています。主なAPI変更としては次のようなものです
|
| 信頼性の改善 | 全体としてのネットワークの信頼性を改善するために、ピアの状況適応動作が変更されました(ネットワークの使用可能性に関してはランデブーとリレーが最も重要なサービスなので、ほとんどの変更はこの2つに関係しています)
|
| 管理しやすさの改善 | ピアに対する詳細リモート・モニタリングのサポート。JXTA 2には拡充された計測、メータリング機能が備わっています。これはネットワーク調整やパフォーマンス/スケーラビリティ改善を図る上での重要な要素であるベンチマーキングに必須です。モニタリング用のGUIユーティリティもあり、JXTAピアをより操作管理しやすくするための長期計画の始まりを象徴しています。 |
| モバイル機能 | Java 2モバイル版(JXME)でのJXTA実装に対するプロキシー機能の提供 |
この記事では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(ランデブー・スーパーピア・ネットワーク)に「押し出され」ます。
JXTA 2ネットワークは常時存在し、ネットワーク全体に渡って動的な分散データ構造として動作します。つまり全JXTAグループ内で公開されたアドバタイズメントのインデックスを含む仮想ハッシュ表という分散構造です。エッジ・ピアは属性一式(表のハッシュ・キー)を渡すことで、いつでもハッシュ表をクエリーできます。要求された値(つまり要求されたアドバタイズメントを含むピア)に対して鍵をハッシュすることで、ネットワーク(実はランデブー・スーパーピア・ネットワーク)がクエリーを解決します。これを図1に示します。
図1. 緩い一貫性を持つDHTとしてのランデブー・スーパーピア・ネットワーク
図1で、エッジ・ピア1(EP1)はローカルでパイプを生成し、アドバタイズメントを保存します。インデックスはSRDI経由で更新され、DHTはこのアドバタイズメントがあることを知ります。ある時間の後、エッジ・ピア2(EP2)がEP1のパイプへのクエリーを実行します。ランデブー・スーパーピア・ネットワークはそのクエリーを解決し、EP1にそのアドバタイズメントに対する要求を通知します。その結果、EP1は要求されたアダバタイズメントをEP2へのレスポンスとして送信します。
このDHTを生成するために、各ピアはアドバタイズメントをローカルでキャッシュし、ローカルで保存されたアドバタイズメントにはすべてインデックスが付けられます。このインデックスはランデブー・ノードに押し出されます(JXTA 2エッジ・ピアは一度に一つのランデブー・ノードにのみ接続します)。ランデブー・スーパーピア・ネットワークはその混合されたインデックスを含むDHTを保持します。クエリーは常にランデブーに送信されます(図2)。
図2. DHTとして動作するランデブー・スーパーピア・ネットワークでのクエリー解決
図2に示すステップは以下の通りです。
- EP1がパイプを生成し、ローカルにアドバタイズメントを保存します。
- インデックスがローカルで更新され、そのインデックス更新が接続されたランデブー(R1)に押し出されます。
- SRDIインデックス伝搬により、更新を受け取るランデブー(R1)がスーパーピア・ネットワークで選択されたランデブー(R3とR5)に新しいインデックス情報を複製します(この選択と複製過程については、ランデブー・ピアビューとRPVウォーカーを見てください)。
- その後、EP2がEP1のパイプをクエリーします。このクエリーはEP2に唯一接続されているランデブー、R4に送信されます。
- R4はそのクエリーの属性をハッシュし、スーパーピア・ネットワークの別のランデブー、R3にリクエストを転送します。
- R3はEP1のインデックス更新をR1経由で受け取ると即時にEP1に対してEP2の要求を通知します。
- EP1は要求されたパイプ・アドバタイズメントを含むレスポンスを直接EP2に送ります。この時点でクエリーが解決されました。
- 今度はEP2がパイプ・アドバタイズメントを保存することになり、再度サイクルが始まります。
ここまで、JXTA 2ランデブー・ネットワークが保持するDHTが常に完全な一貫性をもって保持されるかのように説明してきました。ところがDHT実装に寄与しているランデブー群は(エッジ・ピアほど頻繁ではありませんが)P2Pネットワークに加わったり離れたりするので、現実的には一貫性は保持できません。ランデブーが離れる時は、そのランデブーが保持しているインデックス一式は(担当のピアが再度公開するまで)暫くの間アクセスできなくなります。JXTA 2は適応型方式を採り入れることで緩い一貫性を持つDHTを保持し、本質的に過渡性の強いP2Pネットワークに対応します。
JXTA 2の方式は、(連結ピアが無くなることで、別々なピアの島ができて)ネットワークが突然分割されても、(別々なピアの島を連結するピアが現れて)他のネットワークと新たに統合されても、DHTが動作し続けることを保証するものです。JXTA 2の方式はランデブー・ピアビュー (RPV)やプラグ可能ランデブー・ウォーカーの概念を含むものです。
スーパーピア・ネットワークの各ランデブーはRPVを保持します。RPVはそのピアに既知のランデブーを、各ランデブー固有のピアIDの順で並べたリストです。DHTアルゴリズムで使われるハッシュ機能はどのピアでも同じで、(ローカルで解決できない)クエリー・リクエストの転送先としてのランデブーを決定するのに使われます。
あるランデブーに到達不能になると、そのランデブーはピアのRPVから除去されます。スーパーピア・ネットワークの各ランデブーは、RPVからランダムに選んだランデブー群に対して、既知のランデブーのランダムなサブセットを定期的に送信します。これはPRVがやがて全ネットワークで確実に収束し、下の物理ネットワークでどんな分割や統合がされても、確実に対応できるようにするために行われます。ネットワーク中の異なるランデブーに保持されているRPVは、任意の時間どの瞬間においても、お互いに一貫性が無い可能性があることには注意してください。
DHTを保持しながら、SRDIは受信されるインデックス情報を、固定のハッシュ機能に基づいてスーパーピア・ネットワーク上の選択されたランデブー・ピアに保存します。緩い一貫性に対応して、インデックス情報はRPVに隣接のランデブー・ピアにも冗長的に複製されます(RPVは既知のランデブーを汎用の固有ピアIDの順で並べたリストであることを思い出してください)。これにより、もしターゲットのランデブーがクラッシュした場合でも、クエリー中にそのインデックス情報にハッシュできる可能性はまだ非常に高いことが保証されることになります。
クエリーを解決する時には、ランデブー自身のRPVに対してハッシュ機能が実行されます。複数の既存ランデブーが接続を切られたり、複数の新しいランデブーがスーパーピア・ネットワークに加わったりするのはごく普通にあり得るので、ハッシュがクエリーを即座に解決しない場合はRPVウォーカーが導入され、クエリーを限定数の、他のランデブーに転送します。この限定範囲ウォーカーで使われているアルゴリズムは「プラグ可能」に、つまり、より特定なネットワークの状態に合わせてカスタム化できるように設計されています。図3はインデックス情報の冗長ストレージを示しています。
図3. インデックス情報のSRDI冗長ストレージ
この図では、入ってくるインデックス情報をハッシュ機能がR5にマップします。R1はエッジ・ピアからインデックス情報を受け取るランデブーで、そのインデックス情報をR5に送るのと同時に、R4とR6にも複製することでインデックス情報を得やすくします。もし例えばR3が保存してあるインデックスと合致するクエリーを受け取ると、ハッシュが実行され、そのクエリーをR3のRPVにあるR5に送ります。ただし、もしその間にR5が無くなってしまった場合にはRPVは縮小し、R5が元あったギャップを閉じます。これで前のR6が新しいR5になります。
もしR6が要求されたインデックス情報を持っていないとすると、ネットワークのトポロジーは大幅に変わった可能性があります。この場合にはRPVウォーキング・アルゴリズムが機能し始めます。ウォーカーがRPVリストを歩き回って情報を検索します。
次に、ランデブー・スーパーピア・ネットワークを実際に設定、操作してみます。まずその前に、JXTA 2で改善された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と言われる、スターター・クラスを作ります。このクラスがすることは
- コマンドラインのパラメーターを読み、独自の名前とトランスポート・パラメーターでランデブー・ピアまたはエッジ・ピアをコンフィギュレーションします。
-
net.jxta.util.configパッケージを使ってピア・アドバタイズメントを生成し、保存します。 - 新しいコンフィギュレーションでシェルを起動します。
ステップ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.principalとnet.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 |
テスト・ディレクトリの下にそれぞれrdv1からrdv5まで5つのランデブー起動ディレクトリがあります。peer1と呼ばれるピア起動ディレクトリもあります。各ディレクトリにはShellStarterのパラメーター化に対応するrunshell.batファイルがあります。IPアドレスを変更するには、これらのファイルを編集します。図4はこのネットワークのコンフィギュレーションを示します。
図4. 実験用のJXTA 2ネットワークを構成する
システムを開始するにはまず、すべてのランデブーを1から5の順に起動しますが、この際1つが完全に起動するのを待ってから次を起動するようにします。次にpeer1を起動します。
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のものであることは、rdv4でwhoamiをタイプすることで確認できます。
Lrdv4シェル・ウィンドウを見ると、rdv4から直接応答が送信されていることも分かります。
Replying search query= treasure send reply sent |
他のランデブーではクエリーが転送されているのが分かります。
Forwarding search query= treasure |
つまりこうです。「treasure」をクエリーするとランデブー・ウォーカーが起動され、ランデブー・スーパーピア・ネットワークを「歩き」ます。ランデブー・クライアントとして、このリクエストは結合された唯一のランデブーであるrdv1に渡されます。これはrdv1から始まるウォークで、これによってクエリーの伝搬が始まります。「treasure」ストリングを持たないランデブーは、(任意に設定された生存時間で、ホップカウント制限が10、またループ検出の対象となる)リクエストをrdv4に達するまで転送しますが、これは各ランデブーがウォーカーを経由して他の既知のランデブー・ポイントにリクエストを転送することで行われます。rdv4はクエリーを受け取ると、直接peer1に応答します。
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プログラミングのあらゆる側面に関する記事が豊富に用意されています。

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