分散キャッシュ・アプリケーションの開発
このページでは、アプリケーションの開発と設計の問題について説明します。オプションあるいは主要構成のいずれかとして分散キャッシュ・クラスタ上でアプリケーションを展開する場合は、このページを参照してください。
InterSystems IRIS を使用し、分散システムとしてアプリケーションを展開することは、基本的に実行時の構成に関係します ("分散キャッシュ・クラスタの導入" を参照してください)。つまり、InterSystems IRIS 構成ツールを使用し、データの論理名 (グローバル) とアプリケーション・ロジック (ルーチン) を適切なシステムの物理ストレージにマップします。
ECP リカバリ・プロトコル
ECP は、アプリケーション・サーバとデータ・サーバの間の接続の中断から自動的に回復するように設計されています。このような中断が発生した場合、ECP はリカバリ・プロトコルを実行します。リカバリ・プロトコルは、障害の性質によって異なります。その結果は、接続が回復されるか、何も発生しなかったかのようにアプリケーションのプロセスを続行できるか、またはリセットされ、トランザクションを強制的にロールバックし、アプリケーションのプロセスが再構築されます。主な原則は以下のとおりです。
-
アプリケーション・サーバとデータ・サーバの間の接続が中断した場合、アプリケーション・サーバはデータ・サーバとの接続を再確立しようとします。必要に応じて、[再接続までの時間] 設定で指定された間隔 (既定値は 5 秒) で繰り返し実行します。
-
中断が短時間の場合、接続は回復されます。
データサーバで構成された [トラブル状態の時間間隔] のタイムアウト期間 (既定値は 60 秒) 内に接続が再確立された場合、すべてのロックおよび開いているトランザクションが中断前の状態にリストアされます。
-
中断が長くなると、データ・サーバは接続をリセットします。このため、中断が終了したときに回復できなくなります。
[トラブル状態の時間間隔] 内に接続が再確立されない場合、データ・サーバは接続を一方的にリセットします。これにより、トランザクションをロールバックして、応答しないアプリケーション・サーバからのロックを解放できるようになり、機能しているアプリケーション・サーバがブロックされなくなります。接続が回復した場合、アプリケーション・サーバの側からすると接続が無効になります。中断された接続でデータ・サーバを待機しているすべてのプロセスは、<NETWORK> エラーを受け取り、rollback-only 条件になります。アプリケーション・サーバによって受信された次の要求では、データ・サーバへの新しい接続が確立されます。
-
中断が非常に長い場合は、アプリケーション・サーバも接続をリセットします。
アプリケーション・サーバの長い Time to wait for recovery タイムアウト期間 (既定は 20 分) 内に接続が再確立されない場合、アプリケーション・サーバは一方的に接続をリセットします。中断された接続でデータ・サーバを待機しているすべてのプロセスは、<NETWORK> エラーを受け取り、rollback-only 条件になります。アプリケーション・サーバによって受信された次の要求では、データ・サーバへの新しい接続が確立されます (可能な場合)。
ECP タイムアウト設定を、以下の表に示します。各項目は、管理ポータルの [システム]→[構成]→[ECP設定] ページ、または構成パラメータ・ファイル (CPF) の ECP セクションで構成できます (詳細は、"[ECP]" を参照)。
管理ポータルの設定 | CPF 設定 | 既定値 | 範囲 | |
---|---|---|---|---|
再接続までの時間 | ClientReconnectInterval | 5 秒 | 1 ~ 60 秒 | アプリケーションがデータ・サーバに再接続しようとする間隔。 |
トラブル状態の時間間隔 | ServerTroubleDuration | 60 秒 | 20 ~ 65535 秒 | 中断された接続をリセットする前に、データ・サーバがアプリケーション・サーバからの通信を待機する時間。 |
リカバリまでの待機時間 | ClientReconnectDuration | 1200 秒 (20 分) | 10 ~ 65535 秒 | 中断された接続をリセットする前に、アプリケーション・サーバがデータ・サーバへの再接続の試行を続ける時間。 |
既定値は、以下を実現することを目的としています。
-
アプリケーション・サーバが使用可能になるのを待機することによって、他のアプリケーション・サーバで使用できるデータ・サーバ・リソースを長時間拘束しないようにする。
-
データ・サーバが利用できないときに他に何もすることがないアプリケーション・サーバに、頻繁に再接続を試みることにより、長時間の接続中断を待つ機能を提供する。
ECP は、TCP の物理接続を利用して、容量をあまり使用せずに、相手側のインスタンスの正常性を検出します。ほとんどのプラットフォームで、システム・レベルで TCP 接続障害および検知動作を調整できます。
アプリケーション・サーバの接続が非アクティブになると、データ・サーバは、その接続で新しい要求が到着するのを待機するか、またはアプリケーション・サーバによって新しい接続が要求されるのを待機しながら、アクティブなデーモンを維持します。既存の接続から要求が着信した場合、リカバリすることなく、すぐに処理が再開されます。基本のハートビート・メカニズムが、システムまたはネットワークの障害のためにアプリケーション・サーバが完全に利用不可であることを示す場合、基本の TCP 接続は迅速にリセットされます。したがって、アプリケーション・サーバから長時間応答がないことは、一般に、アプリケーション・サーバの機能を停止させるがその接続を妨げることのない、何らかの問題を示します。
基本の TCP 接続がリセットされた場合、データ・サーバはその接続を “再接続の待機” 状態にします。この状態では、データ・サーバ側にアクティブな ECP デーモンは存在しません。アプリケーション・サーバから新しい接続が要求されたときに、1 対のデータ・サーバ・デーモンが作成されます。
この非応答状態と再接続の待機状態を総称して、データ・サーバの障害状態と呼びます。どちらの状態でも必要なリカバリは、ほとんど同じです。
データ・サーバで障害またはシャットダウンが発生した場合、サーバはクラッシュやシャットダウン時点でアクティブであった接続を記憶しています。再起動後、データ・サーバは短時間 (通常は 30 秒) の間、中断した接続を再接続の待機状態に置きます。その状態の間に、アプリケーション・サーバとデータ・サーバは連携して、データ・サーバがシャットダウンした時点以降のすべてのトランザクションとロック、および未実行の Set および Kill トランザクションを回復します。
ECP 構成インスタンスのリカバリ中、InterSystems IRIS は多数のリカバリ・メカニズムを保証し、またこれらの保証に対する制限を指定します。"ECP リカバリ・プロセス、保証、および制限" では、これらの詳細と、リカバリ・プロセスの詳細について説明しています。
切断の強制
既定では、ECP は、アプリケーション・サーバとデータ・サーバ間の接続を自動的に管理します。ECP 構成インスタンスが起動した時点では、アプリケーション・サーバとデータ・サーバ間のすべての接続は、未接続 (接続が定義済みでも、確立されていない) 状態になります。アプリケーション・サーバが、データ・サーバへの接続を必要とする (データやコードに対する) 要求を行うと、その接続は自動的に確立され、接続状態は正常に変更されます。アプリケーション・サーバとデータ・サーバ間のネットワーク接続は、その後、接続された状態を維持します。
アプリケーションの中には、ECP 接続を切断する必要があるものもあります。例えば、アプリケーション・サーバとして構成されたシステムがあるとします。このシステムは、データ・サーバ・システムに格納されたデータを定期的に (1 日に数回) フェッチする必要がありますが、その後は、データ・サーバとのネットワーク接続をオープンにしておく必要がありません。この場合、アプリケーション・サーバ・システムは、SYS.ECP.ChangeToNotConnected()Opens in a new tab メソッドを呼び出し、ECP 接続状態を強制的に未接続にします。
以下に例を示します。
Do OperationThatUsesECP()
Do SYS.ECP.ChangeToNotConnected("ConnectionName")
ChangeToNotConnected メソッドは、以下を実行します。
-
変更したデータをデータ・サーバに送信し、データ・サーバからの確認応答を待機します。
-
アプリケーション・サーバがオープンしたデータ・サーバ上のロックを削除します。
-
データ・サーバ側のオープンしているすべてのトランザクションをロールバックします。アプリケーション・サーバ側のトランザクションは、“rollback only” 状態になります。
-
未実行の要求を <NETWORK> エラーで完了します。
-
キャッシュされているすべてのブロックをフラッシュします。
状態が未接続に変更された後、次にデータ・サーバにデータが要求されると、接続は自動的に再確立されます。
パフォーマンスとプログラミングに関する考慮点
分散キャッシュ・クラスタ・ベースのアプリケーションの高性能性および高信頼性を実現するには、以下の問題を認識する必要があります。
複数の ECP チャネルを使用しない
帯域幅を増やすためにアプリケーション・サーバとデータ・サーバとの間に複数の重複した ECP チャネルを確立しないでください。1 つの論理トランザクションに対するロックや更新がデータ・サーバ上で非同期になり、データが不整合になるリスクがあります。
ECP 制御構造用のデータ・サーバ・データベース・キャッシュの増大
ECP 経由で提供されるブロックをバッファリングする処理に加え、データ・サーバでは、さまざまな ECP 制御構造を格納するのにグローバル・バッファを使用します。この構造に必要なメモリ量を決定する要素はいくつかありますが、最も重要なものは、クライアントのキャッシュの集約サイズの関数です。要求サイズを概算するために、必要に応じてデータ・サーバのデータベース・キャッシュを調整できます。以下のガイドラインを使用してください。
データベースのブロック・サイズ | 推奨事項 |
---|---|
8 KB | 50 MB にアプリケーション・サーバのすべての 8 KB データベース・キャッシュのサイズの合計の 1% を加えたサイズ |
16 KB (有効化されている場合) | アプリケーション・サーバのすべての 16 KB データベース・キャッシュのサイズの合計の 0.5% |
32 KB (有効化されている場合) | アプリケーション・サーバのすべての 32 KB データベース・キャッシュのサイズの合計の 0.25% |
64 KB (有効化されている場合) | アプリケーション・サーバのすべての 64 KB データベース・キャッシュのサイズの合計の 0.125% |
例えば、既定の 8 KB のブロック・サイズに加えて 16 KB のブロック・サイズが有効になっていて、6 つのアプリケーション・サーバがあり、それぞれに 2 GB の 8 KB データベース・キャッシュおよび 4 GB の 16 KB データベース・キャッシュがある場合、データ・サーバの 8 KB データベース・キャッシュを調整して制御構造用に 52 MB (50MB + [12 GB * .01]) を使用できるようにし、16 KB キャッシュを調整して制御構造用に 2 MB (24 GB * .005) を使用できるようにする必要があります (どちらの場合も小数点以下は切り上げます)。
データベース・キャッシュの割り当てに関する詳細は、"メモリと開始設定" を参照してください。
負荷分散のユーザ要求の影響の評価
ラウンドロビンまたは負荷分散方式でユーザをアプリケーション・サーバに接続すると、アプリケーション・サーバ上でキャッシュから得られる利点が減る可能性があります。ユーザが機能グループに属しており、機能グループで同一のデータを読み取る必要がある場合は、特にこれに該当します。これらのユーザは、複数のアプリケーション・サーバに分散しているため、各アプリケーション・サーバが、データ・サーバに同一のデータを要求する可能性があり、それによって、同じデータに対して複数のキャッシュを使用して分散キャッシュの効率を低下させるだけでなく、ブロックの無効化が増加する可能性もあります。ブロックは、1 つのアプリケーション・サーバで変更されると、他のアプリケーション・サーバでも更新されるためです。これはいくらか主観的ですが、アプリケーションの特性に詳しい人がこの可能性について検討する必要があります。ロード・バランサを構成する場合は、"負荷分散、フェイルオーバー、ミラー構成" を参照して、複数のアプリケーション・サーバにわたってアプリケーション接続を分散する Web サーバ層の負荷分散に関する重要な説明を確認してください。
トランザクションを単一のデータ・サーバに制限する
単一トランザクション内の更新を、単一のリモート・データ・サーバまたはローカル・サーバに制限します。トランザクションに複数のサーバ (ローカル・サーバを含む) に対する更新が含まれており、TCommit が正常に完了できないと、トランザクションに含まれるサーバによっては、更新をコミットしたものと、ロールバックしたものがある場合があります。詳細は、"コミットの保証" を参照してください。
IRISTEMP に対する更新は、ロールバックを目的とするトランザクションの一部とは見なされないため、この制限には含まれません。
アプリケーション・サーバでの一時グローバルの配置
一時 (スクラッチ) グローバルは、グローバルに共有する必要があるデータを含まない場合、アプリケーション・サーバのローカルに配置する必要があります。多くの場合、一時グローバルは、とてもアクティブで、書き込みが集中します。一時グローバルがデータ・サーバ上に配置されていると、これによって ECP 接続を共有する他のアプリケーション・サーバに不利となります。
未定義のグローバルに対する繰り返し参照の回避
未定義のグローバル (例えば、^x が未定義の $Data(^x(1)) など) が繰り返し参照される場合、グローバルがデータ・サーバで定義されているかどうかをテストするネットワーク処理が常に起こります。
それとは対照的に、定義されたグローバル内の未定義のノード (例えば、^x の他のノードが定義済みの $Data(^x(1)) など) が繰り返し参照される場合、グローバル (^x) がアプリケーション・サーバ・キャッシュに格納されると、ネットワーク処理は要求されません。
この動作は、ネットワークに接続されていないアプリケーションの場合と大きく異なります。ローカル・データでは、未定義のグローバルに対する参照の繰り返しは、最適化され、不要な作業は排除されます。アプリケーションをネットワーク環境に移植する設計者の場合、グローバルの使用が定義されていたり、定義されていなかったりするため、確認が必要になる場合があります。通常は、グローバルの他の特定のノードが常に定義されていることを確認するだけで十分です。
ストリーム・フィールドの使用の回避
ストリーム・フィールドがクエリにあると読み込みロックが発生し、データ・サーバへの接続が必要になります。このことから、このようなクエリではデータベース・キャッシュの利点が得られず、2 回目以降の実行でもパフォーマンスが向上しません。
アプリケーション・カウンタでの $Increment 関数の使用
オンライン・トランザクション処理システムの共通の動作は、レコード番号などに使用する一意の値を生成することです。これは、一般的なリレーショナル・アプリケーションで、“次に使用可能な” カウンタ値を含むテーブルを定義して行います。アプリケーションに新規の識別子が必要な場合、カウンタを含む列をロックし、カウンタ値をインクリメントし、ロックを解放します。これは、シングル・サーバ・システムであっても並行処理障害を引き起こします。つまり、アプリケーション・プロセスは、共通カウンタ上のロックが解放されるのを、より長時間待機するようになります。ネットワーク環境では、これはある時点でさらに障害となります。
InterSystems IRIS は、アプリケーション・レベルのロックを一切必要とせずに、(グローバルに格納される) カウンタ値を自動的にインクリメントする $Increment 関数を提供することでこれに対処します。$Increment の並行処理は、InterSystems IRIS データベース・エンジンと ECP の両方に組み込まれており、シングル・サーバや分散アプリケーションで使用した場合に非常に高い効率性が実現されます。
InterSystems IRIS オブジェクト (あるいは SQL) から提供される既定構造を使用して構築されたアプリケーションは、$Increment を自動的に使用して、オブジェクト識別子の値を割り当てます。$Increment は、ECP 上で実行された場合のジャーナル同期に関わる同期処理です。このため、ECP 上での $Increment は比較的低速の処理となり、とりわけ他の比較対象が (アプリケーション・サーバ・データベース・キャッシュまたはデータ・サーバ・データベース・キャッシュのいずれかに) キャッシュ済みのデータを持っているかどうかにより違いが出ます。この影響は、フェイルオーバー・メンバ間のネットワーク遅延により、ミラーリング環境においてさらに大きくなります。このため、アプリケーションを再設計して $Increment を $Sequence 関数に置き換えると便利な場合があります。こうすると、新しい値のバッチは各アプリケーション・サーバ上で各プロセスに自動的に割り当てられ、データ・サーバは新規に値のバッチが必要になった場合にのみ処理に参加します (ただし、連続したアプリケーション・カウンタ値が必要な場合、この手法は使用できません)。$Sequence は $Increment と組み合わせて使用することもできます。
ECP 関連エラー
ECP を使用するシステムには、いくつかの実行時エラーがあります。ECP 関連のエラーは、コマンドの実行直後に発生する場合があります。あるいは、Kill のように、事実上非同期のコマンドの場合、エラーはコマンドの完了後すぐに発生します。
<NETWORK> エラー
<NETWORK> エラーは、通常の ECP リカバリ・メカニズムで処理できなかったエラーを示します。
アプリケーション内で <NETWORK> エラーを受け取った場合は常に、プロセスの停止や未実行処理のロールバックが可能です。<NETWORK> エラーの中には、本質的に致命的なエラー状態になるものもあります。すぐに解決する一時的な状態を示すものもあります。しかし、理想的なプログラミング手法とは、<NETWORK> エラーの発生時、未実行処理をロールバックし、現在のトランザクションを最初から開始することです。
$Data や $Order など get 型要求の <NETWORK> エラーは、即座にトランザクションをロールバックするのではなく、手動で再試行できます。ECP は、データを損失する <NETWORK> エラーの発生を避けようとしますが、読み取り専用の要求に多くのエラーを生じます。
Rollback Only 条件
アプリケーション側の rollback-only 条件は、アプリケーション・サーバによって開始されたトランザクション中にデータ・サーバがネットワーク障害を検出したときに発生し、トランザクションがロールバックされるまですべてのネットワーク要求でエラーが発生した状態になります。