5

我在此处使用 WEBJOBS_SHUTDOWN_FILE 和此处使用 Cancellation Tokens 阅读了有关正常关闭的信息,因此我了解正常关闭的前提,但是我不确定它们将如何影响正在处理队列消息的 WebJobs。

所以这是场景:

  1. 我有一个带有监听队列功能的 WebJob。
  2. 消息被添加到队列并且作业开始处理。
  3. 在处理过程中,有人推动开发,触发重新部署。

假设我已将 WebJobs 连接到 git push 上部署,此部署还将触发 WebJobs 被更新,这(据我所知)将启动作业中的某种关闭工作流。所以我有几个问题源于此。

  1. 正在处理队列消息的作业会在作业退出之前完成对消息的处理吗?或者任何关闭通知本质上都被视为“这个婊子即将关闭。如果你没有任何东西可以处理它,你就是 SOL。”
  2. 如果我们是 SOL,那么我们处理关闭的最佳选择是否本质上是将您正在做的任何事情包装在相当于 DB 事务中并以所有更改在关闭时回滚的方式实现您的关闭处理程序?
  3. 如果队列消息正在处理中并且 WebJob 关闭,该消息是否会重新排队?如果不是,这是否意味着我的关闭处理程序需要处理重新排队该消息?
  4. 在通知作业需要关闭后,监听队列的函数是否有可能获取更多队列消息?

非常感谢这里的任何指导!此外,如果除了我提到的之外,还有其他关于如何处理作业关闭的有用链接,如果您能分享这些链接,那就太好了。

4

1 回答 1

4

经过不小的测试,我想我已经找到了我的问题的答案,我希望其他人可以从我的经验中获得一些见解。

注意:所有这些场景都使用 .NET 控制台应用程序和 Azure 队列进行了测试,因此我不确定 Blob 或表存储,或不同类型的作业文件类型将如何处理这些不同的场景。

  1. 在作业被标记为退出后,正在运行的触发函数将具有配置的时间量(宽限期)(默认为 5 秒,但我认为可以通过使用 settings.job 文件进行配置)在它们之前完成退出。如果它们没有在宽限期内完成,则函数退出。Main() (或您在其中声明 host.RunAndBlock() 的任何文件)将在之后完成运行任何代码host.RunAndBlock()最多在宽限期内剩余的时间(我不确定如果您使用无限循环而不是 RunAndBlock 会如何工作)。至于处理函数中的退出,您基本上可以“监听” CancellationToken,您可以将其传递给 IsCancellationRequired 的触发函数,然后相应地处理它。此外,如果您不自己处理退出,您就不是 SOL。嘘!见第 3 点。

  2. 如果您不处理退出,则您不是 SOL(请参阅第 3 点),但我确实认为将所有工作包装在事务中是个好主意,在您完全确定工作之前不会提交顺其自然。这样,如果您的函数在进程中退出,您就不必担心数据损坏。我可以想到一些场景,您可能希望在事务通过时提交事务(例如批处理作业),但是您需要构建数据或逻辑,以便在作业重新启动后不会重新处理先前处理的实体。

  3. 如果您不处理自己的工作辞职,您就不会遇到麻烦。我对幕后发生的事情的理解几乎不存在,但我很确定结果。如果一个函数正在处理队列消息并且在它完成之前被强制退出,不要害怕!当作业抓取要处理的消息时,它实际上会将其隐藏在队列中一段时间​​。如果您的函数在处理消息时退出,则该消息将在 x 时间后再次“变得可见”,并且它将被重新抓取并针对刚刚部署的可能更新的代码运行。

  4. 所以我对#4 的发现有大约 90% 的信心。我这么说是因为尝试测试它涉及在窗口之间快速切换,而实际上并不完全确定某些部分发生了什么。但这是我发现的:如果队列在宽限期 b4 中添加了新消息,则作业退出,我认为可能会发生以下两种情况之一:如果函数在作业之前没有轮询该队列退出,则消息将保留在队列中,并在作业重新启动时被抓取。但是,如果函数确实抓取了消息,它将被视为与任何其他被中断的消息相同:它将再次在队列中“变得可见”,并在重新启动作业时重新运行。

这几乎概括了它。我希望其他人会发现这很有用。让我知道您是否想对此进行阐述,我很乐意尝试。或者,如果我对它充满了并且您有很多更正,那么这些可能更受欢迎!

于 2015-01-28T06:37:37.480 回答