4

特定の時間にワーカー ロールによって完了するタスクが多数ある Azure ストレージ テーブルが 1 つあります。例:

       Task 1: -> run every 5 min
       Task 2: -> run every 1 min
       Task 3: -> run every 10 min
       Task 4: -> run every 1 min
       Task 5: -> run every 5 min
       ...........................
       Task 1000: -> run every 1 min

このアプローチは正しいですか: 各タスクには、「LastRun」と呼ばれる DateTime 列があります。タスクを実行する必要がある時間を格納する「RunEvery」という別の列があります。worker ロールは、すべてのタスクを継続的に反復処理し、各タスクについて、次の方法で列 "LastRun" をチェックします。

      DateTime currentTime = DateTime.Now;
      if (currentTime >= (myTask.LastRun + myTask.RunEvery))
      {
           myTask.Execute()
      }
      else
      {
           Check.Next.Task.InTable();
      }

worker ロールが継続的に実行される場合、リソースの消費はどうなるでしょうか? どうすればリソースをスピアできますか? または、これをより良い方法で実装できますか? あなたのアドバイスは何ですか?

4

6 に答える 6

12

@Simon Munro の回答に追加: 外部スケジューラに依存せずにタスク スケジューリングを実装するさらに別の方法は、worker ロールで Quartz ライブラリ ( http://quartznet.sourceforge.net/ ) を使用することです。プロジェクトの1つで使用しましたが、非常にうまく機能します。タスクのスケジューリングに関する限り、これにより多くの柔軟性が得られます。ワーカー ロールの複数のインスタンス間での同時実行の問題に対処するには、ブロブ リースと Windows Azure キューを作成する必要があります。

更新: これに触発されて、ここで読むことができる同じことに関するブログ投稿を書きました: http://gauravmantri.com/2013/01/23/building-a-simple-task-scheduler-in-windows-azure/ .

于 2013-01-23T02:22:37.340 に答える
3

独自のスケジュールを設定することはお勧めできません。読み取っているデータをロックしない限り、あらゆる種類の問題が発生します。たとえば、同じワーカー ロールを数十または数百にスケールアップして、各ジョブが必要な回数だけ実行されるようにすることはできますか。blob storageのリースなどを使用して、タスクを「ロック」する必要がある場合があります。

見ているジョブの数が多すぎるかもしれませんが、新しくリリースされたaditi クラウド サービスでsetcronjobのような cron ジョブ サービスを使用することをお勧めします。タスクを Web サービスとして実装し、それらを外部サービスに接続します。

リソース使用率に関しては、数分ごとにイベントをトリガーするタイマーはリソースをあまり消費しません。タスクをキュー ( ConcurrentQueueでさえも) から読み出されるように実行する単一のスレッドを持つことができるため、一度に1 つのタスクのみを実行します (正確なタイミングが問題にならない場合)。他のスレッド/タイマー/イベントは、タスクをキューに追加できます。

于 2013-01-22T21:05:01.510 に答える
1

Gaurav Mantri は、Quartz を Azure Storage Queue/Table/Blob と安全に接続する方法を示す素晴らしい記事を作成しましたが、このソリューションは、私が取り組んでいるアプリケーションの要件を満たしていませんでした。Queue/Blobs/Table を同時に使用すると、Azure のトランザクション コストが高くなる可能性があり、これが私の主な懸念事項の 1 つでした。

私は現在、大量のタスクをスケジュールする必要がある Azure アプリケーションを開発しているので、数日前に独自の「ホーム」ソリューションを作成しましたが、Quartz の品質にはほど遠いものであり、これまでのところ単なるプロトタイプです。まだ適切にテストされていませんが、それでもうまくいくようです。

設計目標

  • ストレージ トランザクションを可能な限り最適化します。これは RangeQueries と BatchOperations のみを使用して行われ、トランザクションは可能な限りグループ化されます。スケジューリングとフェッチ 50 タスクは、3 つのストレージ トランザクションのみで実行できます。
  • 各 ScheduledTask は適切に「コミット」する必要があります (そうしないと、後で再度起動されます)。
  • シンプルで邪魔にならない API
  • スケジューラ クラス スレッド セーフであり、複数のインスタンスにわたって全体的に安全である必要があります

並行性の問題は、タスクが同時にキューから取り出された場合に失敗する削除操作を使用して解決されます。(社内処理)

ここでプロジェクトを公開しました。これはもともと公開することを意図したものではなく、これと見なすことを目的としていました。バグを見つけたら教えてください。

于 2013-02-02T23:52:30.500 に答える
1

現在のアプローチは、複数のワーカー ロールにスケールアップしないように見えます。

いくつかの変更を提案します。

  1. ストレージ キューを使用して、実行準備が整ったタスクを格納します。実行の準備ができたら、キューにメッセージを追加します。これにより、他のワーカー ロールがタスクの実行に参加できるようになります。キューを使用して、実行準備が整うまでタスクを非表示にすることもできます。

  2. スケジュール テーブルの読み取りと更新中に BLOB リソースをロックすると、1 つのワーカー ロールだけがタスクをスケジュールできます。

タスクが (まれに) 2 回実行される可能性があることに注意してください。そのための設計を試みてください。

キューまたはテーブルに頻繁にヒットするのを避けるために、キューとスケジュールが空の場合は Thread.Sleep で指数関数的にバックオフすることを検討してください。

このブログには、実装に役立つ詳細が含まれています。

于 2013-01-22T22:55:32.873 に答える
0

タスクをあまり頻繁に実行する必要がない場合、1 つの方法は、Azure SQL テーブルを作成し、実行ごとに行を生成することです。列として、実行時間と、実行する必要があるタスクの識別子があります。したがって、タスクが 1 日に 1 回実行され、それを 5 年間実行し続けたい場合は、5*365 行を配置します。

ワーカーは無限ループを実行し、そのテーブルから、実行時間が現在の時間よりも短いがまだ実行されていないタスクを選択します。複数のワーカーを使用すると、トランザクションを操作して、各タスクが 1 つのワーカーだけで実行されるようにする必要があります。

または、Azure Service Bus で同様のメカニズムを使用することもできます。サービス バスはスケジュールされた配信をサポートしており、メッセージの有効期限に上限はないようです。Service Bus を使用すると、配信時間を実行時間として、計画された実行ごとにメッセージをプッシュするだけです。その後、ワーカーはキューからメッセージをポップします。

Service Bus を使用する利点の 1 つは、ワーカーが同じタスクで作業を開始するのではないかと心配することなく、ワーカーを簡単に追加できることです。

于 2013-04-21T15:10:25.163 に答える
0

古い質問に答えているかもしれません。しかし、重い Cron のようなライブラリ (非常に多くのライブラリ) を使用する代わりに、Rx The Reactive Extensions を学習し、そこで Timer を使用するために少し時間を費やすことはおそらく価値があります。Rx wiki の簡単な例

于 2014-09-09T11:02:07.573 に答える