IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  WebSphere  >

WebSphere eXtreme Scaleを使ったコンプレックス・ビジネス・イベント処理: パート1 WebSphere Business Eventsの負荷を軽減する

developerWorks
ページオプション
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
542KB (28 ページ)

Adobe® Reader® が必要

JavaScript を要するドキュメントオプションは表示されません

議論する

ダウンロード

原文はこちら

原文はこちら


レベル: 中級

Daniel McGinnes, パフォーマンス・スペシャリスト, IBM

2008年 10月 29日

2パートで構成されるこのシリーズでは、コンプレックス・ビジネス・イベント処理を行う際に、パフォーマンスとスケーラビィリティーを改善するために、IBM® WebSphere® eXtreme Scaleがどのように活用できるかということを示します。パート1では、交通量のモニタリングというシナリオを紹介し、スタンドアロン・サーバー構成のオブジェクト・グリッドを使って、シナリオがどのように実現できるかを示します。eXtreme Scaleは、高ボリュームの生イベントをフィルターするアプリケーションを動かすために使用されます。フィルタリング・アプリケーションは、Business Eventsの負荷を劇的に軽減します。パート2では、この構成に加えて、分散オブジェクト・グリッドを使用することにより、ビジネス・イベントを、コンテキストIDに基づいてパーティションに分散させます。これにより、高可用性とスケーラビリティーが実現でき、イベントを複数のBusiness Eventsインスタンスで処理できるようになります。

概要

WebSphere Business Events(以降、Business Events)は、イベントのパターンに基づき、ビジネス・イベントを検出、評価、反応することを可能にします。ビジネス・ユーザーは、ビジネス・イベントを定義・管理することにより、タイムリーで適切なアクションをとることができるようになります。また、ビジネス・ユーザーによる、コードレス・インプリメンテーションにより、IT部門による開発やインプリメンテーションが不要となり、コストも削減できます。一方、これらのコンプレックス・ビジネス・イベント処理は、CPUに依存するため、高いスケーラビリティーのソリューションが必要となります。

2パートで構成されるこのシリーズでは、WebSphere eXtreme Scale (以降、eXtreme Scale)が、多量のイベントに対してコンプレックス処理が必要な状況で、いかに、パフォーマンスとスケーラビィリティーを改善するかについて示します。パート1では、RFIDベースの交通量モニタリング・システムからのイベントを処理するために、スタンドアロン・サーバー構成のオブジェクト・グリッドを使用します。eXtreme Scale上のプリ・フィルタリング・アプリケーションは、Business Eventsで処理する必要のあるイベントの量を劇的に削減します。パート2では、この構成に加えて分散オブジェクト・グリッドを使用し、コンテキストIDに基づき、イベントを分散させます。この構成により、イベントは複数のBusiness Eventsインスタンスで処理することができるようになり、スケーラビリティーと可用性が向上します。

交通渋滞警告シナリオ

例として扱うシナリオは、自動車に取り付けられたRFIDタグに基づく、交通量管制システムです。RFID技術の一般的な使い方にならい、自動車にRFIDタグが取り付けられ、RFIDセンサーが道路の0.5マイルごとに設置されるとします。自動車がRFIDセンサーを通過する度に、イベント処理システムにイベントが送られます。これにより、イベント処理システムは、道路のそれぞれの場所での、それぞれの自動車の速度を計算することができます。システムが、道路の特定の区域で渋滞のパターンを検出すると、ハイウェイ・パトロールに対して、調査のための警告を出すことや、自動的に道路の警告表示板に表示することができます。このシナリオでは、イベント処理システムに対して、多量のイベントが送られることになります。イベント処理システムには、いくつかの複雑なイベント処理も要求されます。例えば、ただ1台の自動車の速度低下に対しては、警告を出すべきではありません。(その自動車は、故障したか、単に停車しただけかもしれません。) ある時間内での、複数の自動車の速度低下の発生を検出する必要があります。また、道路局がすでに認識している交通事故の場所なども、考慮に入れる必要があります。


図1. 交通渋滞警告シナリオ
図1. 交通渋滞警告シナリオ

ソリューション・アーキテクチャー

ソリューションのデザインに影響を与える2つの大きな要件:

  • 多量のイベントを処理する能力
  • コンプレックス・イベント処理に対応する能力

Business Events V6.1を使用すると、コンプレックス・イベント処理のロジックを、最小限の開発時間で、定義することができます。今回のイベント処理システムに送られてくるイベントは、自動車の速度では無く、ある地点を通過した時刻のみを含むという点を思い出してください。イベント処理システムは、それぞれのRFIDの特定の地点での時刻を記憶しておき、次のイベントから、速度を計算する必要があります。Business Eventsは、コンプレックス・イベントを処理するように設計されていますが、多量のデータを保管されるようにはできていません。従って、Business Eventsの前段に、イベントのプリ・プロセスのための層を設け、それぞれの地点での速度を計算し、そのイベントをBusiness Eventsに転送するという構成が適切と考えられます。

eXtreme Scale V6.1はオブジェクト・グリッドと呼ばれるコンポーネントを持っています。オブジェクト・グリッドは、多量のデータをメモリー上に保管し、データに非常に効率的にアクセスする方法を提供します。さらに、データのパーティショニングとレプリケーションの機能を提供し、スケーラビリティーを改善し高可用性を実現します。これらの理由から、ある地点の通過時刻を保管し、イベントを受け取った時点ですばやくその地点の速度を計算するために、オブジェクト・グリッドを活用することとします。Business Eventsから、それぞれの地点での速度を計算するという必要性を取り除きましたが、多量のイベントを送信するという点は残っています。それは、単一のBusiness Eventsが処理できる範囲を超えるイベントの量である可能性があります。Business Events V6.1では、簡単にクラスター構成をとることができません。

デザイン上の制限を改めて挙げると以下の通りです。

  • 地点と速度を含む多量のイベントがあります。
  • 閾値以下の速度のイベントを検出するために、フィルタリングする必要があります。
  • すでに問題が知られている地点のイベントかどうか確認する必要があります。

シナリオを分析すると、大多数のイベントは、閾値以上の速度と考えることができます。もし、イベントが閾値以上の速度を含む場合、そのイベントには、それ以上の処理をする必要はありません。一方、閾値以下の速度であった場合、それが、本当に渋滞なのか、単なる例外事象なのか、既知の問題なのかを確認するために、コンプレックス・イベント処理を適用する必要があります。速度が、閾値を超えているかどうかの確認は、非常に単純で、コンプレックス・イベント処理を必要としません。従って、この確認については、eXtreme Scale上のアプリケーションで行うことができます。これにより、Business Events上での、大多数のイベントの処理を避けることができます。このことにより、イベント処理システムのパフォーマンスが劇的に向上することが期待されます。

もう1つのデザイン上の判断は、eXtreme Scaleのアプリケーション上で、どのように初期フィルタリングを行うかということです。単純な式「if」を使用することもできます。この方法は効率的ですが、閾値の変更がアプリケーション全体に影響を及ぼします。さらに、入力イベントを処理したスレッドが、必要な場合は、Business Eventsに対する出力イベントの構築と送信まで行うということを意味します。eXtreme ScaleはFIFOキューを使用して、アプリケーション間でデータをやりとりする効率的な方法を提供します。詳細は、「アプリケーションとフィルターの作成」を参照してください。この仕組みにより、アプリケーションとフィルターを効果的に分離することができます。ワーク・アイテムをフィルターに渡すという方法により、データを分散させ、オブジェクト・グリッド・クラスタリングの恩恵を得ることができるようになります。このシリーズのパート2では、分散オブジェクト・グリッドを使用するために、アプリケーションを変更し、スケーラビリティーの向上と高可用性を実現する方法を示します。


図2. 交通渋滞警告ソリューション・アーキテクチャー
図2. 交通渋滞警告ソリューション・アーキテクチャー

上に示したように、Business EventsとeXtreme Scaleは、別のWebSphere Application Server Network Deployment (以降、Application Server)インスタンスで稼働します。 Business EventsとeXtreme Scaleを同じApplication Serverインスタンス上にディプロイすることもできます。しかし、ベスト・プラクティスに従い、それらは、別のApplication Serverで動かすこととします。イベント処理部分から、アプリケーションを分離するソリューションには、2つの利点があります。

  • Application ServerとBusiness Eventsは、全体のITソリューションの中で、別のアプリケーションのために使用することができます。それらを分離することにより、一方のサーバーが他のサーバーに影響を与えるという問題の発生を避けることができます。
  • サーバーは別々のハードウェアで実行することができ、CPU能力の増強にも対応しやすくなります。

既に述べた通り、パート2では、位置に基づいてリクエストを分散させるために、オブジェクト・グリッドをどのように使用するかを示します。それぞれのパーティションは、リクエストを、異なるBusiness Eventsサーバーに転送します。それぞれのイベントの位置は常に同じパーティションに存在し、そして、同じBusiness Eventsインスタンスに送られます。この仕組みにより、コンプレックス・イベントを処理するために使用できるBusiness Eventsインスタンスの数をスケール・アップする方法が提供されます。

製品のインストールと構成

アプリケーションの作成と実行のために、以下のソフトウェアレベルを使用します。

  • IBM Rational Application Developer V7.0.0.2 (hereafter referred to as Application Developer)
  • WebSphere Business Events V6.1 PK66053適用済み。Business Eventsのインストール時に、WebSphere Application Server V6.1.0.15がインストールされます。
  • IBM DB2 V9.5
  • WebSphere eXtreme Scale V6.1.0.2 PK7016適用済み。(前提として、WebSphere Application Serverのインストールが必要です。ここでは、WebSphere Application Server V6.1.0.17をスタンドアロン構成でインストールしました。)

WebSphere Business Events V6.1のインストール

今回の環境では、デフォルトの設定が適切なため、インストールの中では、"Default install set"を使用します。データベース・サーバーとして何を使用するか選択する部分があります。実運用環境では、データベース・サーバーとして、IBM DB2 V9.5を使用することが推奨されます。Business Events V6.1のインストールの詳細は、「リソース」を参照してください。

WebSphere eXtreme Scale V6.1のインストール

eXtreme Scaleをインストールするためには、

  1. Application Server V6.1をスタンドアロン構成でインストールします。
  2. Application Serverに対して、最新のフィックス・パックを適用します。ここでは、フィックス・パック6.1.0.17を使用しました。
  3. Application Server V6.1をインストールした場所に、eXtreme Scale V6.1をインストールします。集中インストール・マネージャーについては、インストールしませんでした。
  4. eXtreme Scaleに対して、最新のフィックス・パックを適用します。ここでは、フィックス・パック2 (V6.1.0.2)とAPAR PK67016をインストールしました。Application ServerとeXtreme Scaleのインストール方法と、フィックス・パックについては、「リソース」を参照してください。

この時点で、Business Events V6.1とeXtreme Scale V6.1の最新のメンテナンス・レベルでのインストールが完了しました。それぞれの製品に親しむために、製品に付属するサンプルとチュートリアルを試してみることができます。

コンプレックス・イベント処理ロジックの作成

イベント処理のロジックの作成をステップ・バイ・ステップでガイドするよりも、Business Events XMLファイル(TAProject.xml) を提供します。XMLファイルはTrafficAlerterExecutables.zipに含まれます。この節では、イベント処理ロジックの主な部分について説明します。

インターミィディエイト・オブジェクトとタッチポイントの作成

Business Eventsは、ビジネス・システム(以降、タッチポイント)の間のリアルタイムなイベント連携を可能にします。このシナリオでは、道路局とeXtreme Scaleサーバーがタッチポイントとなります。タッチポイントは、データを共有するためのビジネス・オブジェクトを表す、インターミィディエイト・オブジェクトを使用します。

Business Events Design Dataユーザー・インターフェースを起動し、TAProject.xmlファイルをインポートしてください。インターミィディエイト・オブジェクト・セクションには、SpeedLocという名前の1つのオブジェクトがあります。このオブジェクトは、2つのフィールド(locationとspeed)を持っています。locationとspeedはイベントから導き出されます。図3はSpeedLocインターミィディエイト・オブジェクトを示します。


図3. SpeedLoc インターミィディエイト・オブジェクト
図3. SpeedLoc インターミィディエイト・オブジェクト

5つのアクションと5つのイベントを定義した3つのタッチポイントが存在します。(図4)


図 4. タッチポイント
図 4. タッチポイント

WXSServer タッチポイントについて説明します。SpeedEventは、eXtreme Scaleプリフィルターからイベントを受け取る場所を定義します。コネクションは、Connectorと定義されています。この設定では、eXtreme Scale フィルターは直接Business Eventsのイベント・トピックに書き込みます。

TestFinishedイベントとAllEventsProcessedアクションは、テスト・アプリケーションのために使用されます。これにより、すべてのイベントがBusiness Eventsにより処理されたことが判ります。(テスト終了処理を参照) AllEventsProcessedアクションは、eXtreme Scaleサーバー上のJava Message Service (JMS)キューにアクションを書き込むために、メッセージ・キュー接続を使用します。Provider URLが、eXtreme Scaleサーバーに合うように、action propertiesを編集する必要があります。

action propertiesを編集するためには、

  1. AllEventsProcessedで右クリックし、Action Propertiesを選択します。
  2. Connectionタブをクリックします。Connectionタブ上で、Configureをクリックします。
  3. URLを編集するために、Provider...をクリックします。ポート番号は、eXtreme ScaleサーバーのBOOTSTRAP_ADDRESSポートとします。(図5)

図 5. provider URLの修正
図 5. provider URLの修正

HighwaysAgencyタッチポイントには、KnownAccidentイベントとアクション、そしてAccidentClearedイベントとアクションがあります。道路局がすでに認識している交通事故の地点について考慮する必要があることを思い出してください。これらのイベントは、道路局に対して、既知の交通事故、およびそれらの事故処理が終了したことを知らせる方法を提供します。LowSpeedAlertアクション(HighwaysAgencyの中)は、交通渋滞が発生したと判断されたときに発せられます。これは、現実のシステムでは、Webサービス呼び出しやemailとなると考えられますが、テストの容易性から、ファイルシステム・コネクションを使用します。

ファイルシステムに合うようにこのコネクターのプロパティーを編集する必要があります。

フィルターとインタラクション・セットの作成

この節では、コンプレックス・イベント処理を実現するための、フィルターとインタラクション・セットについて説明します。Business Eventsでは、フィルターはビジネス・ロジックの1ピースです。インタラクション・セットは、共通するイベント又はアクションを扱う、関連するフィルターのグループです。インタラクション・セットにより、ビジネス・ロジックをインプリメントします。

Design Dataユーザー・インターフェースを閉じ、Designユーザー・インターフェースで、TAProject.xmlファイルを開いてください。フィルター又はインタラクション・セットの定義を表示するには、プロジェクト階層のFilters又はInteractionSetsを拡張し、該当する項目を選択します。

SpeedBelow40フィルターは、速度が40以下であるかどうかをチェックします。イベントに対してプリフィルタリングを行い、eXtreme Scaleにおいてこのチェックを実施するという方針ですが、Business Eventsの中でも、このチェックを行います。もし、このチェックをここで行わない場合、プリフィルター・アプリケーションでエラーが発生した時や、正しく動作しないといったケースにおいて、間違った渋滞の警告を出してしまうという可能性が発生します。これは、「石橋を叩いて渡る」アプローチであると考えてください。


図 6. SpeedBelow40フィルター
図 6. SpeedBelow40フィルター

Not known problemフィルターは、イベントが既知の問題では無いことを保証します。これは、KnownAccidentEventの発生をチェックします。もし、これらのイベントが存在した場合は、このフィルターは、AccidentClearedEventによりイベントがキャンセルされていないかどうかチェックします。


図 7. Not known problemフィルター
図 7. Not known problemフィルター

MultipleLowSpeedsフィルターは、一定の時間内に、LowSpeedアクションが、少なくとも9回発生することをチェックします。また、5分以内に、LowSpeedAlertが発生していないこともチェックします。これは、LowSpeedAlertは、5分おきに1回しか送信されないということを意味します。これにより、問題が発生した際に、HighwaysAgencyが警告で溢れてしまうことを防ぎます。


図 8. MultipleLowSpeedsフィルター
図 8. MultipleLowSpeedsフィルター

AccidentClearedとKnownAccidentインタラクション・セットは、道路局が、既知の事故及び、それらが解消されたことを、システムに知らせるために使用されます。 Not known problemフィルターで、これらのイベントの発生の回数をチェックするようになっているため、このインタラクション・セットが必要となります。このフィルターを適用するために、インタラクション・セットの中でイベントを参照する必要があります。


図 9. AccidentCleared 及び KnowAccidentインタラクション・セット
図 9. AccidentCleared 及び KnowAccidentインタラクション・セット

CheckForLowSpeedインタラクション・セットは、WXSServerタッチポイントからのSpeedEventにより起動します。フィルターは、速度が40以下であるかどうかをチェックします。もし、リクエストがこのフィルターをパスした場合、インターナル・タッチポイントに、LowSpeedEventアクションが発生します。


図 10. CheckForLowSpeedインタラクション・セット
図 10. CheckForLowSpeedインタラクション・セット

ManyLowSpeedsインタラクション・セットは、インターナル・タッチポイントでのLowSpeedアクションの複数の発生をチェックします。また、その地点で既知の問題が発生していないことをチェックします。両方のフィルターをパスした場合、HighwaysAgencyに対してLowSpeedAlertアクションを送信します。SpeedLoc.locationのコンテキスト・リレーションシップを定義していますので、インタラクション・セットとフィルターは、locationごとに評価されます。


図 11. ManyLowSpeedsインタラクション・セット
図 11. ManyLowSpeedsインタラクション・セット

TestFinishedインタラクション・セットは、Business Eventsがすべてのイベントを処理したかどうかを判断します。詳細は、「テスト終了処理」を参照してください。


図 12. TestFinishedインタラクション・セット
図 12. TestFinishedインタラクション・セット

アプリケーションとフィルターの作成

TrafficAlerterアプリケーションを作成するために、Application Developer V7.0を使用します。Application Developer及びJ2EEアプリケーションの作成については慣れ親しんでいると仮定します。Application Developerに、TrafficAlerterPI.zip (この記事と共に提供)をインポートしてください。この節では、アプリケーションの主な部分を中心に説明します。ZIPファイルをインポートすると、以下のプロジェクトが現れます。


表1. Application DeveloperワークスペースのTraffic Alerterプロジェクト
プロジェクト名タイプ説明
TrafficAlerterEnterprise ApplicationTrafficAlerterアプリケーション。
TrafficAlerterAppClientApplication Clientイベント処理システムをテストするために負荷を発生させるEJBクライアント・アプリケーション。
TrafficAlerterClientUtility JarEJB Home及びRemoteインターフェースとスタブ。
TrafficAlerterEJBEJBリクエストを受け付け、速度を計算し、フィルタリングのためにオブジェクト・グリッドに対して速度を渡す、EJB。
TrafficAlerterFilterEnterprise ApplicationTrafficAlerterFilter アプリケーション。
TrafficAlerterFilterWebWebオブジェクト・グリッドのキューから速度を読み込み、閾値をチェックし、必要に応じてBusiness Eventsに転送する、フィルター・アプリケーション。
TrafficAlerterUtilUtility Jarオブジェクト・グリッド用のタイプなど、両方のアプリケーションで使用するクラス。

Application Developerで、オブジェクト・グリッド・アプリケーションを開発するためには、プロジェクト・ビルド・パスに、オブジェクト・グリッド・ライブラリーを追加する必要があります。TrafficAlerterEJBとTrafficAlerterFilterWebの両方のプロジェクトで、変数OBJECT_GRID_JARを参照しています。以下を行ってください。

  1. wsobjectgrid.jarファイルを、eXtreme Scaleのlibディレクトリー(例:C:\Program Files\IBM\WebSphere\AppServer\lib)から、開発環境にコピーします。例えば、C:\WXSLibディレクトリーにコピーします。Application Developerがそのファイルにアクセスできるのであれば、位置は重要ではありません。
  2. TrafficAlerterEJBプロジェクトで右クリックし、「ビルド・パス」=>「ビルド・パスの構成...」を選択します。
  3. ライブラリー」タブをクリックし、OBJECT_GRID_JARを選択し、「編集...」をクリックします。
  4. 変数...」をクリックし、「編集...」をクリックします。OBJECT_GRID_JARが、wsobjectgrid.jarファイルの位置を指すように編集します。
  5. OK」を数回クリックし、プロジェクトを再ビルドします。

オブジェクト・グリッド・アプリケーション では、様々なAPIが使用できます。ここでは、オブジェクト・グリッドを使用するためのシンプルで直感的なプログラミング・モデルを提供する、EntityManagerを使用します。

オブジェクト・グリッド・ディスクリプターXMLファイルで、オブジェクト・グリッドの設定を記述します。これは、グリッドに保管されるオブジェクトを記述する、entity.xmlファイルを参照します。今回の例では、このファイルはとてもシンプルなものですが、様々なトランザクションやアクセスのための設定を定義するためにも使用することが出来ます。オブジェクト・グリッド・ディスクリプター・ファイルは、objectGrid.xmlという名前で、TrafficAlerterFilterWebプロジェクトのWebContent/META-INFフォルダーに配置されます。


リスト1. オブジェクト・グリッド・ディスクリプターXMLファイル(objectGrid.xml)
	
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
	xmlns="http://ibm.com/ws/objectgrid/config">
   <objectGrids 
     <objectGrid name="TrafficAlerterOG" entityMetadataXMLFile="entity.xml">
        <bean id="ObjectGridEventListener" 
          className="com.ibm.ta.startup.beans.TAOGListener" /"> 
        <backingMap name="DataPacket"/>   
        <backingMap name="SpeedAtLocation"/>
     </objectGrid>
   </objectGrids>
</objectGridConfig>

ObjectGridEventListenerクラスを指定していることに注意してください。これは、オブジェクト・グリッドがアクティブになった時、TAOGListenerクラスが通知を受け取るということを意味しています。この仕組みにより、フィルター・アプリケーションが起動します。詳細については、フィルター・アプリケーションの部分で説明します。参照している、Entity.xmlファイル(リスト2.)は、オブジェクト・グリッドに保管されるオブジェクトを定義するためのものです。DataPacketとSpeedAtLocationクラスは、TrafficAlerterUtilプロジェクトに含まれます。


リスト2. エンティティー・スキーマ・ディスクリプターXMLファイル (entity.xml)
	
<?xml version="1.0" encoding="UTF-8"?">
<entity-mappings xmlns="http://ibm.com/ws/projector/config/emd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://ibm.com/ws/projector/config/emd ./emd.xsd""> 
  <description">"Entity Mapping description"</description">
  <entity class-name="com.ibm.ta.util.DataPacket" name="DataPacket" access="FIELD"">
    <description">"This is the DataPacket class"</description">
    <attributes">
    <id name="RFID" /">
    <basic name="locationId" /">
    <basic name="timeInMillis" /">
    </attributes">
  </entity">
  <entity class-name="com.ibm.ta.util.SpeedAtLocation" name="SpeedAtLocation" 
      access="FIELD"">
    <description">"Speed at a location"</description">
    <attributes">
    <id name="Id" /">
    <basic name="locationId" /">
    <basic name="speed" /">
    </attributes">
  </entity">	
</entity-mappings">

分散オブジェクト・グリッドを使用するために、objectGridDeployment.xmlファイルも必要となります。パート1では、スタンドアロン構成のeXtreme Scaleサーバー上で稼働させますが、パート2での対応を容易にすることを考慮して、ローカルでは無く、分散オブジェクト・グリッドを使用するようにします。objectGridDeployment.xmlファイルで、オブジェクト・グリッドで必要なパーティションやレプリカの数を指定します。このファイルで、numberOfPartitions=1、すなわち、パーティション数は1と指定します。リスト3はobjectGridDeployment.xmlファイルの内容を示します。


リスト3. objectGridDeployment.xmlファイル
	
<?xml version="1.0" encoding="UTF-8"?">
<deploymentPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://ibm.com/ws/objectgrid/deploymentPolicy 
 ../deploymentPolicy.xsd"
 xmlns="http://ibm.com/ws/objectgrid/deploymentPolicy">
    <objectgridDeployment objectgridName="TrafficAlerterOG">
    	<!-- Change 1 to at least the number of JVMs being started -->
        <mapSet name="mapSet" numberOfPartitions="1" minSyncReplicas="0" 
        maxSyncReplicas="0" maxAsyncReplicas="0" numInitialContainers="1">
            <map ref="DataPacket" />
            <map ref="SpeedAtLocation"/>
        </mapSet>
    </objectgridDeployment>
</deploymentPolicy>

J2EEアプリケーションでは、objectGrid.xmlとobjectGridDeployment.xmlファイルの名前と場所は重要です。XMLファイルは、正確にこの名前であり、J2EEモジュールのMETA-INFフォルダーに配置されなければなりません。オブジェクト・グリッドは、これらのファイルを見つけると、アプリケーション・サーバーを、カタログ・サービスに対して、オブジェクト・グリッド・コンテナーJVMとして登録します。その結果、クラスターに対して同じアプリケーションをディプロイできるようになり、1つのグリッドとして扱うことができます。

TrafficAlerterEJBプロジェクトのTrafficAlerterBeanはステートレス・セッションBeanです。sendDataPacketという1つのリモート・メソッドを持ち、それは、RFIDがセンサーを通過したことを検出した際に、クライアントから呼ばれます。テストを簡単にするために、複数のセンサーをシミュレートするEJBクライアント・アプリケーションを使用しますが、このメソッドは、Webサービスとして公開することも容易です。

ejbCreateメソッドの中で、オブジェクト・グリッドへの参照を得るために、ファクトリー・メソッドOGFactory.getObjectGridを呼び出します。リスト4.はOGFactoryクラスの内容を示します。


リスト4. OGFactoryクラス
	
  public class OGFactory {
    private static ObjectGrid og;
    private static ObjectGridManager ogManager;
	
    public static synchronized ObjectGrid getObjectGrid() {
      if (og == null) {initialiseOG();}
      return og;
    }
    private static synchronized void initialiseOG() {
      ogManager = ObjectGridManagerFactory.getObjectGridManager();
      try {
        ClientClusterContext context = ogManager.connect(null, null);
        og = ogManager.getObjectGrid(context,TrafficAlerterConstants.TA_OG_NAME);
      } catch (ObjectGridException e) {
        System.out.println("Error occurred connecting to ObjectGrid: " +
        e.printStackTrace();
      }
    }
  }

TA_OG_NAMEは、TrafficAlerterOGであり、オブジェクト・グリッド構成ファイルで定義したオブジェクト・グリッド名を指します。すべてのセッションbeanインスタンスが、オブジェクト・グリッドへの同じ参照を得ることを保証するために、このファクトリー・クラスを使用します。もし、それぞれのセッションbeanインスタンスが、オブジェクト・グリッドに対して、それぞれ独自の参照を取得した場合、com.ibm.websphere.objectgrid.plugins.OptimisticCollisionException例外が発生することがあります。

sendDataPacketメソッドの内容をリスト5.に示します。このメソッドは、クライアントから、データ・パケット(RFID、位置及び時刻を含む)を受け取ります。RFIDに対して速度を計算し、フィルター・アプリケーションが読み込んで処理できるように、オブジェクト・グリッドに位置と速度を保管します。


リスト5. sendDataPacketメソッド
	
  public void sendDataPacket(DataPacket data) {
1   EntityManager em = getEntityManager(); 
    em.getTransaction().begin() 
    try{
      DataPacket currentData = (DataPacket) em.find(DataPacket.class,data.RFID);
      if (currentData == null) {
2       currentData = new DataPacket();
        currentData.locationId = data.locationId;
        currentData.RFID = data.RFID;
        currentData.timeInMillis = data.timeInMillis;
        em.persist(currentData);
        em.getTransaction().commit();
      } else {
3       BigDecimal diff = new BigDecimal(data.timeInMillis - currentData.timeInMillis);
        BigDecimal timeInHours = diff.divide(millisInHour,10, RoundingMode.HALF_UP);
        BigDecimal speedBig = halfMile.divide(timeInHours, 0, RoundingMode.HALF_UP);
        int speed = speedBig.intValue();
				
4       currentData.locationId = data.locationId;
        currentData.timeInMillis = data.timeInMillis;
        em.persist(currentData);
        em.getTransaction().commit();
				

	
5       em.getTransaction().begin();
        SpeedAtLocation sp = new SpeedAtLocation();
        sp.locationId = data.locationId;
        sp.speed = speed;
        sp.Id = UUID.randomUUID().toString();
        boolean persisted = false;
6       while (! persisted){ 
          try {
            em.persist(sp);
            em.getTransaction().commit();
            persisted = true;
          } catch (EntityExistsException eee) {
            sp.Id = UUID.randomUUID().toString();
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

sendDataPacketメソッドの内容を以下に説明します。(リスト5.内の番号を見てください)

  1. オブジェクト・グリッドと通信するために、EntityManagerへの参照を必要とします。
  2. オブジェクト・グリッド内に、このRFIDのエントリーが存在しない場合、このエントリーを単に追加するだけで、戻ります。
  3. ここでは、このDataPacket内の時刻と、以前の位置で保管された時刻を基に、速度を計算します。
  4. オブジェクト・グリッドに保管された、このRFIDの位置と時刻の値を更新し、コミットします。
  5. SpeedAtLocationオブジェクトを作成し、フィルターが処理できるように、オブジェクト・グリッドに書き込みます。
  6. 生成したIDはユニークであるはずですが、もし重複している場合は、トランザクションがコミットするまで、ループします。

どのように速度を計算し、それをオブジェクト・グリッドに保管するかを説明しました。次に、TrafficAlerterFilterアプリケーションがどのように動くかを説明します。

TrafficAlerterFilterアプリケーションは、TrafficAlerterFilterWebプロジェクトに含まれます。このプロジェクトは、リスト1.で参照したTAOGListenerクラスを含みます。このクラスは、ObjectGridEventListenerをインプリメントします。すなわち、オブジェクト・グリッドが初期化されるとshardActivatedメソッドが呼ばれ、オブジェクト・グリッドが停止されると、shardDeactivateメソッドが呼ばれることを意味します。これらのメソッドは、リスト6.に示されています。


リスト6. shardActivatedとshardDeactivateメソッド (TAOGListenerクラス)
	
  public void shardActivated(ObjectGrid arg0) {
    InitialContext ic;
    try {
      ic = new InitialContext();
      WorkManager wm = (WorkManager)ic.lookup("java:comp/env/wm/WorkManager");
      for (int i = 0; i < TrafficAlerterConstants.NUM_FILTER_THREADS; i++) {
        Work taFilterWork = new TAFilterWorker(arg0);
        wm.startWork(taFilterWork);
        allWork[i] = taFilterWork;
    } catch (Exception e1) {
      e.printStackTrace();
    }		
  }
	
  public void shardDeactivate(ObjectGrid arg0) {
    try {
      for (int i = 0; i < TrafficAlerterConstants.NUM_FILTER_THREADS; i++) {
        Work taFilterWork = allWork[i];
        taFilterWork.release();
    } catch (Exception e1) {
      e.printStackTrace();
    }	
  }

オブジェクト・グリッドに対して、直接リッスンするのでは無く、shardActivatedshardDeactivateメソッドはアプリケーション・サーバーの非同期beanの機能である、ワーク・マネージャーAPIを使用します。アプリケーション・サーバーの非同期bean拡張は、異なるスレッドで作業する環境を提供します。shardActivatedメソッドは、多数のTAFilterWorkerスレッドを起動することに注目してください。この固定値は、デフォルトでは3に設定されています。リクエストの多くの割合がBusiness Eventsに送信されるような状況では、すべての作業を処理するために、複数のスレッドが必要となります。

TAFilterWorkerクラスは、オブジェクト・グリッド上で処理されるオブジェクトをリッスンしながらループしている非同期beanです。このクラスは、com.ibm.websphere.asynchbeans.Workインターフェースをインプリメントしています。すなわち、ワーク・マネージャーを使用して稼働するようにスケジュールすることが可能です。オブジェクト・グリッド上でワークを探してループするrunメソッドは、リスト7.に示します。


リスト7. TAFilterWorker.runメソッド
	
   public void run() {
     Session session = getSession();
     EntityManager em = session.getEntityManager();
     try {
1    ObjectMap map = session.getMap("SpeedAtLocation");
2    while (!appStopping.get()) {
       em.getTransaction().begin();
3      Object msgKey = map.getNextKey(2000);
4      if (msgKey != null) {
5        SpeedAtLocation sp = (SpeedAtLocation) em.find(SpeedAtLocation.class, msgKey); 
6        if (sp.locationId.equals("-1")) { 
           sendTestFinishedEvent();
         } else {
7          if (sp.speed < TrafficAlerterConstants.TA_MIN_SPEED) {
             sendEventToWBE(sp);
           }
         }
8        map.remove(msgKey); 
       }
       em.getTransaction().commit();
     }
     } catch (Exception e) {
       e.printStackTrace();
       System.out.println("Error occurred: " + e.getMessage());
     }
  }

テスト終了処理
TrafficAlerterEJBは、もう1つのリモート・メソッドとして、testFinishedを持っています。testFinishedは、すべてのテストイベントが送信された時、クライアントから呼ばれます。このメソッドは、locationが-1でspeedが-1のSpeedAtLocationオブジェクトを、sendDataPacketメソッドと同じような形で書き込みます。フィルター・アプリケーションはこの特別なlocationをチェックします。もし、-1にセットされていた場合、Business Eventsに対して、TestFinishedイベントを送信します。Business Eventsがこのイベントを受け取ると、JMSキューにメッセージを書き込むAllEventsFinishedアクションを起動します。クライアント・アプリケーションはこのキューをリッスンしています。このメッセージを受け取ることにより、すべてのイベントがフィルターを通りBusiness Eventsで処理されたということを知ることができます。アプリケーションのスループットを測定できるようにしたいために、この処理を追加しました。測定のためには、Business Eventsが、すべてのイベントの処理を終了したタイミングを知る必要があったのです。

runメソッドについて、下記に説明します。(リスト7.の番号を参照してください。)

  1. SpeedAtLocationオブジェクトを含むmapを取得します。
  2. ループを続けるために、AtomicBooleanを使用します。もし、オブジェクト・グリッドが停止すると、shardDeactivateメソッドが、このクラスのreleaseメソッドを呼び出し、appStoppingをtrueにセットします。
  3. mapからエントリーを取得します。もし、エントリーが存在しない場合は、2000ミリ秒待機します。
  4. 2000ミリ秒以内に、mapにエントリーが見つからなかった場合、getNextKeyはnullを戻します。この場合、トランザクションをコミットし、ループを再開します。
  5. mapにエントリーを見つけると、SpeedAtLocationオブジェクトを取得するために、キーを使用します。
  6. Business Eventsに、TestFinishedイベントを送信する必要があるかどうかをチェックします。「テスト終了処理」を参照してください。
  7. ここは、閾値に対して速度をチェックし、フィルタリングを行う場所です。閾値よりも低い時は、Business Eventsに対してイベントを送信します。それ以外は、何もしません。
  8. このエントリーはチェックされましたので、mapから削除します。

runメソッドは、sendEventToWBEメソッドを呼び出します。(リスト8) このメソッドは、XMLの組み立てと、メッセージの送信という、2つの追加のメソッドを呼び出します。


リスト8. sendEventToWBEメソッド
     
  private void sendEventToWBE(SpeedAtLocation sal) {
    String xmlToSend = composeXMLEvent(sal.speed, sal.locationId);
    publishEvent(xmlToSend);
  }
 

リスト9は、composeXMLEventメソッドを示します。


リスト9. composeXMLEventメソッド
     
  private String composeXMLEvent(long speed, String location) {
    StringBuilder xml = new StringBuilder();
    xml.append("<connector name=\"WXSServer\" version=\"2.2\"><
      connector-bundle name=\"SpeedEvent\" type=\"event\"><connector-object 
      name=\"SpeedEventObject\"><field name=\"speed\" type=\"Integer\">");
    xml.append(speed);
    xml.append("</field><field name=\"location\" type=\"String\">");
    xml.append(location);
    xml.append("</field></connector-object></connector-bundle>");
    xml.append("<loginfo>Low Speed detected</loginfo></connector>");
    return xml.toString();
  }
    

Business Eventsが期待するXMLイベントのフォーマットは、Business Events Design Dataユーザー・インターフェースから決めることができます。

  1. TouchpointsWXSServerを開き、SpeedEventで右クリックします。Event Propertiesを選択し、Eventタブをクリックします。(図13)
  2. ここから、Business Eventsのパケット・スキーマとサンプルをエクスポートすることができます。

図13. Business Eventsパケット・スキーマとサンプルのエクスポート
図13. Business Eventsパケット・スキーマとサンプルのエクスポート

publishEventメソッドと、それが呼び出すrecreateJMSProducerを、リスト10に示します。簡単のため、例外対応処理は省かれています。


リスト10. publishEventメソッド
     
  private void publishEvent(String xmlEvent) { 
    int retries = 0;
    while (retries < 3) {
      try {
        if (session == null) {
          recreateJMSProducer();
        }
        msg = session.createTextMessage(xmlEvent);
        msg.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
        producer.send(msg);
        return;
      } catch (JMSException e) {
        System.out.println("JMSException occurred: " + e.getMessage());
        recreateJMSProducer();
        retries++;
      } 
    } 
    System.out.println("Publish of Event to WBE failed");
  }

  private void recreateJMSProducer() {
    if (ctx == null) {
      ctx = new InitialContext();
    }
    if (cf1 == null) {
      cf1 = (ConnectionFactory) ctx.lookup("jms/WbeTopicConnectionFactory");
    }
    connection = cf1.createConnection();
    session = connection.createSession(false,javax.jms.Session.AUTO_ACKNOWLEDGE);
    if (dest == null) {
      dest = (Topic) ctx.lookup("jms/eventTopic");
    }
    producer = session.createProducer(dest);
  }
    

このメソッドは、トピックに対してメッセージをパブリッシュする、極めて一般的なJMSコードです。効率のために、JMSセッションを再利用するようにしていますが、もし、失敗した場合は、JMSリソースを再作成しています。トピックは、実際には、プログラムが稼働しているeXtreme Scaleサーバーでは無く、Business Eventsサーバー側に、存在することを思い出してください。このため、Business Eventsサーバー上のリモートJMSリソースをポイントする、ローカルJMSリソースを作成する必要があります。詳細は、「ディプロイとテスト」を参照してください。

ディプロイとテスト

開発が完了しました。次のステップは、インストールとアプリケーションのテストです。以下のステップを実行してください。

  1. Application Developerから3つのモジュールとプロパティー・ファイルをエクスポートします。
    • TrafficAlerterアプリケーションをTrafficAlerter.earファイルとしてエクスポートします。
    • TrafficAlerterFilterアプリケーションをTrafficAlerterFilter.earファイルとしてエクスポートします。
    • TrafficAlerterUtilプロジェクトをTrafficAlerterUtil.jarファイルとしてエクスポートします。
    • TrafficAlerterAppClientプロジェクトにあるtrafficAlerter.propsファイルをエクスポートします。
  2. 次に、TrafficAlerterUtil.jarファイルをeXtreme Scaleサーバーのクラス・パスに追加します。オブジェクト・グリッドは、同じアプリケーション・サーバー上の2つの異なるアプリケーションの間で共有されます。これは、グリッド内に保管されアクセスされるオブジェクトは、同じクラス・ローダーによりロードされることを保証しなければいけないということを意味します。もし、TrafficAlerterUtil.jarファイルが、それぞれのアプリケーションにパッケージされていた場合、そのクラスは、異なるクラス・ローダーによりロードされてしまいます。eXtreme Scaleの管理コンソールにおいて、「アプリケーション・サーバー」=>「サーバー1」=>「プロセス定義」=>「Java仮想マシン」を選択し、TrafficAlerterUtil.jarファイルをクラス・パスに追加してください。
  3. サーバーはデフォルトの初期と最大のヒープサイズを使用します。サーバーに対してより多くのヒープを割り当てるため、両方の設定値を1024に増やしてください。
  4. すでに触れましたように、Business Eventsのトピックとトピック接続ファクトリーをポイントする、2つのJMSリソースをeXtreme Scaleサーバー上に作成する必要があります。さらに、テスト終了処理のために使用する、JMSキューとキュー接続ファクトリーを作成する必要があります。提供されているJythonスクリプト(createJMSResources.py)を使用して、表2に一覧されているリソースを作成してください。スクリプトを実行するために、eXtreme Scaleをインストールした、binディレクトリーに移動してください。下記を実行します。
    wsadmin -lang jython -f createJMSResources.py WXS_Endpoint WBE_Endpoint.
    WXS_Endpointは、eXtreme ScaleのホストとSIB_ENDPOINT_ADDRESSポートです。WBE_Endpointは、Business EventsのSIB_ENDPOINT_ADDRESSです (例えば、localhost:7280)。

表2. 作成されるJMSリソース
JMSリソース
名前タイプ説明
WXSBusサービス統合バステスト終了処理のために使用される、JMSキューを含むバス。eXtreme Scaleサーバーは唯一のバス・メンバー。
TEST_FINISHEDSIB宛先テスト終了処理のために使用される、WXSBus上に作成されたキューの宛先。
AllEventsProcessedJMSキューTEST_FINISHED SIB宛先を参照する、JMSキュー・リソース。
AllEventsProcessedQCFJMSキュー接続ファクトリーAllEventsProcessedキューにアクセスするために使用される、JMSキュー接続ファクトリー・リソース。
WbeTopicConnectionFactoryJMSトピック接続ファクトリーフィルター・アプリケーションがBusiness Events上のイベント・トピックと接続するために使用する、JMSトピック接続ファクトリー。プロバイダー・エンドポイントは、Business EventsのSIB_ENDPOINT_ADDRESSにセットされる。
eventTopicJMSトピックフィルター・アプリケーションがBusiness Events上のイベント・トピックと接続するために使用する、JMSトピック。
  1. 管理コンソールを使用して、TrafficAlerter.earとTrafficAlerterFilter.earアプリケーションをインストールします。
  2. Business Eventsコネクターのデバッグ・ロギングを使用不可にします。デバッグ・ロギングは、コネクターのパフォーマンスに著しい影響を与えます。ログ設定をDEBUGからERRORに変更するために、Business Eventsプロパティーのユーザー・インターフェースを起動し、Full Configuratorのコネクター・セクションを表示します。下記の値を変更します。
    as.director.connectors.log4j.logger.com.aptsoft.connectors property to ERROR. 図14を参照してください。

    図14. ログ設定値をERRORに変更
    図14. ログ設定値をERRORに変更

  3. テストを実行する前に、eXtreme Scale、Business Events、Business Eventsコネクターを再起動します。

EJBクライアントを使用したテスト

TrafficAlerterアプリケーションのTrafficAlerterAppClientプロジェクトに、TrafficAlerterクライアントがパッケージされています。これは、Application Serverが提供しているlaunchClientツールを使って動かすことのできる、J2EEアプリケーション・クライアント・モジュールです。このクライアントは、DataPacketオブジェクトをフィルター・アプリケーション対して送信する、多数のセンサーをシミュレートします。これは、現実のクライアント・アプリケーションを意図したものでは無く、主な目的は、パフォーマンスをテストするために、多量のリクエストをTrafficAlerterアプリケーションに送信することです。

クライアントを実行するには、

  1. launchClientにパスが通っていることを確認してください。
  2. 以下を実行します。
    launchclient TrafficAlerter.ear -CCclasspath=TrafficAlerterUtil.jar trafficAlerter.props

プロパティー・ファイルtrafficAlerter.propsは、クライアントをどのように実行するかを決定するための、多数のプロパティーを定義しています。これらのプロパティーは表3.で説明されています。


表3. TrafficAlerterAppClientで使用されるプロパティー
名前説明
providerURLTrafficAlerter EJBをルックアップするために使用されるURL。eXtreme Scaleサーバーのホスト名とBOOTSTRAP_ADDRESSポートから成ります。
ejbURLTrafficAlerter EJBのJNDI名。通常は、デフォルト値から変更する必要はありません。
locationsそれぞれのクライアント・スレッドが繰り返す、位置の数。
numRFIDsそれぞれのクライアント・スレッドがシミュレートするRFIDの数。これは、WBERatioの倍数にセットされる必要があります。
WBERatioこの値は、Business Eventsにいくつのリクエストが送信されるかを決定します。この値が0にセットされると、すべてのリクエストは、フィルターによって除かれます。この値が1にセットされると、すべてのリクエストは、Business Eventsに転送されます。この値が2にセットされると、リクエストの半分がBusiness Eventsに送信され、残りがフィルターにより処理されます。この値が100にセットされると、100回のリクエストの内、1回のリクエストがBusiness Eventsに送信されます。この値は、numRFIDsプロパティーと関連があります。numRFIDsは、WBERatioの倍数にセットされる必要があります。
threads実行するクライアント・スレッドの数。それぞれのスレッドは同じ数のlocationとRFIDを実行します。
durationテストを実行する時間(秒)。指定した数のRFIDとlocationをすべて実行する場合は、0に設定します。

テスト結果

フィルターの効果をテストするために、2セットの測定を行いました。初めのセットのために、通常のアプリケーションとリクエストをフィルターするためにフィルターを使用しました。2番目のセットでは、すべてのリクエストがBusiness Eventsに送られるように、フィルター・アプリケーションからフィルタリング・ロジックを取り除きました。リクエストは、フィルター・アプリケーションを通して流れますが、すべてのイベントはBusiness Eventsに送られます。これは、Business Eventsが、速度が40以下かどうかの簡単なチェックを行うことを意味します。これにより、すべてのリクエストをBusiness Eventsに送信する場合に対して、eXtreme Scaleアプリケーションでのフィルタリングの効果を見ることができます。いくつかの異なるWBERatioを使いました。このパラメーターは、eXtreme Scaleサーバー上でのフィルターを使ってフィルターされるイベントの数と、コンプレックス処理が必要となるイベントの数に影響を与えます。


図15. プリフィルター・アプリケーションがある場合と無い場合の結果
図15. プリフィルター・アプリケーションがある場合と無い場合の結果

この結果は、クライアント、eXtreme Scaleサーバー、Business EventsサーバーとDB2を同じWindows®マシン上で稼働させて、得たものです。これは、最適化された構成ではありませんが、セットアップが最も簡単です。それぞれのケースで、CPU使用率が100%に近くなるように、十分なスレッド数を使用しました。結果は、eXtreme Scaleプリフィルターでフィルターされるイベントの割合が高いとき、eXtreme Scaleプリフィルターを使う効果が高いことを示しています。全てのリクエストがコンプレックス処理を必要とする場合(WBERatio=1の場合)、eXtreme Scaleプリフィルターを使用する効果はありません。

まとめ

この記事では、eXtreme Scaleでの単純なフィルタリング・アプリケーションが、Business Eventsでの多量のイベントのコンプレックス処理が要求される状況で、いかにパフォーマンスを改善するかを説明しました。このシリーズのパート2では、eXtreme ScaleとBusiness Eventsインスタンスの数をスタンドアロン・サーバーから、増やす必要がある場合に、オブジェクト・グリッド・パーティショニングの利点を生かすために、このアプリケーションを、どのように拡張できるかを説明します。図16は、このソリューションを図示したものです。


図16. パート2のソリューション・アーキテクチャー
図16. パート2のソリューション・アーキテクチャー




上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
ソース・コードを含むプロジェクト交換ファイルTrafficAlerterPI.zip53KBHTTP
EARファイルとBusiness Eventsプロジェクト・ファイルTrafficAlerterExecutables.zip70KBHTTP
Jython wsadmin スクリプトcreateJMSResources.zip3KBHTTP
ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために

議論するために


著者について

Photo of Daniel McGinnes

Daniel McGinnes is a Performance Specialist at IBM in the UK Lab at Hursley. He works on measuring and tuning performance of several WebSphere products, including WebSphere Application Server, WebSphere Enterprise Service Bus, and WebSphere Business Events. He previously worked as an IT specialist providing consultancy to IBM customers across EMEA and USA.




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


IBM, WebSphere, DB2, Lotus, Rational, and Tivoli are trademarks or registered trademarks of IBM Corporation in the United States, other countries, or both. Microsoft and Windows are registered trademarks of Microsoft Corporation in the United States, other countries, or both. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product, and service names may be trademarks or service marks of others. 他の会社名、製品名およびサービス名等はそれぞれ各社の商標です。

    日本IBMについて プライバシー お問い合わせ