【问题标题】:Azure worker role - background tasks scheduleAzure 辅助角色 - 后台任务计划
【发布时间】:2014-09-09 19:02:07
【问题描述】:

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

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

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

【问题讨论】:

  • 几天前我可能已经写了你要找的东西。它是一个依赖于 Azure Tables 的 c# 调度程序,专为低事务消耗(每 50 个计划任务 3 个表存储事务)而设计,可在多个角色实例的上下文中使用。计划任务是“事务性的”,这意味着您必须调用 .Handled();当任务完成时(否则它将在“x”小时后再次触发)。如果有兴趣,我还需要清理一下代码,然后我可以在github上发布。
  • 绝对感兴趣!接缝有趣!请让我知道什么时候准备好!提前致谢!
  • 我正在发布它。
  • @uzul 你能告诉我你什么时候发表这篇文章吗?我在哪里可以找到它……不胜感激!

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


【解决方案1】:

添加到@Simon Munro 的答案:在您的工作角色中使用 Quartz 库 (http://quartznet.sourceforge.net/) 来实现没有外部调度程序依赖项的任务调度的另一种方法。我在其中一个项目中使用过它,效果非常好。就计划任务而言,它为您提供了很大的灵活性。您仍然需要使用 blob 租赁和 Windows Azure 队列来处理您的工作角色的多个实例之间的并发问题。

更新:受此启发,我写了一篇关于相同内容的博客文章,您可以在此处阅读:http://gauravmantri.com/2013/01/23/building-a-simple-task-scheduler-in-windows-azure/

【讨论】:

  • “在没有外部调度器依赖的情况下实现任务调度的另一种方法是使用 Quartz 库”。 Quartz 库在我看来是一个外部依赖项。
  • 也许我应该澄清一下我所说的外部依赖是什么意思——我的意思是一个外部服务(比如 Simon 提到的 aditi 云服务)。 Quartz 库已集成到您的项目中,并且是您项目的一部分。
  • 我明白了 :) 顺便说一句很棒的文章。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    我建议进行一些更改:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      设计目标

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

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

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

      【讨论】:

        【解决方案5】:

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

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

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

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-28
            • 2011-08-22
            • 2014-11-09
            相关资源
            最近更新 更多