効率的なクラウドキュー管理(Azureキュー)

「AtContent.comサービスの内部構造とアーキテクチャ」シリーズのこの4番目の記事では、Azureサービス(ワーカーロール)のインスタンスを使用したジョブのバックグラウンド処理に精通することを提案します。



インスタンス間のプライマリ通信チャネルとしてAzureキューを使用することをお勧めします。 ただし、このチャネルのみを使用すると、サービスインスタンスを最も効率的に使用できません。 したがって、この記事では、どのように学習します







図からわかるように、Azureの標準SDKツールは、キュー(Azure Queue)のみを介した相互作用のシナリオを想定しています。 同時に、Azureサービスインスタンスは、アプリケーションインスタンスがキューを介してジョブを送信するポイントを認識しません。 したがって、彼は定期的にキュー内のジョブをチェックする必要があり、これによりいくつかの問題と不便が生じます。



問題の1つは、タスクの処理の遅延です。 次の理由で発生します。 サービスインスタンスは、キュー内のジョブを定期的にチェックする必要があります。 さらに、このようなチェックを頻繁に行うと、Azure Queueに対して多数のトランザクションが生成されます。 そのようなタスクが同時にキューに入れられることがめったにない場合、多数の「アイドル」トランザクションが発生します。 キュー内のジョブの可用性をあまり頻繁にチェックしない場合、そのようなチェックの間隔は長くなります。 したがって、サービスインスタンスによってチェックされた直後にタスクがキューに入る場合、次の間隔の開始時にのみ処理されます。 これにより、メッセージ処理に大幅な遅延が生じます。



もう1つの問題は、アイドルトランザクションです。 つまり、キューにメッセージがなくても、サービスインスタンスはこれらのメッセージの存在を確認するために、引き続きメッセージに接続する必要があります。 これによりオーバーヘッドが発生します。



SDKが提供する標準的なアプローチでは、トランザクションコストとジョブ処理の遅延量のいずれかを選択する必要があります。 一部のシナリオでは、処理時間はわずかであり、タスク自体はかなり定期的に到着します。 この場合、SDKからの推奨事項に従って、キューから定期的に選択することでタスクを処理できます。 しかし、タスクが不規則に入ってきた場合、急増と停滞が生じる可能性があり、標準的な方法でタスクを処理する効率が低下します。



インスタンスとロール間のメッセージングメカニズムを使用して、これらの問題を解決できます。 シリーズの以前の記事( http://habrahabr.ru/post/140461/ )で説明されていました。 このメカニズムに関するいくつかの言葉。 これにより、あるインスタンスから別のインスタンスに、またはロールのすべてのインスタンスにメッセージを転送できます。 これを使用すると、インスタンスでさまざまなハンドラーを実行できます。これにより、たとえば、インスタンスの状態を同期できます。 タスクに適用されると、タスクをキューに追加した直後にキューの処理を開始できます。 同時に、キュー内のジョブの可用性を常に確認する必要はなく、「アイドル」トランザクションが排除されます。





このメカニズムをより詳細に検討すると、次のことがわかります。





Azureアプリケーションインスタンスは、タスクをAzureキューに追加し、Azureサービスインスタンスにメッセージを送信します。 次に、メッセージはハンドラーをアクティブにします。 ハンドラーのその他のアクションは、設定によって異なります。 設定にキュー処理がすでに実行されているレコードがある場合、それを再起動しても意味がありません。 それ以外の場合、ハンドラーは処理を開始し、対応するレコードを設定に追加します。 彼は進行中のキューからタスクを選択し、終了するまで続行します。



ハンドラー設定はさまざまな方法で保存できます。 たとえば、インスタンスのメモリ(最も信頼性の高い方法ではありません)、インスタンスのストレージ、またはブロブのストレージ(Azure Blob Storage)。



キューを処理するためのCPlaseライブラリには、キューハンドラーを作成できる特別なQueueクラスがあります。 このため、ライブラリにはIWorkerQueueHandlerインターフェイスとその拡張機能もあり、キューを操作するのに便利です。

public interface IWorkerQueueHandler { bool HandleQueue(string Message); } public static class WorkerQueueHandlerExtensions { private static string CleanUpQueueName(string DirtyQueueName) { return DirtyQueueName.Substring(0, DirtyQueueName.IndexOf(",")).ToLowerInvariant().Replace(".", "-"); } public static string GetQueueName(this IWorkerQueueHandler Handler) { return CleanUpQueueName(Handler.GetType().AssemblyQualifiedName); } public static string GetQueueName(Type HandlerType) { return CleanUpQueueName(HandlerType.AssemblyQualifiedName); } }
      
      





インターフェイスは非常にシンプルで、キューからのメッセージを処理するすべてのロジックを実装するメソッドが1つだけあります。 ただし、拡張機能には1つの目標があります。ハンドラーのタイプからキューの受け入れ可能な名前を取得することです。 これにより、プログラマーがさまざまなハンドラーのキュー名を制御する必要がなくなります。



Queueクラス自体は、Azureストレージにない場合、必要なキューの選択とその作成を実装します。 キューにタスクを追加するだけでなく、Azureサービスのインスタンスにメッセージを送信します。 この場合、すでに述べたように、インスタンスとロール間でメッセージを交換するメカニズムが使用されます。

 public static CloudQueue GetQueue(string QueueName) { CreateOnceQueue(QueueName); return queueStorage.GetQueueReference(QueueName); } public static bool AddToQueue<QueueHandlerType>(string Task) where QueueHandlerType : IWorkerQueueHandler { var Queue = GetQueue(WorkerQueueHandlerExtensions.GetQueueName(typeof(QueueHandlerType))); return AddToQueue<QueueHandlerType>(Queue, Task); } public static bool AddToQueue<QueueHandlerType>(CloudQueue Queue, string Task) { try { var Message = new CloudQueueMessage(Task); Queue.AddMessage(Message); Internal.RoleCommunicatior.WorkerRoleCommand(typeof(QueueHandlerType)); return true; } catch { return false; } }
      
      





キューに入ってくるタスクのおよその量とストリームのおおよその構造を知っていれば、このようなソリューションの利点を簡単に計算できます。 そのため、たとえば、タスクが主に20〜23時間の夕方に発生する場合、間隔を空けてタスクをチェックするほとんどの時間は「アイドル」になります。 そして、21時間の間、結果なしでキューからタスクを選択すると計算するのは簡単です。 さらに、このようなチェックが1秒間に1回実行されると、1日に約75,000の「アイドル」トランザクションが発生します。 10,000あたり0.01ドルの取引額では、この金額は1日あたり0.075ドルまたは1か月あたり2.25ドルになります。 ただし、100の異なるキューがある場合、1か月あたりの追加費用は225ドルになります。



間隔を置いたジョブ処理の反対側は、処理の遅延です。 一部のタスクでは、このような遅延はそれほど大きくありません。 しかし、できる限り迅速に処理する必要があるタスクがあります。たとえば、著者、ディストリビューター、サービス間の収入の分配などです。 作成者は、しばらくしてからではなく、アカウントで稼いだお金をすぐに見たいので、このタスクは処理時間に敏感です。 さらに、タスクのフローが非常に大きい場合、処理間の1秒の遅延により、処理されたタスクのフローが1分あたり60に制限されます。これにより、処理が即座に実行されます。 したがって、負荷がピークのとき、ジョブフローはキューを非常に迅速に膨張させる可能性があります。



特定の時間間隔でキューからタスクを処理するこのアプローチでは、キューからタスクを選択する「アイドル」試行のコストとピーク負荷での処理の遅延とのバランスを取る必要があります。 提案されたソリューションにより、間隔とアイドルトランザクションを処理する必要がなくなります。 また、キューからタスクの処理を遅延なく、高い効率で、「アイドル」トランザクションの追加コストなしで構築できます。



また、キューを操作するメカニズムはCPlase Open Sourceライブラリの一部であり、まもなく公開され、すべての人が利用できるようになることに注意してください。



シリーズを読む:




All Articles