Java EE と Web 2.0 との出会い

非同期イベント駆動型アーキテクチャーを採り入れて、最近の Web アプリケーションの課題に対処する

標準 Java EE (Java Platform, Enterprise Edition 5) ベースの手法で開発した Web 2.0 アプリケーションはパフォーマンスとスケーラビリティーに関する深刻な問題に直面します。その理由は、同期 API の使用をはじめ、Java EE プラットフォーム設計の基礎となる多くの原則が、Web 2.0 ソリューションの要件には適用されないためです。この記事では、Java EE と Web 2.0 での手法の違いを解説し、非同期設計がもたらすメリットを検討するとともに、Java プラットフォームで非同期 Web アプリケーションを開発する際のソリューションをいくつか取り上げて評価します。

Constantine Plotnikov (cap@isg.axmor.com), Chief Engineer, Axmor

Constantine Plotnikov は、ロシアのノボシビルスクにある Axmor Software and the IBM Customer Innovation Team (CIT) Lab でチーフ・エンジニアを務めています。彼は Novosibirsk State University で数学修士号を取得しました。1994 年以来、分散アプリケーションに取り組んでいる彼は、IT 産業で 15 年以上の経験を積んでいます。JDO (Java Data Object) および JMI (Java Metadata Interface) エキスパート・グループの一員として Java Community Process に参加した経歴もあります。



Artem Papkov (artem@us.ibm.com), IT Architect, IBM

Artem Papkov は、現在 IBM Client Innovation Team のソリューション・アーキテクトで、カスタマーやビジネス・パートナーと協力して SOA および Web サービスなどの新しい技術を導入しています。1998 年、Belarusian State University of Informatics and Radioelectronics でコンピューター・サイエンスの博士号を取得後、2000年にノースカロライナ州リサーチ・トライアングル・パーク所在の IBM に加わりました。新しい技術を使用した多層ソリューションのソフトウェア開発、アーキテクチャー設計、およびインターネット・ベース・ソリューションの経験を持ちます。過去 3 年間は、カスタマーと密に連携して IBM の戦略的統合技術としての Web サービス、および統合手法としての SOA の導入を支援しています。Artem の連絡先は、artem@us.ibm.com です。



Jim Smith (jamessmi@us.ibm.com), Manager, IBM

Jim Smith は、ソフトウェア開発の分野で 18 年以上の経験を持ちます。彼の経歴は、カリフォルニア州リバーモアの Sandia National Labs での、無数の既存のレガシー・コードを使用した高速データ収集システムおよび分散コンピューティング・システムの設計に始まります。Java 言語とカスタマー向き技術に豊富な経験を持つ彼は、IBM カスタマーのための Java ソリューションの実現に的を絞った Emerging Internet Technologies チームに移りました。彼は、ATS (Advanced Technology Solutions) の設立者の 1 人です。これは、IBM、開発研究所、ビジネス・パートナー、およびカスタマーのための先進技術と軽量ビジネス・プロセスを開発、洗練、および特権付与し、標準技術と IBM 製品の導入とデプロイメントをさらに高速化する使命を持つ世界的なソフトウェア・サービスおよび開発組織です。現在 Jim は、この組織を管理しています。



2007年 11月 06日

Java EE プラットフォームを使用して作成された著しい数のエンタープライズ・アプリケーションが成功を納めていますが、Java EE の設計原則は Web 2.0 世代のアプリケーションを効率的にサポートしません。Java EE と Web 2.0 での原則の違いを深く理解することは、この両者の違いにある程度対処するためにどのような手法とツールを使用したらよいか、十分な情報に基づいて判断する上で有用です。この記事では Web 2.0 と標準 Java EE プラットフォームが相容れない理由、そして Web 2.0 アプリケーションには非同期イベント駆動型アーキテクチャーのほうが適している理由を説明します。さらに、Java プラットフォームでの非同期設計を可能にすることによって Java プラットフォームの Web 2.0 への対応を強化すること、を目的としたフレームワークおよび API について紹介します。

Java EE の原則と前提

Java EE プラットフォームが作成された目的は、企業・一般消費者間 (B2C: Business-to-Consumer) および企業間 (B2B: Business-to-Business) アプリケーションの開発をサポートするためです。インターネットに将来性を見出した企業は、インターネットを通してそのパートナーや顧客との既存のビジネス・プロセスを強化し始めました。このようなアプリケーションは多くの場合、既存のエンタープライズ統合システム (EIS: Enterprise Integration System) とやりとりをします。そのため、Java EE サーバーのパフォーマンスとスケーラビリティーを測定するのにもっともよく使われるベンチマーク、ECperf 1.1、SPECjbb2005、そして SPECjAppServer2004 (「参考文献」を参照) の使用事例では、B2C、B2B、EIS に重点を置いています。同様に、標準の Java PetStore のデモも典型的な e-commerce アプリケーションとなっています。

これらのベンチマークには、Java EE アーキテクチャーのスケーラビリティーに関する以下の暗黙的、明示的な前提が反映されています。

  • 要求スループットは、顧客の観点から見たパフォーマンスに影響するもっとも重要な特性である。
  • トランザクションの所要時間はもっとも顕著にパフォーマンスを左右する要素であるため、使用する個々のトランザクションの時間を短縮することによってアプリケーションの全体的パフォーマンスは改善される。
  • トランザクションの多くは互いに独立している。
  • 長期間続くトランザクションの場合は別として、トランザクションによって影響されるビジネス・オブジェクトはほとんどない。
  • トランザクションの所要時間は、アプリケーション・サーバーのパフォーマンス、そして同じ管理ドメインにデプロイされた EIS によって制限される。
  • ネットワーク通信のコスト (ローカル・リソースの操作時) は、コネクション・プーリングによって十分に補われる。
  • ネットワーク構成、ハードウェア、ソフトウェアへの投資が、トランザクションの所要時間を短縮することになる。
  • コンテンツとデータはアプリケーション所有者が管理する。外部サービスに依存していない場合、帯域幅が顧客へのコンテンツ提供を制約するもっとも重要な要素となる。

パフォーマンスとスケーラビリティーの問題について

当初、Java EE プラットフォームは主に単一の管理ドメインにデプロイされたリソースでサービスを操作するように設計されました。EIS トランザクションの存続期間は短く、要求は短時間で処理されるため、プラットフォームは大きなトランザクション負荷をサポートできるという前提になっています。

このような前提が問題となるのが、新たに登場した数々のアーキテクチャーによる取り組みとパターンです。ピアツーピア (P2P) やサービス指向アーキテクチャー (SOA)、そして Web 2.0 と (非公式に) 総称される新しいタイプの Web アプリケーションなど、これらの新しいアーキテクチャーは要求の処理に時間がかかるコンテキストで適用されます。そのため Java EE の手法で Web 2.0 アプリケーションを開発すると、深刻なパフォーマンスおよびスケーラビリティーの問題が持ち上がってきます。

これらの前提によって生み出されたのが、Java EE API が基礎とする以下の原則です。

  • 同期 API。Java EE ではほとんどの用途に同期 API が使用されます (実質上、唯一の例外となっているのは、膨大で扱いにくい JMS (Java Message Service) API です)。この要件はパフォーマンス上の理由というよりはユーザビリティーに基づいていました。同期 API は使いやすく、オーバーヘッドを小さくできるからです。大々的なマルチスレッド化が必要になると、途端に重大な問題が持ち上がってくるため、Java EE では管理の及ばないマルチスレッド化が行われないように徹底しています。
  • 一定数のスレッド・プール。スレッドは重要なリソースであり、スレッドの数が特定の限界を超えるとアプリケーション・サーバーのパフォーマンスが大幅に劣化することがすぐに判明しました。しかし、操作のそれぞれは短時間であるという前提があるので、操作を限られた数のスレッド間で分散することで優れた要求スループットを維持することができます。
  • 一定数の接続プール。データベースへの接続を 1 つにすると、最適なデータベース・パフォーマンスを達成するのは難しくなります。データベース接続を追加すれば複数のデータベース操作を並行して実行できるようになりますが、それでもアプリケーションの速度はある程度までしか向上しません。また、接続がある一定の数に達するとデータベースのパフォーマンスが劣化することになります。データベース接続数がサーブレット・スレッド・プールで使用できるスレッドの数より少ないこともよくあります。このような理由から作成されたのが、接続プールです。接続プールがあれば、サーブレットや EJB (Enterprise JavaBean) などのサーバー・コンポーネントはそこから接続を割り当て、後で接続プールに接続を戻すことができます。使用できる接続がない場合、サーバー・コンポーネントは現行のスレッドをブロックしている接続を待機しますが、他のコンポーネントが接続を使用するのは短時間だけなので、通常この遅延時間は長くはありません。
  • リソースへの固定接続。アプリケーションは少数の外部リソースしか使用しないという前提があり、各リソースの接続ファクトリーは JNDI (Java Naming and Directory Interface) (EJB 3.0 の場合は依存性注入) を使用して取得します。実際、複数の異なる EIS リソースへの接続をサポートする主要な Java EE API はエンタープライズ Web サービス API だけで (「参考文献」を参照)、それ以外のほとんどの Java EE API は、リソースが固定されていること、そして接続を開く操作にはユーザー・クレデンシャルなどのような追加データのみを提供すればよいことを前提としています。

上記の原則は Web 1.0 ではどれも非常に有効に働き、固有のアプリケーションをこれらの制限内で設計することも可能でした。しかし、Web 2.0 の時代をサポートするには効率的ではありません。


Web 2.0 による全体像の変化

Java EE と SOA との出会い

Java EE に対する最初の挑戦の 1 つに、SOA の導入がありました。SOA では対話動作のスループットが高くなる可能性があるだけでなく、サービス・エンドポイントに到達するまで複数のドメインを横断しなければならないことからレイテンシーも大きくなる可能性があります。さらに一部の対話動作には人間による承認が必要となりますが、この承認プロセスによって生じる遅延は数時間から数週間に及ぶ場合もあります。SOA は各種の仲介をサポートするように設計されていることから、レイテンシーの状況は悪化するのが通常です。

これまで Java EE プラットフォームでは、このようなレイテンシーの問題に対処するためにトランザクション・メッセージング API を使用し、ビジネス・プロセスの概念を導入するという方法が採られてきました。しかし、SOAP-over-HTTP Web サービス呼び出しモデルと JMS のようなメッセージング・サービスとの間には一致しない点があります。それは、HTTP では同期要求/応答モデルを使用し、組み込みの信頼性機能を提供しないという点です。B2B コンテキストでデプロイされた Web サービスについては、WS-Notification、WS-Reliability、WS-ReliableMessaging、WS-ASAP などの仕様がこの不一致の対処を図っています。一方 B2C の場合には、リッチ・アプリケーション・クライアントがデプロイされるのが一般的です。Web アプリケーションとは対照的に、リッチ・アプリケーション・クライアントではシナリオに固有の対話パターンを使って大きなレイテンシーに対処できるためです。

Web 2.0 アプリケーションには、その実装に Java EE を選択しにくくしている独特の要件が数多くあります。1 つの特徴として、Web 2.0 では Web 1.0 での場合よりも頻繁にアプリケーション同士がサービス API を介して互いを使用します。Web 2.0 アプリケーションのさらに重要な要素は、一般消費者間 (C2C) の対話動作への大きな偏りです。つまり、アプリケーションの所有者が作成するコンテンツはごく一部で、大部分はユーザーによって作成されます。

SOA、B2C、Web 2.0 の組み合わせがもたらす大きなレイテンシー

Web 2.0 のコンテキストでは、マッシュアップ・アプリケーションが SOA のサービス API によって公開されたサービスとフィードを頻繁に使用します (「Java EE と SOA との出会い」を参照)。これらのアプリケーションは、B2C のコンテキストでサービスを利用しなければなりません。一例として、マッシュアップでそれぞれ固有の 3 つのソースからデータ (気象情報、交通情報、マップ) をプルするとします。この 3 種類のデータを取得するのに必要な時間は、全体的な要求処理時間に加算されます。しかしデータ・ソースとサービス API の数が増えたにも関わらず、サービスの利用者が応答性に優れたアプリケーションを期待することには変わりありません。

キャッシングなどの手法はレイテンシーを軽減できても、すべてのシナリオに適用できるわけではありません。例えばマップ・データをキャッシュに入れて応答時間を短縮するのは理にかないますが、検索クエリーの結果やリアルタイムの交通情報をキャッシュに入れるとなると、たいていは不可能であったり、非実用的です。

その性質上、サービス呼び出しは高レイテンシーの処理で、一般にクライアントとサーバーでの CPU リソースはほんのわずかな量しか割り当てられません。Web サービス呼び出しに必要な時間の大部分は、新しい接続の確立とデータの送信に費やされます。したがって、クライアント・サイドまたはサーバー・サイドでのパフォーマンスを改善しても、呼び出しの所要時間の短縮にはほとんど効果がありません。

さらなる双方向性

ユーザーの参加を可能にする Web 2.0 では、アプリケーションでアクティブなユーザーごとに行われるサーバー要求の数が大幅に増えるため、新しい難題がもたらされます。サーバー要求数の増大には、以下の理由があります。

  • ほとんどのイベントは他の利用者のアクションによって発生することから、関連イベントの数が増え、したがって利用者がイベントを生成する可能性もさらに大きくなります。これらのイベントは当然、利用者に一段と活発に Web アプリケーションを使用させることになります。
  • アプリケーションが利用者に提供する使用事例が多くなります。Web 1.0 の利用者はカタログをブラウズし、商品を購入し、注文の処理状況を追跡するだけでしたが、今ではフォーラムへの参加、チャット、マッシュアップなどによって利用者同士が積極的に関わることができるため、このような活動によってトラフィックの負荷が増加することになります。
  • 最近のアプリケーションではユーザー・エクスペリエンスを改善するために Ajax を使用する傾向が強くなってきています。Ajax を使用した Web ページは静的コンテンツ、スクリプト (かなりの大きさになる可能性があります)、そしてサーバーへの数多くのリクエストで構成されるため、単純な Web アプリケーションのページの場合よりもロードに時間がかかります。ロードが完了した Ajax ページがサーバーに対して複数の短いリクエストを送信することも珍しくありません。

レイテンシーが大きく、帯域幅が小さいクライアント

携帯電話をはじめ、帯域幅が限られたクライアントを対象とするアプリケーションがますます使われるようになってきています。サーバーが特定のクライアントに素早くサービスを提供できるとしても、クライアントのほうではデータを素早く利用できません。クライアントの接続帯域幅は小さく、デバイスの物理的制約もあるためです。クライアントがこのような低スループットの接続でデータをロードしている間、サーバーは十分に活用されないか、あるいはサーブレットのスレッドが占有されている間、待機状態に陥ります。今まで以上にスケーラブルな通信機構が開発されない限り、ネットワーク・サービスを使用するモバイル機器が増加して無線周波スペクトルが使用過多になるにしたがって、帯域幅が限られたクライアントではスループットとレイテンシーが徐々に劣化していくことになります。

通常は以上のことが原因で、サーバーへのトラフィック量も要求の数も一般的な Web 1.0 アプリケーションより増大します。高負荷の状態でこのトラフィックを管理するのは容易なことではありません (ただし、Ajax ではトラフィックを最適化できる可能性も同じく高くなります。たいていの場合、Ajax によって生じるトラフィック量は、同じ使用事例をサポートする単純な Web アプリケーションによって生じるトラフィック量よりも少ないからです)。

コンテンツの増加

Web 2.0 アプリケーションは、前世代の Web アプリケーションより遥かに大きなコンテンツ量とサイズを特徴とします。

Web 1.0 の世界では、コンテンツは企業体の明示的な承認を受けた後、企業の Web サイトでのみ公開されるのが一般的でした。表示されるテキストの一字一句を管理するのは組織です。したがって、予定されたコンテンツのサイズが構造基盤の制約に反していれば、そのコンテンツは最適化されるか、あるいは複数のかたまりに分割されます。

Web 2.0 サイトではその性質から、コンテンツのサイズや作成に制約を設けていません。Web 2.0 コンテンツの大部分を生成するのはユーザーとコミュニティーで、組織や企業は投稿やコンテンツの作成を可能にするツールを提供するに過ぎません。画像、音声、ビデオの多用により、コンテンツのサイズも大きくなってきています。

持続的な接続

クライアントからサーバーへの新たな接続を確立するには相当な時間がかかるため、複数の対話動作が見込まれる場合には、いったん確立したクライアントとサーバー間の接続を再利用するほうが効率的です。接続を維持しておくと、クライアントに通知を送信するのにも役立ちます。けれどもほとんどの場合、Web 2.0 アプリケーションのクライアントはファイアウォールに守られているので、サーバーからクライアントへの直接接続を確立するのは困難であるか、または不可能です。Ajax アプリケーションは要求を送信して特定イベントをポーリングしなければなりませんが、このポーリングの要求数を減らすため、一部の Ajax アプリケーションでは Comet パターンを使用しています (「参考文献」を参照)。このパターンでは、サーバーが接続をオープンにしたままイベントを待機し、イベントが発生してから応答を送信するように設計されています。

持続的な接続は、SIP、BEEP、XMPP などのピアツーピア・メッセージング・プロトコルで次第に使用されるようになっています。また、ライブ・ビデオをストリーミング配信する場合にも持続的な接続が役に立ちます。

スラッシュドット効果のリスク増大

Web 2.0 アプリケーションによってサイトの読者を大幅に増やせるという事実は、一部のサイトにとっては「スラッシュドット効果」の影響を一層受けやすくなるということでもあります。スラッシュドット効果とは、人気のブログやニュース・サイト、あるいはソーシャル・ネットワーキング・サイトでサイトが紹介されると、そのサイトへのトラフィック負荷が爆発的に増えるという現象です (「参考文献」を参照)。すべての Web サイトは、通常の負荷よりも桁違いに大きなトラフィックを処理できるように備えておかなければなりません。さらに重要なのは、このような高負荷の状態でもグレースフルなパフォーマンス低下になるようでなければならないということです。


レイテンシーの問題

操作のレイテンシーは操作のスループットよりも大きな影響を Java EE アプリケーションに及ぼします。アプリケーションが使用するサービスが大量の操作を処理できるとしても、レイテンシーは変わらないか、あるいは悪化してしまうことさえあります。現行の Java EE API では、このような状況はその API の設計に暗黙的に含まれるレイテンシーに関する前提に反するため、うまく対処することができません。

同期 API を使用する場合、フォーラムやブログ用の大規模なページを処理するために 1 つの処理スレッドが占有されることになります。各ページを処理するのに 1 秒かかるとすると (大量のページ数になる LiveJournal などのアプリケーションを想定してください)、スレッド・プールにあるスレッドが 100 であれば毎秒 100 のページしか処理することができません。これは許容しがたい処理速度です。スレッド・プールのスレッド数を増やしても、その効果は限られており、これはスレッド・プール内のスレッド数が増えるにつれ、アプリケーション・サーバーのパフォーマンスが劣化するためです。

Java EE の同期 API が使用するスレッドは常に 1 つだけなので、Java EE アーキテクチャーでは SIP、BEEP、XMPP などのメッセージング・プロトコルの利点は生かされません。アプリケーション・サーバーが使用するスレッド・プールは限られていることから、スレッドがひっきりなしに使用されていると、アプリケーション・サーバーはメッセージング・プロトコルを使用してメッセージの送受信を行っている間、他の要求を処理できないためです。これらのプロトコルで送信されるメッセージは必ずしも短いわけではなく (特に BEEP の場合)、またメッセージを生成すると他の組織にデプロイされたリソースに Web サービスやその他の手段によってアクセスすることになる可能性があることにも注意してください。さらに、BEEP や SCTP (Stream Control Transmission Protocol) といったトランスポート・プロトコルは 1 つの TCP/IP 接続で複数の論理接続を同時に使用する可能性もあります。そうなると、スレッド管理の問題はさらに深刻になります。

Web アプリケーションはストリーミング配信シナリオの実装に際して、標準の Java EE パターンと API を放棄せざるを得ませんでした。その結果、Java EE アプリケーション・サーバーは P2P アプリケーションの実行やビデオのストリーミング配信にめったに使用されなくなり、代わりにメッセージング・プロトコルを処理するカスタム・コンポーネントが開発される場合のほうが多くなっています。これらのコンポーネントではたいてい、JCA (Java Connector Architecture) コネクターを使って専用の非同期ロジックを実装します (この記事を読んでいくとわかるように、新世代のサーブレット・エンジンは Comet パターンを処理するために標準以外のインターフェースもサポートします。ただしこのサポートは、API の点でも、使用パターンという点でも、標準サーブレット・インターフェースとは根本的に異なります)。

最後に、ネットワーク基盤への投資がトランザクションの所要時間を短縮できるという基本的な Java EE 原則を思い出してください。この原則に反して、ライブ・ビデオを配信する場合にはネットワーク基盤を高速化しても要求に費やされる時間には何の影響もありません。ストリームは生成されると同時にクライアントに送信されるからです。ネットワーク基盤を改善しても、ストリーム数が増える結果、接続するクライアント数を増やせたり、高い解像度でのストリーミング配信が促進されたりするだけに過ぎません。


非同期への道

これまで説明してきた問題を回避する方法として考えられるのは、アプリケーションの設計段階でレイテンシーを考慮し、非同期イベント駆動型のアプリケーションを実装することです。アイドル状態のアプリケーションは、スレッドをはじめとする有限のリソースを占有すべきではありません。非同期 API の場合、アプリケーションは外部イベントをポーリングし、イベントが到着したときに該当するアクションを実行します。一般にこのようなアプリケーションは複数のイベント・ループに分割され、それぞれのイベント・ループが固有のスレッド内に常駐します。

非同期イベント駆動型設計による明らかな利点は、操作間にデータ依存性がない限り、外部サービスを待機している多数の操作を並行して実行できることです。非同期イベント駆動型アーキテクチャーには、従来の同期設計に比べてスケーラビリティーに極めて優れているという利点もあります。これは、並行操作がまったく発生しない場合も例外ではありません。

非同期 API の利点: 概念検証モデル

非同期 API を使用することによってもたらされるスケーラビリティーのメリットは、単純なサーブレット・プロセス・モデルを使って説明することができます (非同期設計が Web 2.0 アプリケーションのスケーラビリティー要件に対する答えであるとすでに確信している方は、このセクションを飛ばして Web 2.0 / Java EE での難題に対処するためのソリューションのセクションに進んでも構いません)。

ここで取り上げるモデルでは、サーブレット・プロセスが着信要求で何らかの処理を行ってからデータベースに対してクエリーを実行し、そしてデータベースから取得した情報を使って Web サービスを呼び出します。最終的な応答は、Web サービスの応答に基づいて生成されます。

このモデルのサーブレットでは、比較的レイテンシーの大きな以下の 2 種類のリソースを使用します。この 2 つのリソースは、負荷が増加した時の特性と振る舞いが異なります。

  • データベース接続。このリソースは通常、Web アプリケーションが DataSource として利用するもので、同時に利用可能な接続数が制限されています。
  • ネットワーク接続。このリソースは、クライアントへの応答の作成、そして Web サービスの呼び出しに使用されます。最近まで、ほとんどのアプリケーション・サーバーでは一定数のネットワーク接続しかありませんでしたが、新しい世代のアプリケーション・サーバーではノンブロッキング I/O (NIO) を使用してネットワーク接続を実装するようになってきているので、このモデルでは必要なだけ同時ネットワーク接続を使用できるという前提にすることができます。モデル・サーブレットがこのリソースを使用するのは以下の場合です。
    1. Web サービスを呼び出す場合。宛先サーバーが毎秒処理できる要求の数は限られていますが、通常、この数はかなりのものです。呼び出しの所要時間はネットワーク・トラフィックによって決まります。

    2. クライアントから要求を読み出す場合。このモデルでは HTTP GET 要求を前提とするため、このコストは無視します。したがって、クライアントから要求を読み出すのに必要な時間はサーブレット要求の所要時間には加算されません。

    3. クライアントに応答を送信する場合。このモデルではこのコストを無視します。それは、短いサーブレット応答の場合、アプリケーション・サーバーは応答をメモリーのバッファーに入れておき、後で NIO を使用してクライアントに送信することができるためです。ここでは応答は短いものであるという前提にします。したがって、クライアントへの応答を作成するのに必要な時間はサーブレット要求の所要時間には加算されません。

サーブレットの実行時間は、表 1 に記載するフェーズに分かれるとします。

表 1. サーブレットの動作時間配分 (抽象単位での時間)
フェーズ所要時間動作内容
12 単位サーブレット要求の情報解析
28 単位ローカル・データベース・トランザクション
32 単位データベース要求結果の処理とリモート呼び出しの準備
416 単位Web サービスによるリモート・サーバーの呼び出し
54 単位応答の作成
合計32 単位

図 1 に、ビジネス・ロジック、データベース、Web サービスでの実行時間の分布を示します。

図 1. 実行ステップ間での時間配分
実行ステップ間での時間配分

上記では、図がわかりやすくなるように時間を配分しています。実際のほとんどの Web サービスでは、はるかに多くの時間が処理に費やされます。おそらく、Web サービスの処理時間はビジネス・ロジック Java コードの 100 倍から 300 倍になると考えるのが妥当でしょう。しかし同期呼び出しモデルにチャンスを与えるため、ここでは Web サービスが極めて高速か、アプリケーション・サーバーが非常に遅いか、あるいはその両方が当てはまるかという実際にはありそうもないパラメーターを選びました。

接続プールの容量は 2 とします。したがって、同時に行えるデータベース・トランザクションは 2 つだけです (現実のアプリケーション・サーバーでは、実際のスレッド数と接続数はこれよりも多くなるはずです)。

また、いずれの Web サービス呼び出しも所要時間は同じで、すべての呼び出しは並行して実行できるという前提も設定します。Web サービスの対話動作ではデータのやり取りに時間が費やされるため、これは現実的な前提です。実際の処理に費やされる時間は、Web サービス呼び出しのほんのわずかな部分でしかありません。

このシナリオでは、負荷が低ければ同期と非同期との振る舞いに変わりはありませんが、データベース・クエリーと Web サービス呼び出しが並行して発生するとしたら、非同期の振る舞いのほうが勝ることになります。興味深い結果になるのは、アクセスが突然ピークになるなどの過負荷状態が発生した場合です。例えば 9 つの同時要求が行われたとします。同期の場合、サーブレッド・エンジンのスレッド・プールには 3 つのスレッドがあります。一方、非同期の場合に使用するのは 1 つのスレッドだけです。

いずれの場合にしても、9 つすべての接続が到着時に受け入れられます (たいていのサーブレット・エンジンでの場合と同じです)。しかし同期の場合、最初の 3 つの接続が処理されている間は、受け入れられた残りの 6 つの接続に対して何の処理も行われません。

図 2 と図 3 はそれぞれ同期 API の場合、非同期 API の場合をモデル化した単純なシミュレーション・プログラムを用いて作成したものです。

図 2. 同期の場合

図 2 のそれぞれの長方形はプロセスのうちの 1 つのステップを表します。長方形のなかに示された最初の数字はプロセス番号 (1 から 9) で、2 番目の数字はプロセス内でのフェーズ番号です。各ステップは色分けされています。データベースの操作と Web サービスの操作はそれぞれデータベース・エンジンと Web サービス実装によって実行されるため、異なる線上に示していることに注意してください。サーブレット・エンジンは結果を待機している間、何の処理も行いません。明るいグレーの部分はアイドル (待機) 状態を表します。

図の下部にあるひし形のマーカーは 1 つまたは複数の要求が完了した時点を示します。このマーカーの最初の数字は抽象単位での時間です。この数字に括弧で囲まれた数字が続く場合、それはその時点で終了した要求の数を示します。図 2 を見ると、最初の 2 つの要求は 32 の時点で終了し、最後の要求は 104 の時点で終了したことがわかります。

次に、データベースと Web サービス・クライアントのランタイムが非同期インターフェースをサポートする場合を考えてみましょう。すべての非同期サーブレットは単一のスレッドを使用するという前提です (この前提とは異なり、非同期インターフェースは他にもスレッドが使用可能であれば、問題なくスレッドを追加で使用することができます)。すると、図 3 の結果になります。

図 3. 非同期の場合

図 3 には、いくつか注目すべき点があります。まず、最初の要求が終了するまでの時間は同期の場合よりも 23% 増えていますが、最後の要求が終了するまでの時間は 26% 短縮されています。しかも、それまでに使用されたスレッド数は同期の場合の 3 分の 1 です。また、要求実行時間の分布が一段と規則正しくなっているということは、ユーザーがページを受信する速度がより規則正しくなるということでもあります。最初の要求と最後の要求の処理時間の差は 80% です。同期インターフェースの場合、その差は 225% でした。

今度は、アプリケーションとデータベース・サーバーをアップグレードして処理速度を 2 倍にしたとします。表 2 に、この場合の時間配分を記載します (抽象単位での時間は表 1 での抽象単位を基準としています)。

表 2. アップグレード後のサーブレットの動作時間配分
フェーズ所要時間動作内容
11 単位サーブレット要求の情報解析
24 単位ローカル・データベース・トランザクション
31 単位データベース要求結果の処理とリモート呼び出しの準備
416 単位Web サービスによるリモート・サーバーの呼び出し
52 単位応答の作成
Total:24 単位

ご覧のように、要求処理時間の合計は 24 単位で、以前の要求所要時間の約 4 分の 3 となっています。

図 4 に、ビジネス・ロジック、データベース、Web サービスでの新しい時間配分を示します。

図 4. アップグレード後のステップ間での時間配分
アップグレード後のステップ間での時間配分

図 5 に、同期処理後の結果を示します。この図から、実行時間の合計は約 25% 短縮されていることがわかりますが、ステップの分布パターンにはそれほどの変化はありません。また、サーブレット・スレッドの待機状態はさらに長くなっています。

図 5. アップグレード後の同期の場合

クリックして大きなイメージを見る

図 5. アップグレード後の同期の場合

図 6 は、非同期 API で処理した場合の結果です。

図 6. アップグレード後の非同期の場合

非同期の場合、非常に興味深い結果となりました。データベースとアプリケーション・サーバーのパフォーマンス向上により、処理に要する時間が一段と改善されています。時間の分布はアップグレード前よりも均一で、もっとも長い要求処理時間ともっとも短い要求処理時間の差はわずか 57% しかありません。処理時間の合計 (最後の要求が準備できた時点) はアップグレードする前の 57% です。同期の場合の 75% と比べると、これは顕著な改善です。最後の要求 (要求 9) が完了するまでの時間は同期の場合より 40% 短縮され、最初の要求については同期の場合より 14% 増えているだけにすぎません。その上、非同期の場合はさらに多くの並行 Web サービスの操作を実行することができます。同期の場合、サーブレット・スレッド・プールのスレッド数によって制約されるため、ここまでの並列性は実現することができません。Web サービスがこれより多くの要求を処理できたとしても、サーブレットがアクティブになるのが追いつかないため、要求を送信することができないのです。

実際のテスト結果が、非同期アプリケーションのほうがスケーラビリティーに優れ、過負荷状態をより円滑に処理できることを裏付けています。レイテンシーは解決するのが非常に困難な問題で、これに関してはムーアの法則 (「参考文献」を参照) もあまり期待できません。最近のコンピューティングにおける多くの改善は必要な帯域幅を増やすためのもので、レイテンシーには変わりがないか、場合によってはレイテシーが悪化することさえあります。このような理由から、開発者たちは現在、アプリケーション・サーバーに非同期インターフェースを組み込もうと努力しているわけです。

非同期システムの実装方法には多くのオプションが用意されていますが、デファクト・スタンダードとして確立されているパターンは 1 つとしてありません。それぞれの手法に利点と欠点があり、さらに状況によってもその効果は変わります。この記事の残りの部分では、Java プラットフォームを使用して非同期イベント駆動型アプリケーションを作成するための機構を、その利点と欠点を含めて概説します。


一般的なソリューション

臨機応変な並行性と NIO

Java 言語には Java 1.4 からノンブロッキング・ネットワーク I/O API (java.nio.*) が備わっています。さらに Java SE 5 からは標準の並行性ユーティリティー (java.util.concurrent.*) も改良されています。ノンブロッキング I/O (NIO) と並行性により、開発者は利用可能な API とフレームワークを使用して膨大な数の同時接続をサポートするアプリケーションを実装できるようになっています。

しかし、これらの NIO API はまだレベルがかなり低く、通常はパフォーマンス上の問題をその他の手段では解決できない場合にしか使用されません。NIO 選択機構は極めて低レベルの API です。そのため、この API を使ってストリーム間のコピーよりも複雑なことを行うのは至難の業です。さらに、同じ NIO セレクターを使用する独立したモジュールを作成するのも容易ではありません。そのため、NIO をラップして、この種の開発を容易にするフレームワークの開発が必要となります。

以上の理由から、NIO API が直接使用されることはめったになく、アプリケーションがより使いやすいインターフェースで NIO API をラップすることは珍しくありません。NIO API は大掛かりな事態には役立つものの、これを直接使用するようアプリケーション・プログラマーに強制してはいけません。

Java 5 の並行性ユーティリティーが提供する操作は NIO API よりレベルが高いので、並行性ユーティリティーを使って作成したアプリケーションでは、マルチスレッドの問題によって障害が発生する傾向が少なくなります。しかし一方で、デッドロック状態になりやすく、デバッグでその根本原因を見極めるのが難しいことには変わりありません。

Java プラットフォームでの非同期のやりとりを一般的な方法で可能にしようという試みがいくつか行われています。いずれの試みもメッセージ・パッシングによる通信モデルをベースとしたものです。その多くはアクター・モデルのバリエーションを使ってオブジェクトを定義していますが、ユーザビリティー、利用可能なライブラリー、そして手法という点ではフレームワークによって大きく異なります。これらのプロジェクトの Web サイトおよび関連情報へのリンクは、「参考文献」を参照してください。

SEDA

SEDA (Staged Event-Driven Architecture: ステージ状イベント駆動型アーキテクチャー) は、非同期プログラミングとオートノミック・コンピューティングの概念を組み合わせた興味深いフレームワークです。SEDA は、J2SE 1.4 に導入された Java NIO API でとりわけ力が入れられました。このプロジェクト自体は打ち切られましたが、SEDA は Java アプリケーションのスケーラビリティーと適応性に新たなベンチマークを設定し、非同期 API に関するその概念は他のプロジェクトに影響を与えています。

非同期と同期の API 設計を組み合わせることを目指す SEDA は、興味深い結果をもたらします。このフレームワークの特徴は、臨機応変な並行性があるというよりは、極めてユーザービリティーが高いことにありますが、ユーザーの心をつかむまでには至っていません。

SEDA では、1 つのアプリケーションが複数のステージに分割され、それぞれのステージが複数のスレッドを持つコンポーネントとなります。要求はいずれかのステージに送られ、そこで処理されます。各ステージは、そのキャパシティーを以下の方法で調整することができます。

  • 使用するスレッドの数を負荷に応じて増減します。これにより、実際の使用量に応じてコンポーネント単位で動的にサーバーを適応させることが可能になります。つまり、コンポーネントで使用量が急激に増加すると追加のスレッドが割り振られ、コンポーネントがアイドル状態になるとスレッドの数が減らされます。
  • 振る舞いを負荷に応じて変更します。例えば、負荷に応じて単純化したページを生成することも可能です。単純化したページでは、画像を使用しなかったり、含まれるスクリプトの数を減らしたり、そして必須ではない機能を無効にしたりすることができます。ユーザーは引き続きアプリケーションを使用できますが、生成される要求数とトラフィック量は少なくなります。
  • そのステージに要求を送ろうとするステージをブロックしたり、あるいは要求を単純に受け付けないようにします。

上記にリストした最初の 2 つは、オートノミック・オンピューティングの概念を巧妙に適用した素晴らしい概念です。その一方、3 つ目の概念はこのフレームワークが普及しなかった理由の一端です。アプリケーションの設計段階でよくよく注意しない限りデッドロックのリスクを増やし、障害点をもたらすことになるからです。このフレームワークが使いにくい理由としては、他にも以下の点が挙げられます。

  • ステージはかなり大まかに分けられたコンポーネントです。ステージの一例にはネットワーク・インターフェースと HTTP サポートがありますが、このステージではネットワーク層を 1 つの単位として扱うため、一部のクライアントの帯域幅が制限されているなどといった問題を解決するのは困難です。
  • 非同期呼び出しの結果を返す簡単な手段がありません。結果は単にステージに送られるだけで、関連する操作の状態の検出はそのステージに任されます。
  • 現在使用できる Java ライブラリーのほとんどは同期ライブラリーです。このフレームワークは同期コードを非同期コードから一貫した方法で分離しようとしないため、誤ってステージ全体をブロックしてしまうコードを作成しがちだという危険があります。

SEDA プロジェクトの概念実装としてもっとも広く使われているのは、おそらく Apache MINA フレームワークでしょう (「参考文献」を参照)。また、この概念は OSFlash.org の Red5 ストリーミング・サーバーや Apache Directory Project、そして Jive Software Openfire XMPP Server の実装にも用いられています。

E プログラミング言語

厳密には、E プログラミング言語はフレームワークではなく、動的に型付けされた関数型プログラミング言語です。セキュアな分散コンピューティングを行うことを重点としているこの言語は、非同期プログラミング用の興味深い構成要素も提供しています。E プログラミング言語は非同期プログラミングの分野では Joule 言語と Concurrent Prolog 言語を継承していると言われていますが、その並行性サポートと全体的な構文は、Java 言語、JavaScript、C# などの主要なプログラミング言語の使用経験を持つプログラマーにとって自然で使いやすいものとなっています。

E 言語は現在、Java および Common-Lisp で実装されています。Java アプリケーションから使用することは可能ですが、過酷な使用に耐える最近のサーバー・サイドのアプリケーションに導入する際にはいくつかの障壁があります。その問題のほとんどは開発の初期段階に起因するもので、おそらく後から修正されることになります。それ以外の問題については E 言語の動的性質が原因ですが、これらの問題のほとんどは E 言語が提供する並行性の拡張機能とは関係ありません。

E 言語には、非同期プログラミングをサポートする以下の中核的な言語構成要素があります。

  • vat はオブジェクトのコンテナーです。すべてのオブジェクトはある特定の vat のコンテキスト内で有効で、他の vat から同期アクセスすることはできません。
  • promise は、非同期操作の結果を表す変数です。最初は未確定状態 (unresolved state) で、つまり操作がまだ終了していないことを意味します。操作が完了するとある値に確定 (resolve) するか、あるいは失敗としてスマッシュ (smash) されます。
  • すべてのオブジェクトはメッセージを受信することが可能で、ローカル側で呼び出すことができます。ローカル・オブジェクトは、即時呼び出し操作によって同期で呼び出されることも、最後に行われる送信操作によって非同期で呼び出されることもあります。リモート・オブジェクトについては、最後の送信操作でしか呼び出すことができません。最後に行われる呼び出しによって promise が作成されます。即時呼び出しには . 演算子、最後に行われる呼び出しには <- が使用されます。
  • promise は明示的に作成することも可能です。その場合には、他の vat へ渡すことのできるリゾルバー (resolver) オブジェクトへの参照を指定します。リゾルバー・オブジェクトには、resolvesmash の 2 つのメソッドがあります。
  • when 演算子では、promise の resolve または smash 処理が行われるときにコードを呼び出すことができます。when 演算子に含まれるコードはクロージャーとして扱われ、エンクロージング・スコープから定義にアクセスするときに実行されます。これは、匿名の内部 Java クラスがメソッド・スコープ定義にアクセスする仕組みと同様です。

以上の数少ない構成要素によって、非同期コンポーネントを容易に作成できる、驚くほど強力でユーザービリティーの高いシステムが実現します。実動環境で使用しないとしても、E 言語は複雑な並行性の問題をプロトタイプ化するのに役立ちます。この言語はメッセージ・パッシングの規則を強制し、並行性の問題に対処するのに便利な構文を提供するからです。また、E 言語の演算子は何も特別なものではないので、結果的なコードは元のコードが持つ簡潔さと単純さに欠けることになるかもしれませんが、他のプログラミング言語でエミュレートすることができます。

E 言語は非同期プログラミングのユーザビリティーの水準を引き上げます。この言語での並行性サポートは他の言語の機能とはまったく異っており、既存の言語に組み込むことも可能です。E 言語の機能については、Squeak、Python、Erlang の開発との関連で現在検討が進んでいるところで、C# のイテレーターといった比較的ドメイン固有の言語機能よりも実用性に優れたものになるはずです。

AsyncObjects フレームワーク

AsyncObjects フレームワーク・プロジェクトが焦点としているのは、ピュア Java コードでユーザビリティーの高い非同期コンポーネント・フレームワークを作成することです。このフレームワークは SEDA と E プログラミング言語の結合を試みるもので、E 言語のように基本的な並行性機構を提供するとともに、SEDA と同じく同期 Java API との統合機構を提供します。このフレームワークの最初のプロトタイプ・バージョンは 2002年にリリースされました。その後、開発はほとんど進んでいませんでしたが、最近になってこのプロジェクトの取り組みが再開されています。E 言語によって、非同期プログラミングをいかに使いやすくできるかが証明されたことから、このフレームワークではピュア Java コードはそのままに最大限のユーザビリティーを達成するという目標が設定されました。

SEDA の場合と同様、アプリケーションは複数のイベント・ループに分割されますが、このプロジェクトには SEDA のような自己管理機能はまだ実装されていません。SEDA とは異なり、このプロジェクトでは I/O に対して単純な負荷管理機構を使用します。コンポーネントは SEDA よりもはるかにきめ細かく分けられ、promise を使用して操作の結果を受信するようになっているためです。

このフレームワークは E プログラミング言語と同じ概念である、非同期コンポーネント、vat、そして promise の概念を実装します。ピュア Java コードには新しい演算子を導入できないため、任意のオブジェクトを非同期コンポーネントにすることはできません。そのため、実装では特定の基本クラスを継承しなければなりませんが、それにはフレームワークが実装する非同期インターフェースが必要です。フレームワークが提供するこの非同期インターフェースの実装がコンポーネントの vat にメッセージを送信し、vat が後でそのメッセージをコンポーネントに送ります。

現行バージョン (0.3.2) のフレームワークは Java 5 に対応しており、Generics をサポートします。現行のプラットフォームに Java NIO を使用できる場合には、Java NIO が使用されます。ただし、フレームワークを単純なソケットに戻すことも可能です。

このフレームワークの最大の問題は、同期 Java API との統合が困難なことから、クラス・ライブラリーが充実していないことです。現時点ではネットワーク I/O ライブラリーしか実装されていません。しかし、この後説明する Axis2 での非同期 Web サービスや Tomcat 6 での Comet Servlet などといったこの分野での最近の改善によって (サーブレット固有、または I/O 固有の API を参照)、同期 Java API との統合は簡易化されるはずです。

Waterken の ref_send

Waterken の ref_send フレームワークも、E 言語の概念を Java プログラミングで実装しようという試みです。このフレームワークの実装には、主に Joe-E という Java 言語のサブセットが使用されます。

このライブラリーは、最後に行われる (操作の) 呼び出しをサポートします。ただし、このサポートは AsyncObjects のサポートほどには自動化されていない感があります。また、現行バージョンのフレームワークでのスレッド・セイフティーにも問題があります。

リリースされているのは中核となるクラスとちょっとしたサンプルだけで、重要なアプリケーションやクラス・ライブラリーはありません。そのため、規模を大きくしたときにこのフレームワークの概念がどれだけ有効であるかはまだ定かではありません。フレームワークの作成者たちは完全な Web サーバーの実装が完了し、近日中にリリースされる予定だと言っているので、その際に改めてこのフレームワークを検討してみると面白いかもしれません。

Frugal Mobile Objects

Frugal Mobile Objects は、アクター・モデルをベースにしたもう 1 つのフレームワークで、対象としているのは Java ME CLDC 1.1 などのリソースが制約された環境です。このフレームワークは興味深い設計パターンによって、インターフェースをかなり単純に維持しつつも、リソースの使用量を減らします。

このフレームワークは、アプリケーションがパフォーマンスとスケーラビリティーの問題に直面したときに、リソースが制約された環境でさえも非同期設計によるメリットがあることを実証します。

フレームワークが提供する API はかなり複雑なように見えますが、フレームワークが対象とする環境の制約を考えれば、それもうなずけます。

Scala アクター

Java プラットフォームのプログラミング言語には、Scala もあります。この言語が提供するのは Java 機能のスーパーセットですが、構文はやや異なります。通常の Java プログラミング言語と比べると、この言語はユーザビリティーに関する機能がいくつか強化されているためです。

興味深い機能の 1 つは、Erlang プログラミング言語に倣ってモデル化されたアンカー・ベースの並行性サポートです。設計はまだ確定されていないようですが、この機能は比較的使用しやすく、言語構文でサポートされています。しかしながら、Scala による Erlang 的な並行性サポートは、E 言語の並行性サポートと比べるとユーザビリティーと自動化の点でいくらか劣ります。

Scala モデルではすべてのメッセージで呼び出し側への参照が渡されることから、このモデルにはセキュリティー上の問題も伴います。呼び出されたコンポーネントが値を返すだけでなく、呼び出し側コンポーネントのすべての操作を呼び出すことが可能なためです。この点に関しては、E 言語の promise モデルのほうが Scala モデルよりも細分度に優れています。ブロックしているコードと通信するための機構は、まだ完全には開発されていません。

Scala のメリットは、JVM バイト・コードにコンパイルされるという点です。そのため、理論的にはパフォーマンスを損なうことなく Java SE および Java EE アプリケーションで使用することができます。ただし商用で使用するのにふさわしいかどうかは別の問題です。Scala の IDE サポートは限られているため、Java 言語のようにはベンダーの支持を得られないからです。したがって、プロトタイプのような短期間のプロジェクトには注目すべきプラットフォームかもしれませんが、長期間続くことが見込まれるプロジェクトに使用するには危険があります。


サーブレット固有、または I/O 固有の API

これまで説明した問題は、特にサーブレット、Web サービス、そして汎用 I/O のレベルでは深刻なので、いくつかのプロジェクトではこの 3 つのレベルで問題に対処するためのソリューションを提案しています。しかしこれらのソリューションの最大の欠点は、限られたカテゴリーのアプリケーションだけしか解決しようとしていないことです。非同期サーブレットを作成できたとしても、ローカル・リソースとリモート・リソースを非同期で呼び出すことができなければほとんど意味がありません。また、非同期モデルとビジネス・コードを作成可能であることも必須です。さらに、提案されたソリューションのユーザビリティーが一般的なソリューションのユーザビリティーに劣るという問題もよくあります。

その一方、これらの試みは非同期コンポーネントの実装に関わる問題を認識するという点では注目に値します。プロジェクトの Web サイトおよび関連情報へのリンクは、「参考文献」を参照してください。

JSR 203 (NIO.2)

JSR 203 は NIO API の改訂版です。この記事を書いている時点ではまだ初期のドラフト段階なので、開発プロセスで大幅な変更が行われる可能性があります。この API は Java 7 に組み込まれることを目標としています。

JSR 203 では非同期チャネルという概念を導入しています。JSR 203 は多くのプログラマーの悩みの種に対処する目的で設計されていますが、API に関しては依然として低レベルのままのようです。今までのバージョンに欠けていた非同期のファイル入出力 API をついに導入した JSR 203 では、IoFuture および CompletionHandler の概念によって他のフレームワークのクラスが使いやすくなっています。概して、新しい非同期 NIO API のほうが前世代の API によるセレクター・ベースのものよりユーザビリティーに優れており、単純なタスクにはカスタム・ラッパーを作成しなくても直接使用することができます。

一方、この JSR の大きな欠点は、ファイル入出力およびソケット入出力にかなり特定されていることです。それより上位の非同期コンポーネントを作成するためのビルティング・ブロックは提供されていません。上位レベルのクラスを作成することは可能ですが、同じことをするにしてもクラス固有の手段を提供する必要があります。しかし Java 言語での非同期コンポーネントの開発には標準の方法がまだないことを考えると、これは技術的に正しい判断だと思われます。

Glassfish Grizzly NIO

SEDA フレームワークのサポートと同様の Glassfish Grizzly NIO サポートは、SEDA での問題も同じくほとんど引き継いでいます。ただし、このサポートがより重点を置いているのは I/O タスクです。提供されている API は通常の NIO API より上のレベルですが、扱いにくいという点では変わりありません。

Jetty 6 の Continuations

Jetty Continuations は従来とはかなり異なった手法で、クイック・ハックとも呼べるほどです。例えばサーブレットが Continuation オブジェクトを要求し、タイムアウトを指定して suspend() メソッドを呼び出した場合、この操作は例外をスローします。その後に再開操作を呼び出すこともできますが、再開操作が呼び出されなくても指定された時間が過ぎると Continuation オブジェクトが自動的に再開します。

このように、Jetty では同期しているように見える API を非同期の動作で実装しようと試みていますが、この振る舞いはクライアントの期待を裏切ることになります。サーブレットは suspend() が呼び出された時点ではなく、メソッドの開始時に再開するからです。

Apache Tomcat 6 の Comet API

Tomcat のComet API は、Comet がやりとりを行うパターンをサポートするだけのために設計されています。サーブレット・エンジンはサーブレットにその状態遷移に関する情報、そしてデータの読み取りが可能かどうかを通知します。この手法は Jetty で使用している手法より理にかなっていてわかりやすいものです。この手法では従来の同期 API を使用してストリームの書き込み/読み取りを行います。このような実装方法では、API を慎重に使えば API によるブロックは発生しません。

JAX WS 2.0 および Apache Axis2 の非同期 Web サービス・クライアント API

JAX WS 2.0 と Axis2 では、Web サービスのノンブロッキング呼び出しの API をサポートしています。Web サービスの操作が終了すると指定されたリスナーに Web サービス・エンジンから通知が送られるため、Web サービスの使用法に新たな可能性がもたらされます。これは、Web クライアントからの使用する場合にも言えることです。1 つのサーブレットから複数の個別の Web サービスが呼び出されたとしても、呼び出しは並行して行われるので、クライアントでの全体的な遅延時間は短縮されます。


まとめ

非同期 Java コンポーネントの必要性が認識された今、非同期アプリケーションの分野では活発な開発が進んでいます。少なくとも、開発者にとってとりわけ頭痛の種であるサーブレットついては主要なオープン・ソースのサーブレット・エンジン (Tomcat および Jetty) が何らかのサポートを提供するようになっています。Java ライブラリーも非同期インターフェースを提供し始めるようになっていますが、これらのインターフェースには共通のテーマがありません。そのためスレッド管理などの問題がインターフェース間に互換性を持たせることを難しくしています。そこで必要とされているのが、さまざまな関係者が提供する多数の非同期コンポーネントを収容できるコンテナーです。

現在ユーザーには、異なる状況でそれぞれに利点と欠点を持つ多くの選択肢が残されています。Apache MINA はよく使われるネットワーク・プロトコルをそのままサポートするライブラリーの一例なので、これらのプロトコルが必要な場合には、このライブラリーを選択するのがふさわしいでしょう。Apache Tomcat 6 は Comet がやりとりを行うパターンを十分にサポートしており、非同期のやりとりがこのパターンに限られている場合には魅力的な選択肢です。一方、アプリケーションを一から作成していて、既存のライブラリーがそれほど役に立たないことがわかっている場合には、さまざまな使いやすいインターフェースを使用できる AsyncObjects フレームワークがお勧めです。このフレームワークは、既存の非同期コンポーネント・ライブラリーのラッパーを作成するのにも役立つかもしれません。

今や、Java 言語に共通の非同期プログラミング・フレームワークを作り出すことに重点を置いた JSR を作成する段階にきています。そのような JSR が作成された後には、既存の非同期コンポーネントをこのフレームワークに統合し、そして既存の同期インターフェースの非同期バージョンを作成するという長い道のりが続きます。その道のりを一歩一歩進む上でエンタープライズ Java アプリケーションのスケーラビリティーは改善され、次に待ち受けている難題に取り組めるようになるはずです。増え続けるインターネット人口、そして日々の活動に広がり続けているネットワーク・サービスが今後、そうした難題の数々をもたらすことは間違いありません。

developerWorks の Ajax リソース・センター

Ajax Resource Center にアクセスしてください。ここは、無料のツール、コード、そして Ajax アプリケーションの開発に関する情報などが用意されたワンストップ・ショップです。また、Ajax のエキスパートであるJack Herrington がホストする活発な Ajax コミュニティー・フォーラムは、あなたが今まさに探している答えを持っているかもしれない開発者仲間と交流する手段となります。

参考文献

コメント

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=Web development, Java technology, XML
ArticleID=272948
ArticleTitle=Java EE と Web 2.0 との出会い
publish-date=11062007