分散アプリケーションの開発
この章は、アプリケーションの開発と設計の問題について説明しています。オプションあるいは主要構成のいずれかとして ECP を使用してアプリケーションを展開する場合は、この章を参照してください。
Caché を使用し、分散 (マルチサーバ) システムとしてアプリケーションを展開することは、基本的に実行時の構成に関係します ("分散システムの構成" を参照してください)。つまり、Caché 構成ツールを使用し、データの論理名 (グローバル) とアプリケーション・ロジック (ルーチン) を適切なシステムの物理ストレージにマップする必要があります。
以下の項目について説明します。
ECP リカバリ
ECP では、ECP アプリケーション・サーバと ECP データ・サーバ間の接続の中断は、自動的に復元されるよう設計されています。
ECP アプリケーション・サーバと ECP データ・サーバの接続が中断された場合、以下が発生します。
-
アプリケーション・サーバの接続の状態が、再接続を試行中であることを示す障害に設定されます。
-
ECP アプリケーション・サーバは、ECP データ・サーバへの再接続を試行します。
-
[トラブル状態の時間間隔] ("ECP のタイムアウト値" を参照) で指定されている時間以内にアプリケーション・サーバの接続が再確立されると、接続の状態は正常に変化します。すべてのロックとオープンしているトランザクションは、割り込み前の状態にリストアされます。
-
[トラブル状態の時間間隔] で指定されている時間以内に ECP データ・サーバとの接続を再確立できなかった ECP アプリケーション・サーバは、その接続を無効にし、リモート・アクティビティを待機しているすべてのプロセスに NETWORK エラーを返します。続いて、アプリケーション・サーバの接続の状態を未接続に設定します。次のリファレンスでは、データ・サーバに新しい ECP 接続を確立します。
-
[リカバリまでの待機時間] ("ECP のタイムアウト値" を参照) で指定されている時間以内に接続を再確立できなかった場合、ECP データ・サーバは、ECP アプリケーション・サーバが関係している開いたトランザクションをすべてロールバックし、サーバに対して保持されているすべてのロックを ECP アプリケーション・サーバに代わって解除します。データ・サーバの接続の状態は解放に変更されます。
既定では、ECP は以下のタイムアウト値を使用します。
管理ポータルの設定 | 既定値 | 範囲 |
---|---|---|
トラブル状態の時間間隔 | 60 秒 | 20 ~ 65535 秒 |
リカバリまでの待機時間 | 1200 秒 (20分) | 10 ~ 65535 秒 |
再接続までの時間 | 5 秒 | 1 ~ 60 秒 |
各項目は、管理ポータルの システム, 構成, ECP設定 ページで構成できます。
接続が障害状態を示す時間です (秒単位)。この時間が経過すると、データ・サーバは、接続が回復不可能でリカバリできないと判断します。
これは、[このシステムを ECP データ・サーバとして構成] セクションで設定し、既定値は 60 秒です。秒数は 20 ~ -65535 の範囲で設定します。
アプリケーション・サーバが、接続を回復不能として判断するまで、接続の再確立を試行し続ける時間です (秒単位)。
これは、[このシステムを ECP アプリケーション・サーバとして構成] セクションで設定し、既定値は 1200 秒 (20分) です。値は 10 秒 ~ 65535 秒の間で設定します。アプリケーション・サーバは、待機時間がタイムアウトになるまで、設定した再接続間隔を待って接続を再試行します。
データ・サーバが使用不可能になったときに、再接続を試行するまで待機する時間です (秒単位)。
これは、[このシステムを ECP アプリケーション・サーバとして構成] セクションで設定し、既定値は 5 秒です。秒数は 1 ~ -60 の範囲で設定します。アプリケーション・サーバは、再接続試行時間がタイムアウトになるまで、この間隔で予定されたとおり接続を再試行します。
既定値は、データ・サーバに長時間待機させないように設定されています。これは、作動していないアプリケーション・サーバに長時間データ・サーバ・リソースが専有されないようにするためです。アプリケーション・サーバはデータ・サーバがクラッシュしてから再起動するまで、最大 20 分待機します。これは、データ・サーバの再起動後、アプリケーション・サーバが完全にリカバリさせるための時間です。アプリケーション・サーバからの再接続がないとき、それを待機するよりも、データ・サーバでは優先させるべきことがあるという暗黙の想定がここにはあります。
ECP では、パイプの反対側の状態の検知に TCP 物理接続が使用されます。ECP は、パイプが溢れることなく、常にメセージが通過するようにします。ほとんどのプラットフォームで、システム・レベルで TCP 接続障害および検知動作を調整できます。
データ・サーバ側は、一定時間内にアプリケーション・サーバからのトラフィックを受信しない場合、その接続に応答がないと判断します。この非応答状態のとき、アクティブな ECP データ・サーバ・デーモンが、新しい要求の着信や新しい接続の要求を待ちます。既存の接続から要求が着信した場合、リカバリすることなく、すぐに処理が再開されます。基本の応答メカニズムでは、アプリケーション・サーバの障害かネットワーク障害によってアプリケーション・サーバからの交信が途絶えた場合、基本の TCP 接続がすぐにリセットされます。そのため、データ・サーバ側で長時間非応答状態が続いた場合、それはアプリケーション・サーバ側で接続障害ではなく、機能を停止させるような問題 (システムのハングなど) が発生したと判断されます。
基本の TCP 接続がリセットされた場合、データ・サーバはその接続を “再接続の待機” 状態にします。この “再接続の待機” 状態では、データ・サーバ側にアクティブな ECP デーモンは存在しません。アプリケーション・サーバ・システムから新しい接続が要求されたときに、1 対の ECP データ・サーバ・デーモンが作成されます。
この非応答状態とリカバリ待機状態を総称して、データ・サーバ側の障害状態と呼びます。どちらの状態でも必要なリカバリは、ほとんど同じです。
データ・サーバがクラッシュまたはシャットダウンした場合、サーバはクラッシュやシャットダウン時点でアクティブであった接続を記憶しています。再起動後、データ・サーバは短時間 (通常は 30 秒) の間、中断した接続を “再接続の待機” 状態に置きます。その状態の間に、アプリケーション・サーバとデータ・サーバは連携して、データ・サーバがシャットダウンした時点以降のすべてのトランザクションとロック、および未実行の Set および Kill トランザクションを回復します。
ECP 構成システムのリカバリ中、Caché によって、“ECP リカバリ保証と制限” の付録の "ECP リカバリ保証" に記載されているいくつかのメカニズムが保証されます。ただし、これらの保証には制限があります。詳細は、同じ付録の "ECP リカバリの制限" を参照してください。
切断の強制
既定では、ECP は、アプリケーション・サーバ・システムとデータ・サーバ・システム間の接続を自動的に管理します。ECP 構成システムが最初に起動した時点では、ECP アプリケーション・サーバとデータ・サーバ間のすべての接続は、未接続 (接続が定義済みでも、確立されていない) 状態になります。ECP アプリケーション・サーバが、ECP データ・サーバへの接続を必要とする (データやコードに対する) 要求を行うと、その接続は自動的に確立され、接続状態は正常に変更されます。ECP アプリケーション・サーバとデータ・サーバ間のネットワーク接続は、その後、接続された状態を維持します。
アプリケーションの中には、ECP 接続を切断する必要があるものものあります。例えば、ECP アプリケーション・サーバとして構成されたシステムがあるとします。このシステムは、データ・サーバ・システムに格納されたデータを定期的に (1 日に数回) フェッチする必要がありますが、その後は、データ・サーバとのネットワーク接続をオープンにしておく必要がありません。この場合、ECP アプリケーション・サーバ・システムは、SYS.ECPOpens in a new tab クラスの ChangeToNotConnected メソッドを呼び出し、ECP 接続状態を強制的に未接続にします。
例えば以下のようになります。
Do OperationThatUsesECP()
Do SYS.ECP.ChangeToNotConnected("ConnectionName")
ChangeToNotConnected メソッドは以下を実行します。
-
変更したデータをデータ・サーバに送信し、データ・サーバからの確認応答を待機します。
-
ECP アプリケーション・サーバがオープンした ECP データ・サーバ上のロックを削除します。
-
データ・サーバ側のオープンしているすべてのトランザクションをロールバックします。アプリケーション・サーバ側のトランザクションは、“rollback only” 状態になります。
-
未実行の要求を NETWORK エラーで完了します。
-
キャッシュされているすべてのブロックをフラッシュします。
状態が未接続に変更された後、次に ECP データ・サーバにデータが要求されると、接続は自動的に再確立されます。
パフォーマンスとプログラミングに関する考慮点
ECP アプリケーションの高性能性および高信頼性を実現するには、以下の問題を認識する必要があります。
複数のデータ・サーバにわたるトランザクションの回避
リモート ECP データ・サーバかローカル・サーバかにかかわらず、単一トランザクション内の更新を単一サーバに制限します。トランザクションに複数のサーバ (ローカル・サーバを含む) に対する更新が含まれており、TCommit が正常に完了できないと、トランザクションに含まれるサーバによっては、更新をコミットしたものと、ロールバックしたものがある場合があります。詳細は、“ECP リカバリ保証と制限” の "コミットの保証" のセクションを参照してください。
CACHETEMP に対する更新は、ロールバックを目的とするトランザクションの一部とは見なされないため、この制限には含まれません。
ZSync コマンドの機能不全
ECP 構成では、ZSync コマンドは使用できません。ECP では、Set または Kill 処理がエラーを受け取った場合は常に、トランザクション全体をロールバックのみとして宣言することによって、トランザクション内で同様の効果を実現できます。
大規模な ECP システムにおけるメモリの使用量
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 MB のブロック・サイズに加えて 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) を使用できるようにする必要があります (どちらの場合も小数点以下は切り上げます)。
データベース・キャッシュへのメモリの割り当ての詳細は、"Caché システム管理ガイド" の “Caché の構成” の章にある "メモリと開始設定" を参照してください。
一時グローバル
一時 (スクラッチ) グローバルは、グローバルに共有する必要があるデータを含まない場合、アプリケーション・サーバのローカルに配置する必要があります。多くの場合、一時グローバルは、とてもアクティブで、書き込みが集中します。一時グローバルがデータ・サーバ上に配置されていると、これによって ECP 接続を共有する他の ECP アプリケーション・サーバに不利となります。
複数の ECP チャネル
帯域幅を増やすためにアプリケーション・サーバとデータベース・サーバとの間に複数の重複した ECP チャネルを確立しないでください。1 つの論理トランザクションに対するロックや更新がデータベース・サーバ上で非同期になり、データが不整合になるリスクがあります。
負荷分散アプリケーション・サーバ
ラウンドロビンまたは負荷分散方式でユーザをアプリケーション・サーバに接続すると、アプリケーション・サーバ上でキャッシュから得られる利点が減る可能性があります。ユーザが機能グループに属しており、機能グループで同一のデータを読み取る必要がある場合は、特にこれに該当します。これらのユーザは、複数のアプリケーション・サーバに分散しているため、各アプリケーション・サーバが、データ・サーバに同一のデータを要求する可能性があり、それによってブロックの無効化が増加する可能性があります。ブロックは、1 つのアプリケーション・サーバで変更されると、他のアプリケーション・サーバでも更新されるためです。これはいくらか主観的ですが、アプリケーションの特性に詳しい人がこの可能性について検討する必要があります。
未定義のグローバルに対する繰り返し参照
未定義のグローバル (例えば、^x が未定義の $Data(^x(1)) など) が繰り返し参照される場合、グローバルが ECP データ・サーバで定義されているかどうかをテストするネットワーク処理が常に起こります。
それとは対照的に、定義されたグローバル内の未定義のノード (例えば、^x の他のノードが定義済みの $Data(^x(1)) など) が繰り返し参照される場合、グローバル (^x) がアプリケーション・サーバ・キャッシュに格納されると、ネットワーク処理は要求されません。
この動作は、ネットワークに接続されていないアプリケーションの場合と大きく異なります。ローカル・データでは、未定義のグローバルに対する参照の繰り返しは、最適化され、不要な作業は排除されます。アプリケーションをネットワーク環境に移植する設計者の場合、グローバルの使用が定義されていたり、定義されていなかったりするため、確認が必要になる場合があります。通常は、グローバルの他の特定のノードが常に定義されていることを確認するだけで十分です。
$Increment 関数とアプリケーション・カウンタ
オンライン・トランザクション処理システムの共通の動作は、レコード番号などに使用する一意の値を生成することです。これは、一般的なリレーショナル・アプリケーションで、“次に使用可能な” カウンタ値を含むテーブルを定義して行います。アプリケーションに新規の識別子が必要な場合、カウンタを含む列をロックし、カウンタ値をインクリメントし、ロックを解放します。これは、シングル・サーバ・システムであっても並行処理障害を引き起こします。つまり、アプリケーション・プロセスは、共通カウンタ上のロックが解放されるのを、より長時間待機するようになります。ネットワーク環境では、これはある時点でさらに障害となります。
Caché では、$Increment を使用することにより、アプリケーション・レベルをロックする必要なく、(グローバルに格納される) カウンタ値を自動的にインクリメントします。$Increment の並行処理は、Caché データベース・エンジンと ECP の両方に組み込まれ、シングル・サーバと分散アプリケーションの使用を効果的にします。
Caché オブジェクト (あるいは SQL) から提供される既定構造を使用して構築されたアプリケーションは、$Increment を自動的に使用して、オブジェクト識別子の値を割り当てます。
$Increment は、ECP 上で実行された場合のジャーナル同期に関わる同期処理です。このため、ECP 上での $Increment は比較的低速の処理となり、とりわけ他の比較対象が (アプリケーション・サーバ・バッファ・プールまたはデータベース・サーバ・バッファ・プールのいずれかに) キャッシュ済みのデータを持っているかどうかにより違いが出ます。この影響は、フェイルオーバー・メンバ間のネットワーク遅延により、ミラーリング環境において更に大きくなります。これにより、アプリケーションを再設計することで、それぞれのアプリケーション・サーバに新しい値のバッチを割り当て、各アプリケーション・サーバ内でそのバッチにより $Increment を使用することが有効となります。データベース・サーバで新規に値のバッチが必要になった場合にのみ、そのデータベース・サーバを手がけます。(ただし、連続したアプリケーション・カウンタ値が必要な場合、この手法は使用できません。)また、$Sequence 関数も、$Increment の代用として、またはその組み合わせによって使用すれば、このコンテキストにおいて有効となります。
ECP 関連エラー
ECP を使用するシステムには、いくつかの実行時エラーがあります。ECP 関連のエラーは、コマンドの実行直後に発生する場合があります。あるいは、Kill のように、事実上非同期のコマンドの場合、エラーはコマンドの完了後すぐに発生します。
<NETWORK> エラー
<NETWORK> エラーは、通常の ECP リカバリ・メカニズムで処理できずに発生したエラーを示します。
アプリケーション内で <NETWORK> エラーを受け取った場合は常に、プロセスの停止や未実行処理のロールバックが可能です。<NETWORK> エラーの中には、本質的に致命的なエラー状態になるものもあります。すぐに削除される一時的な状態を示すものもあります。しかし、理想的なプログラミング手法とは、<NETWORK> エラーの発生時、未実行処理をロールバックし、現在のトランザクションを最初から再度開始することです。
$Data や $Order など get 型要求の <NETWORK> エラーは、即座にトランザクションをロールバックするのではなく、手動で再試行できます。ECP は、データを損失する <NETWORK> エラーの発生を避けようとしますが、読み取り専用の要求に多くのエラーを生じます。
Rollback Only 条件
アプリケーション側の rollback-only 条件は、アプリケーション・サーバが開始したトランザクション中に、データ・サーバがネットワーク障害を検出した場合に発生します。トランザクションがロールバックされるまで、すべてのネットワーク要求がエラーに遭遇する状態になります。