スレッド化

メッセージ処理ノードおよびパーサーは、 マルチインスタンス、マルチスレッド化環境で作業することが必要です。 それぞれが多くの構文エレメントを持つ、 多くのノード・オブジェクトまたはパーサー・オブジェクトがあり、 これらのオブジェクト上にメソッドを実行する多くのスレッドがあり得ます。 メッセージ・ブローカー設計では、メッセージ・オブジェクトとそれが所有するその他のオブジェクトが、 メッセージ・フローを介してメッセージを受け取り、処理する スレッドによってのみ使用されるようにします。

メッセージ・フロー処理ノードのインスタンスは、 ノードが定義されるメッセージ・フローを保守するすべてのスレッドによって共有および使用されます。 パーサーの場合、パーサーのインスタンスは 1 つのメッセージ・フロー・スレッドによってしか使用されません。

ユーザー定義拡張機能はこのモデルを固守し、セマフォーがスレッド間で アクセスを逐次化する必要のあるグローバル・データやリソースの使用を避けるべきです。 そのような逐次化は、パフォーマンスのボトルネックの原因となることがあります。

ユーザー定義拡張機能のインプリメンテーション関数は再入可能でなければならず、 それらが呼び出すその他の関数も再入可能であることが必要です。 すべてのユーザー定義拡張機能のユーティリティー関数は、完全に再入可能です。

ユーザー定義拡張機能は、必要であれば追加のスレッドを生み出すことができますが、 インプリメンテーション関数の完了時に、 同じ スレッドがブローカーに制御を戻すことが不可欠です。 これに失敗すると、ブローカーの保全性に妥協が生じ、予測不能な結果になります。

実行モデル

実行グループが初期化されると、ランタイムに対して適切な lil が使用可能になります。 実行グループ・ランタイム・プロセスが開始し、専用構成スレッドを生み出します。 メッセージ・フロー実行環境では、メッセージ・フローはスレッド・セーフです。 逐次化の問題を考慮しなくても、 多数の OS スレッド上で並行してメッセージ・フローを実行することができます。 インプリメントするユーザー定義ノードは、このスレッド化モデルと妥協するべきではありません。 以下の点に注意してください。
  • メッセージ・フローに送信される入力メッセージは、それを受け取ったスレッドによってのみ 処理されます。メッセージ処理中には、スレッドまたはコンテキストの交換は行われません。
  • メッセージ・フローがアクセスするデータ構造は、1 つのスレッドにしか可視になりません。 これらのデータ構造は、処理中のメッセージの存続期間のみ存在します。
  • メッセージ・フローの単一インスタンスは、メッセージ・フロー・スレッド・プールの すべてのスレッド間で共用されます。 これは、状態がないという点で、メッセージ・フロー・ノードの動作に関連します。
  • 実行グループのメモリー要件は、より多くの OS スレッド上でメッセージ・フローを実行しても、 過度に影響を受けることはありません。

スレッド化モデル

次のメッセージ・フローの例は、独自のユーザー定義ノードを設計およびインプリメントする際に 意識すべきスレッド化の考慮事項を理解するのに役立ちます。 ここでは、ユーザー定義入力ノードの例を考慮します。

メッセージ・フローは、スレッドの集合で実行するように構成できます。 これはメッセージ・フロー中の入力ノード数、 およびメッセージ・フローの additionalInstances プロパティーの値によって決定されます。 これらの 2 つのエレメントが、メッセージ・フローが使用できるスレッド・プールの最大容量を決定します。 したがってメッセージ・フローに、単一スレッド化実行を指示する特定の処理要件がある場合、 これがそのケースであることを確認する必要があります。

入力ノード処理のイベントの典型的な順序は以下のようになります。
  1. 入力ノード構成が行われる
  2. スレッドがスレッド・プールからの要求を受ける
  3. 割り振られたスレッドがノードの実行メソッドで開始する
  4. 構成 (または再構成) がコミットされる
  5. 初期化処理がスレッドのコンテキストで実行される
  6. スレッドがブローカーのキュー・マネージャーに接続する
  7. メッセージ・グループおよびバッファー・オブジェクトが作成される
  8. 入力キューへの queue open 要求がキュー・マネージャーに送信される。 このキューは、スレッドの存続期間中オープンしたままです。
  9. 入力ノードがメッセージ処理ループに入る
  10. メッセージが受け取られると、データ・バッファーにメッセージのヘッダーと本文が入る
  11. メッセージ・オブジェクトが作成され、スレッドのグループに付加される
  12. 複数のスレッドが指定される場合、スレッド・ディスパッチングがアクティブになる
  13. メッセージ・データがダウンストリームで伝搬される
以下の点に注意してください:
  • 入力ノードは、選択されたメッセージ・フローのスレッド化モデルをインプリメントします。
  • 常に入力ノードには、その入力ソースから読み取るか、 または受け取ったメッセージをアクティブに処理する最低 1 つのスレッドがあります。 メッセージ・フローに複数の入力ノードがある場合、 任意の入力ノードのディスパッチング・ポリシーが決定したとおり、 追加のスレッド・インスタンスを使用して、その入力ノードを保守することが可能です。
スレッドをデマンド (要求) することができます。 メッセージ・フローがデプロイされると、入力ノードは初期スレッドを要求します。 メッセージ・フローには関連するスレッドのプールがありますが、 ディスパッチング・ポリシーの責任があるのは入力ノードです。 つまり、メッセージ・フロー自体の 1 つのインスタンスがスレッド上で実行していることを 常に確認する必要があります。 additionalInstances プロパティーのデフォルト値はゼロなので、 複数の入力ノードを定義してある場合、スレッドへの追加の要求は失敗します。 これは、メッセージ・フローが予期しているよりも多くのスレッドを消費する可能性があるということです。 また、複数の入力ノードを定義した場合、入力ノードの 1 つがスレッド不足になる可能性もあります。

additionalInstances プロパティーを使用して個別のスレッドでブローカーがメッセージ・フローの追加のコピーを 開始するのは、入力キューがボトルネックになるのを防ぐ最も有効な方法です。 しかし、別々のスレッドを作成すると、メッセージ・キューからのメッセージの並列処理が実行されるので、 このプロパティーは、処理されるオーダー・メッセージが重要でない場合のみに使用を制限するべきです。

スレッドは、入力ノード構成および操作の結果として作成されます。 スレッドはスレッド・プールでアクティブまたはアイドル状態になり、 アイドル状態のスレッドは入力ノードによってディスパッチされるか、 またはブローカーがシャットダウンされるまでプールに残ります。

下記の図は、メッセージ・フローのスレッド割り振りを例示しています。

メッセージ・フローでのスレッド割り振り


図中のエレメントの説明に付随するテキストを参照

最初にスレッド 1 が要求され (A)、メッセージを待機します。 メッセージが受け取られると (B)、スレッド 1 がメッセージを伝搬し、スレッド 2 をディスパッチします。 スレッド 2 は即座にメッセージを受け取り (C)、メッセージを待機するスレッド 3 を伝搬およびディスパッチします (D)。 スレッド 1 が完了し (E)、スレッド・プールに戻ります。 次にスレッド 3 がメッセージを受け取り (F)、スレッド 1 をディスパッチしてメッセージを伝搬します。 ここでスレッド 1 がメッセージがキューに到着するのを待機します (G)。

H のマークには意味がありません。メッセージ・フローのこのインスタンスでは、 スレッド 1 がメッセージを獲得しますが、その時点で他のすべてのスレッドはアクティブなので、 ディスパッチはしません。 メッセージが伝搬されます。

このメッセージが伝搬された後、スレッド 2 が完了し (I)、 キューから新しいメッセージを受け取って、この新規メッセージを伝搬します。 その後スレッド 3 が完了し (J)、プールに戻ります。 次いでスレッド 2 も完了します (K)。 これはスレッド 1 の完了時にディスパッチしなかったので (L)、 キュー上にメッセージがなくてもスレッド・プールに戻ることはできず、 メッセージがキューに到着するのを待機します。

WebSphere Message Broker でのスレッドの動作について、以下の点に注意してください。
  • スレッドは、ワークロードに必要な場合のみ作成されます。 つまり、実行グループ・プロセスが使用できるスレッドは、 構成で使用可能とされるよりも少ないということです。
  • すべての使用可能なスレッドがメッセージ・フロー内でアクティブに処理中でない限り、 常に 1 つのスレッドが入力キューを読み取ります。
  • 任意の時点でワークロードが増えると、同じメッセージ・フロー中の他の入力ノードが、 スレッド・プールに戻されていたスレッドを獲得できるようになります。
あるスレッドがメッセージを獲得するのに、他のすべてのスレッドがその時点で アクティブである場合、最初のスレッドはディスパッチできません。 メッセージが伝搬されます。このスレッドの完了時にディスパッチしなかったので、 キュー上にメッセージがなくてもスレッド・プールに戻ることはできません。
関連資料
cniDispatchThread
特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック
Copyright IBM Corporation 1999, 2006 最終更新: 08/21/2006
as01460_