WebファームのWindowsサービス(同時実行の競合を防ぐ方法)
-
07-07-2019 - |
質問
先を見て、Webファームがいつ作成されるか...
電子メールの送信、ファイルのサムネイル化/処理など、さまざまなバックグラウンドタスクを実行するさまざまなWindowsサービスアプリケーションがあります。
サーバーファーム環境では、理論上、各マシンに各サービスをインストールして実行できますが、ビジネスオブジェクトベースの「先書き勝利」による競合が発生する可能性があります。またはタスクの望ましくない複製。例:同じメールが何度も送信される。
" first-write-wins"シナリオは、問題を解決するかアイテムをスキップするコードまたはロジックによって克服できます。 (基本的なキューイングメカニズム(クエリリストとプロセスレコード)の場合は、再度試行されます)
タスクを複製するために、トランザクションでタスクを実行して他のプロセスが同じリソースを取得するのを防ぐことができますが、それらは待機するだけで、再び起こることに基づいてログインを処理する必要がありますか?これは本当ですか?
タスクの重複を防ぐために、「ロックフラグ」を書き込むメカニズムを構築することを考えています。起動する最初のサービスによって設定されるデータベースに。このフラグは日付が付けられ、サービスのインスタンスを参照します。 「所有する」サービスフラグはタスクを実行し、定期的にこの日付を更新します。サービスがフラグを所有していない状況では、各サービスにタイムアウト/トレランス設定もあり、トレランスをチェックし、必要に応じて引き継ぎます。
これは妥当な解決策のように聞こえますか、それともその段階でより良いメッセージキューベースの解決策に進むべきですか(また、それが農場環境でどのように機能するかわかりませんか?
技術:C#/ ASP.NET / SQL Server
解決
2つのメカニズムを考えることができます。
-
すべてのタスクがデータベースアクティビティから派生している場合、新しい「タスク」を作成できます。テーブルおよびアクティビティのトリガーを設定して、タスク情報を含む新しいレコードを挿入します。その後、Windowsサービスは「タスク」をポーリングできます。テーブルを作成し、アトミックな選択および削除トランザクションを使用して、1つのサービスのみがそれを実行するようにします。
-
メッセージキューを使用してタスクをドロップし、Windowsサービスにキューをポーリングさせることができます。キューに入れられた各メッセージは、単一のサービスによってのみキューから取り出すことができるため、各タスクが一度だけ実行されることを保証できます。もちろん、メッセージキューの負荷について心配する必要があります。アプリケーションによっては、AmazonのSimple Queue Serviceのようなものを使用できます。これにより、信頼性とスケーラビリティを心配する必要がなくなります。