Azure工作者角色 - 后台任务计划

时间:2013-01-22 19:45:49

标签: azure azure-storage azure-worker-roles

我有一个azure存储表,我有一堆任务要在某个时间由一个worker角色完成。例如:

       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();
      }

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

6 个答案:

答案 0 :(得分: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/

答案 1 :(得分:3)

滚动自己的日程安排并不是一个好主意。除非您锁定正在阅读的数据,否则会遇到各种问题。例如,您可以扩展到数十个或数百个相同的工作者角色,并确保每个作业只运行所需的次数。您可能需要使用leases on blob storage等内容来“锁定”您的任务。

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

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

答案 2 :(得分:1)

您当前的方法似乎不会扩展到多个工作人员角色。

我建议做一些改变:

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

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

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

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

    This blog包含可能有助于您实施的更多详细信息。

答案 3 :(得分:1)

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

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

设计目标

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

使用Delete操作解决并发问题,如果任务已经同时出列,则该操作将失败。 (内部处理)

我刚刚发布了项目here。这本来不是要发表的,不应该被认为是这样。当你发现错误时请告诉我。

答案 4 :(得分:0)

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

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

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

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

答案 5 :(得分:0)

可能会回答一个老问题。但是,与使用像图书馆这样的重量级Cron(其中很多)相比,可能值得投入一点时间来学习Rx The Reactive Extensions,并在那里使用Timer。 A simple example from the Rx wiki