Queue Centric 工作模式的故障处理
Failure handling for Queue Centric work pattern
我计划在我的一个应用程序中使用here所述的以队列为中心的设计。这基本上包括使用 Azure 队列,其中工作请求从 UI 排队。工作人员从队列中读取、处理和删除队列中的消息。
worker 完成的 'work' 是在事务内完成的,因此如果 worker 在完成之前失败,重新启动时它会再次获取相同的消息(因为它尚未从队列中删除)并尝试再次执行操作(最多重试次数)
要缩放 我可以使用两种方法:
- 多个工作人员,每个工作人员都有一个单独的队列。因此,如果我有五个工作人员 W1 到 W5,我有 5 个队列 Q1 到 Q5,每个工作人员都知道要从哪个队列读取并且故障处理类似于一个队列和一个工作人员的情况
- 一个队列和多个工人。 failure/Retry 这里的处理会更加复杂,最终可能会使用消息队列中的 'Invisibility' 时间来确保没有两个工作人员选择相同的工作。必须计算隐身时间以确保它足以让作业完成,但又不会足够长以致在很长一段时间后执行重试。
想知道第一种方法是否正确?上面第二种方法中处理故障的稳健方法是什么?
您最好采用方法 2 - 单个队列,但有多个工作人员。
这样更好,因为:
- 将消息传递到队列的进程只需要知道一个队列端点。这降低了这一端的复杂性;
- 扩展从队列中拉出的工作线程的数量现在与任何代码/配置更改无关 - 您可以更轻松地(在运行时)扩展和缩减
如果你担心 visibility
,你可以先选择一个默认的 timespan
,然后如果 worker 看起来耗时太长,它可以定期调用 UpdateMessage()更新消息的可见性。
最后,如果您的工作人员超时并且未能完成消息的处理,其他工作人员将再次拾取它以重试。您还可以使用消息的 DequeueCount 属性 来管理重试次数。
Multiple workers each with a separate queue. So if I have five workers
W1 to W5, I have 5 queues Q1 to Q5 and each worker knows which queue
to read from and failure handling is similar as the case with one
queue and one worker
通过这种方法,我发现了以下问题:
- 这种方法使您的体系结构紧密耦合(从而打破了使用队列的全部目的)。因为每个 worker 角色监听一个专用队列,负责在队列中推送消息的 Web 应用程序总是需要知道有多少个 worker 运行。任何时候你扩大或缩小你的工作者角色,一些你需要告诉网络应用程序的方式,以便它可以开始在适当的队列中推送消息。
- 如果某个辅助角色实例出于某种原因被关闭,则可能会因为其他辅助角色实例正在其专用队列上工作而无法处理某些消息。
- 根据 Web 应用程序将消息推送到队列中的方式,辅助角色实例的利用率可能 utilization/over 不足。为了获得最佳利用率,Web 应用程序应该了解工作者角色的利用率,以便它可以决定将消息发送到哪个队列。这当然不是 Web 应用程序希望做的事情。
我相信#2 是正确的方法。 @Brendan Green 在他的回答中很好地涵盖了你对#2 的担忧。
我计划在我的一个应用程序中使用here所述的以队列为中心的设计。这基本上包括使用 Azure 队列,其中工作请求从 UI 排队。工作人员从队列中读取、处理和删除队列中的消息。
worker 完成的 'work' 是在事务内完成的,因此如果 worker 在完成之前失败,重新启动时它会再次获取相同的消息(因为它尚未从队列中删除)并尝试再次执行操作(最多重试次数)
要缩放 我可以使用两种方法:
- 多个工作人员,每个工作人员都有一个单独的队列。因此,如果我有五个工作人员 W1 到 W5,我有 5 个队列 Q1 到 Q5,每个工作人员都知道要从哪个队列读取并且故障处理类似于一个队列和一个工作人员的情况
- 一个队列和多个工人。 failure/Retry 这里的处理会更加复杂,最终可能会使用消息队列中的 'Invisibility' 时间来确保没有两个工作人员选择相同的工作。必须计算隐身时间以确保它足以让作业完成,但又不会足够长以致在很长一段时间后执行重试。
想知道第一种方法是否正确?上面第二种方法中处理故障的稳健方法是什么?
您最好采用方法 2 - 单个队列,但有多个工作人员。
这样更好,因为:
- 将消息传递到队列的进程只需要知道一个队列端点。这降低了这一端的复杂性;
- 扩展从队列中拉出的工作线程的数量现在与任何代码/配置更改无关 - 您可以更轻松地(在运行时)扩展和缩减
如果你担心 visibility
,你可以先选择一个默认的 timespan
,然后如果 worker 看起来耗时太长,它可以定期调用 UpdateMessage()更新消息的可见性。
最后,如果您的工作人员超时并且未能完成消息的处理,其他工作人员将再次拾取它以重试。您还可以使用消息的 DequeueCount 属性 来管理重试次数。
Multiple workers each with a separate queue. So if I have five workers W1 to W5, I have 5 queues Q1 to Q5 and each worker knows which queue to read from and failure handling is similar as the case with one queue and one worker
通过这种方法,我发现了以下问题:
- 这种方法使您的体系结构紧密耦合(从而打破了使用队列的全部目的)。因为每个 worker 角色监听一个专用队列,负责在队列中推送消息的 Web 应用程序总是需要知道有多少个 worker 运行。任何时候你扩大或缩小你的工作者角色,一些你需要告诉网络应用程序的方式,以便它可以开始在适当的队列中推送消息。
- 如果某个辅助角色实例出于某种原因被关闭,则可能会因为其他辅助角色实例正在其专用队列上工作而无法处理某些消息。
- 根据 Web 应用程序将消息推送到队列中的方式,辅助角色实例的利用率可能 utilization/over 不足。为了获得最佳利用率,Web 应用程序应该了解工作者角色的利用率,以便它可以决定将消息发送到哪个队列。这当然不是 Web 应用程序希望做的事情。
我相信#2 是正确的方法。 @Brendan Green 在他的回答中很好地涵盖了你对#2 的担忧。