4

我有一个 azure 存储表,其中我有一堆任务要在某个时间由工人角色完成。例子:

       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”的日期时间列。还有一个名为“RunEvery”的列存储必须执行任务的时间。worker 角色不断迭代所有任务,并为每个任务使用以下方法检查“LastRun”列:

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

如果工作者角色连续运行,那么消耗资源呢?我们如何才能获得资源?或者我可以以更好的方式实现这一点吗?你有什么建议?

4

6 回答 6

12

添加到@Simon Munro 的答案:在没有外部调度程序依赖的情况下实现任务调度的另一种方法是在您的工作角色中使用 Quartz 库( http://quartznet.sourceforge.net/ )。我在其中一个项目中使用过它,效果非常好。就计划任务而言,它为您提供了很大的灵活性。您仍然需要使用 blob 租赁和 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 上的租约之类的东西来“锁定”您的任务。

尽管您正在查看的作业数量可能很多,但一个好的方法是使用 cron 作业服务,例如setcronjob新发布的aditi 云服务。您将任务实现为 Web 服务并将它们连接到外部服务。

就您的资源利用率而言,每隔几分钟触发一次事件的计时器不会在资源方面使用太多。您可以有一个线程来执行从队列中读取的任务(甚至是ConcurrentQueue),因此您一次只执行一个任务(如果精确的时间不是问题的话)。其他线程/定时器/事件可以将任务添加到队列中。

于 2013-01-22T21:05:01.510 回答
1

您当前的方法似乎无法扩展到多个工作角色。

我建议进行一些更改:

  1. 使用存储队列来存储准备执行的任务。当队列准备好运行时,向队列添加一条消息,这样其他工作者角色就可以参与执行任务。您还可以使用队列来隐藏任务,直到它也准备好运行。

  2. 在读取和更新计划表时锁定 blob 资源,这样只有一个辅助角色可以计划任务。

请记住,您的任务可能(在极少数情况下)执行两次,因此请尝试为此进行设计。

为了避免过于频繁地访问队列或表,如果您的队列和计划为空,请考虑使用 Thread.Sleep 以指数方式退出。

此博客包含可能有助于您实施的更多详细信息。

于 2013-01-22T22:55:32.873 回答
1

虽然 Gaurav Mantri 写了一篇很棒的文章,展示了如何以安全的方式将 Quartz 与 Azure 存储队列/表/Blob 连接起来,但这个解决方案并不能满足我正在处理的应用程序的要求。在 Azure 事务成本方面,同时使用 Queue/Blobs/Table 可能会变得昂贵,这是我主要关心的问题之一。

我目前正在开发一个需要安排大量任务的 Azure 应用程序,所以我在几天前编写了自己的“家庭”解决方案,但它与 Quartz 的质量相差甚远,到目前为止它只是一个原型,尚未经过正确测试,但对我来说似乎工作正常。

设计目标

  • 尽可能优化存储事务。这仅使用 RangeQueries 和 BatchOperations 完成,事务尽可能地分组。调度和获取 50 个任务只需 3 个存储事务即可完成。
  • 每个 ScheduledTask 都必须正确“提交”,(否则稍后将再次启动)。
  • 简单且非侵入性的 API
  • 调度程序类线程安全,并且在多个实例中应该是整体安全的

并发问题是使用删除操作解决的,如果任务已经同时出队,该操作将失败。(内部处理)

我刚刚在这里发布了这个项目。这本来不是要出版的,被认为是这样的。当您发现错误时请告诉我。

于 2013-02-02T23:52:30.500 回答
0

如果任务不需要过于频繁地运行,一种方法是创建一个 Azure SQL 表并为每次执行生成一行。作为列,您将拥有执行时间和应该运行的任务的一些标识符。因此,如果一个任务每天运行一次,并且您希望它保持运行 5 年,您将放置 5*365 行。

工作人员将运行无限循环,从该表中选择执行时间小于当前时间但尚未执行的任务。对于多个工作人员,您需要处理事务以确保每个任务仅由一个工作人员执行。

或者,您甚至可以对 Azure 服务总线使用类似的机制。服务总线支持预定传递,并且消息的存活时间似乎没有上限。使用服务总线,您只需为每个计划执行推送消息,并将交付时间作为执行时间。然后工作人员将从队列中弹出消息。

使用服务总线的一个好处是您可以轻松添加更多工作人员,而不必担心他们会开始处理相同的任务。

于 2013-04-21T15:10:25.163 回答
0

可能是在回答一个老问题。但与其使用重量级的 Cron 类库(其中很多),不如花点时间学习 Rx The Reactive Extensions 并在那里使用 Timer 可能是值得的。来自 Rx wiki 的一个简单示例

于 2014-09-09T11:02:07.573 回答