質問

私はそれを知っています Network Load BalancingFailover Clustering私たちは作れる パッシブサービス 非常に利用可能です。しかし、どうですか アクティブなアプリ?

例:私のアプリの1つは、固定間隔で外部リソースから一部のコンテンツを取得します。私は次のシナリオを想像しました:

  1. 単一のマシンで実行します。問題:このインスタンスが低下した場合、コンテンツは取得されません
  2. クラスターの各マシンで実行します。問題:コンテンツは複数回取得されます
  3. クラスターの各マシンにそれを持っていますが、そのうちの1つでのみ実行します。各インスタンスは、タスクを実行するかどうかを決定するために、何らかの共通リソースをチェックする必要があります。

ソリューション#3について考えていたとき、私は共通のリソースがどうあるべきか疑問に思いました。データベースにテーブルを作成することを考えました。ここでは、グローバルロックを取得するために使用できます。

これが最良の解決策ですか?人々は通常これをどのように行いますか?

ちなみに、それはWindows Server 2008で実行されているC#.NET WCFアプリです

役に立ちましたか?

解決

そのような問題については、彼らはメッセージキューを発明しました。クラスター化されたアプリケーションがすべてメッセージキューを聞くときのケースを想像してください(クラスター自体:-))。ある時点で、1つのインスタンスが最初のコマンドを取得して外部リソースをダウンロードします。成功した場合、インスタンスはメッセージをフラッシュし、代わりに「実行時間」 +「インターバル」に等しい後の実行時間のために別のものを投稿します。しかし、インスタンスが処理中に死んだ場合、それは問題ではありません。メッセージはキュー(タイムアウト後)に戻って(タイムアウト後)、他のインスタンスを拾うことができます。少しのトランザクション、少しメッセージキュー

私は世界のJava EE側にいるので、コーディングの詳細を手伝うことができます

他のヒント

私はあなたのソリューション#3を使用して同様の何かを実装しました。

のようなものと呼ばれるテーブルを作成します resource_lock, 、列付き(例: locking_key)ロックキーが含まれます。

次に、各間隔で、アプリのすべてのインスタンスが次のようになります。

  1. のようなクエリを実行するupdate resource_lock set resource_key = 1 where resource_key is null'。 (もちろん、サーバー固有のID、タイムスタンプなどを挿入することもできます。)
  2. 0行が更新された場合:何もしない - 別のアプリインスタンスはすでにリソースを取得しています。
  3. 1行が更新された場合:リソースを取得して設定します locking_key 戻る null.

これには2つの利点があります。

  • サーバーのいずれかが失敗した場合、リソースはまだ実行されているサーバーによってフェッチされます。
  • ロックをデータベースに残します。これにより、自分で実装することができません。

おそらくあなたが知っているが、情報に基づいた答えを挑戦するようにする質問には説明されていない要件がいくつかあります。これらの質問のいくつかは次のとおりです。

  • タスクは正常に完了する必要がありますか?
  • タスクが正常に完了しない場合、「誰が知る必要があり、どのタイプのアクションを実行する必要がありますか?
  • タスクを再度実行する時が来たときにタスクが完了していない場合の動作は何ですか?実行する必要がありますか?
  • 指定されたインターバルでジョブが実行されることはどれほど重要ですか?インターバルが5分ごとである場合、5分ごとに行う必要がありますか、それともタスクは5分10秒後に実行できますか?

最初のステップは、定期的なタスクの実行方法に答えることです。 1つのオプションはWindowsスケジュールされたタスクですが、それは本質的にあまり利用可能ではありませんが、それを回避することは可能かもしれません。 SQL Serverを使用している場合、SQL Serverの一部としてフェイルオーバーするため、SQL Serverエージェントをスケジューラとして使用することがもう1つの選択肢です。

決定する次のステップは、WCFアプリケーションを呼び出す方法です。最も簡単なオプションは、NLB IPアドレスを介してWCFサービスを呼び出すジョブをトリガーすることです。これは、データベースサーバー(またはそのゾーン内の他のサーバー)がアプリケーションゾーンに呼び出している場合、NO-NOと見なすことができます(もちろん、MSDTCなどの例外は常にあります)。

別のオプションは、キューモデルを使用することです。これは、ほとんどの状況で最も信頼できるものです。たとえば、SQL Serverエージェントは、ストアドプロシージャを実行して、キューテーブルにレコードを入力できます。次に、各アプリケーションサーバーで、サービスを処理するキューレコードを探して投票できます。キュー内のレコードへのアクセスは、データベースによってシリアル化され、最初のサーバーがジョブを実行する(およびそのジョブは1回しか実行されない)。

この回答の冒頭の質問への回答に応じて、さらにエラー処理を追加する必要がある場合があります。外部リソースの取得が通常かなり短い場合は、キューレコードを単純にロックしておくことをお勧めします。 select for update タスクが完了したら、ステータスを更新します(または、必要に応じてレコードを削除します)。これにより、他のサービスインスタンスが別のサーバーで処理されているときにレコードの処理をブロックし、トランザクションの処理中にクラッシュが発生した場合、クラスター内の別のサービスがレコードを取得できるようになります。 (ただし、トランザクションタイムアウトを必要と思う限り、トランザクションタイムアウトを増やすことができます。)

データベースのロックを長時間保持することが実行不可能な場合は、ロジックを変更してサービスに監視を追加できます。これで、ジョブが処理を開始すると、そのステータスがキューに変更され、実行中のサーバーがレコードで更新されます。ある種のサービスステータステーブルを作成でき、各サービスインスタンスは、投票するたびに現在を更新します。これにより、クラスター内の他のサービスは、実行中のジョブを再処理することができますが、実行中のサービスは特定の期間内に「チェックイン」されていません。

このアプローチには制限もあります。タスクが実際に完了したが、どういうわけかデータベース接続が失われた場合はどうなりますか?ジョブは再び実行される可能性があります。もちろん、他の非輸送リソース(Web要求、ファイルシステムなど)と組み合わせた原子データベースアクションを備えているという問題は簡単に解決されるとは思いません。私はあなたがファイルか何かを書いていると仮定しています - 外部コンテンツもデータベースに配置されている場合、単一のトランザクションはすべてが一貫していることを保証します。

シンプルさの観点から、探していることを達成するための最も迅速/最も簡単な方法は、すべての要求に対してマシンが選択されるように、クラスターを「ラウンドロビン」することです(クラスター管理サービスなど)リクエストを処理します。実際のクライアントリクエストは、それを処理するマシンに直接送られません。代わりに、それらは単一のエンドポイントを指します。これは、可用性と負荷に基づいて、着信要求をマシンに配布するプロキシとして機能します。参照されたリンクを引用するには、

ネットワークロードバランシングは、マシンのプールを構成する方法であるため、リクエストに応答します。サーバーファームで実装されている最も一般的に見られます。これは、Webサイトまたはターミナルサーバーファームの負荷を広げる同一の構成マシンです。また、ファイアウォール(ISA)ファーム、VPNアクセスポイントに使用することもできます。実際には、単一のマシンの負荷が多すぎるTCP/IPトラフィックがあるときはいつでも、単一のマシンとして表示することもできます。アクセス目的。

アプリケーションが「アクティブ」であることに関しては、その要件は「アクティブ」であろうと「パッシブ」であろうと、この方程式はこの方程式に因子を象徴していませんが、アプリケーションはまだサーバーにリクエストを行います。

HTTPスタイルのリクエストを提供するための商用ロードバランサーが存在するため、調べる価値があるかもしれませんが、W2K8のロードバランシング機能を使用すると、それらをタップするのが最適です。

Win2k8でそれを構成する方法の詳細については、参照してください これ 記事。

この記事 はるかに技術的であり、NLBを交換で使用することに焦点を当てていますが、原則はまだあなたの状況に適用されるべきです。

こちらをご覧ください NLBセットアップと構成の別の詳細なウォークスルー。

それに失敗すると、アプリケーションコードはNLBが存在することを厳密に認識していない(そしてそうすべきではない)ため、ServerFaultで検索 /投稿することで十分にサービスされる可能性があります。

編集:別のリンクを追加しました。

編集(2番目):OPは、「アクティブ」対「パッシブ」コンセプトで私の誤った結論を修正しました。それに対する私の答えは、私の元の答えに非常に似ています。「アクティブ」サービス(WCFを使用しているため、簡単にWindowsサービスになる可能性がある)を2つの部分に分割できることを保存します。実際の処理部分と、管理部分。管理部分は単一のサーバーで実行され、実際の処理を行う他のサーバーのラウンドロビンロードバランサーとして機能します。元のシナリオよりもわずかに複雑ですが、私はそれがかなりの柔軟性を提供するだけでなく、処理と管理のロジックをきれいに分離すると信じています。

場合によっては、3つのマシンがすべてのリクエストを実行し、最後に結果を比較して、結果が絶対に正しく、ハードウェアの障害が処理中に問題を引き起こしていないことを確認することが有用であることがあります。これは、たとえば飛行機のために彼らがしていることです。

それ以外の場合は、新しいサービスに切り替えるために1つの悪い結果と小さなダウンタイムを持つことで暮らすことができますが、次のサービスを大丈夫にしたいだけです。その場合、ハートビートモニターを備えたソリューション番号3は優れたセットアップです。

また、人々はSMSでサービスがダウンしていることをSMSで通知する必要があり、アプリケーションは、何らかのフェールオーバーを手動で実行するまで、時代遅れのデータを使用するだけです。

あなたの場合、後者はおそらくあなたにとってより有用だと思います。もう一方の端でのサービスに実際に依存することはできないため、その場合に何をすべきかについての解決策を考え出す必要があります。時代遅れのデータを返すことはあなたにとって良いことかもしれません、そしてそれはそうではないかもしれません。言わなければならないのは申し訳ありません:それは依存します。

Zookeeperは、分散ロックの有効なケースを作成します。 Zookeeperには、データを備えたディレクトリのようなzノードがあります。

Netflixキュレーターでさえ、すでに多くのレシピが既に行われ、使用しています。いいね:リーダーの選挙、分散ロックなど。

C#のZookeeperのクライアントがいると思います。このオプションを絶対に試してみてください。 #オプション3

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top