Amazon SWF:至少必须有一名工作人员在运行,为啥?

Posted

技术标签:

【中文标题】Amazon SWF:至少必须有一名工作人员在运行,为啥?【英文标题】:Amazon SWF: at least one worker has to be running, why?Amazon SWF:至少必须有一名工作人员在运行,为什么? 【发布时间】:2013-02-05 20:53:43 【问题描述】:

我刚刚开始使用 AWS Ruby SDK 来管理简单的工作流程。我立即注意到的一种行为是,在提交新的工作流执行之前,必须至少运行一个相关的工作人员和一个相关的决策者。

如果我在启动工作程序和决策程序之前提交了新的工作流执行,那么即使我仍在超时限制内,任务也永远不会被执行。为什么是这样?根据对 HTTP 长轮询工作原理的描述,我希望任一应用程序在调用 poll() 时都能接收相关任务。

我在作业失败后遇到其他死锁情况(例如,由于工作人员或决策程序错误,或由于被终止)。有时,重新运行甚至只是启动全新的工作流执行将导致工作流执行死锁。初始决策任务显示在 AWS 控制台的工作流执行历史记录中,但决策者从未收到它们。诚然,我无法确认/将此问题简化为测试用例,但我怀疑它与上述问题有关。这种情况大约有 10% 到 20% 的时间发生;其余时间,一切正常。

需要提及的其他一些事情:我将单个任务列表用于按顺序运行的两个单独的活动任务。工作者和决策者都在轮询同一个任务列表。

这是我的工人:

require 'yaml' require 'aws' config_file_path = File.join(File.dirname(File.expand_path(__FILE__)), 'config.yaml') config = YAML::load_file(config_file_path) swf = AWS::SimpleWorkflow.new(config) domain = swf.domains['test-domain'] puts("waiting for an activity") domain.activity_tasks.poll('hello-tasklist') do |activity_task| puts activity_task.activity_type.name activity_task.complete! :result => name puts("waiting for an activity") end

编辑

AWS 论坛上的另一位用户评论道:

我认为原因在于 SWF 没有立即识别长轮询连接关闭。当你杀死一个工人时,它的连接一段时间可以被服务认为是打开的。所以它仍然可以向它分派任务。对你来说,新工人似乎永远不会得到它。验证它的方法是检查工作流程历史记录。您将看到活动任务启动事件,其中包含已死工作人员的主机和 pid 的识别字段。最终,此类任务将超时,并且可以由决策者重试。

请注意,这种情况在频繁终止连接的单元测试中很常见,对于任何生产应用程序来说都不是问题。常见的解决方法是为每个单元测试使用不同的任务列表。

这似乎是一个相当合理的解释。我将尝试确认这一点。

【问题讨论】:

【参考方案1】:

您提出了两个问题:一个是关于在没有活动决策者的情况下开始执行的问题,另一个是关于演员在任务中间崩溃的问题。让我按顺序说。

我根据您的观察进行了一项实验,实际上,当新的工作流执行开始并且没有决策者轮询 SWF 时,仍然认为新的决策任务开始了。以下是我来自 AWS 控制台的事件日志。注意会发生什么:

Fri Feb 22 22:15:38 GMT+000 2013 1 WorkflowExecutionStarted
Fri Feb 22 22:15:38 GMT+000 2013 2 DecisionTaskScheduled
Fri Feb 22 22:15:38 GMT+000 2013 3 DecisionTaskStarted
Fri Feb 22 22:20:39 GMT+000 2013 4 DecisionTaskTimedOut
Fri Feb 22 22:20:39 GMT+000 2013 5 DecisionTaskScheduled
Fri Feb 22 22:22:26 GMT+000 2013 6 DecisionTaskStarted
Fri Feb 22 22:22:27 GMT+000 2013 7 DecisionTaskCompleted
Fri Feb 22 22:22:27 GMT+000 2013 8 ActivityTaskScheduled
Fri Feb 22 22:22:29 GMT+000 2013 9 ActivityTaskStarted
Fri Feb 22 22:22:30 GMT+000 2013 10 ActivityTaskCompleted
...

第一个决策任务被立即安排(这是意料之中的)并立即开始(即据称已分派给决策者,即使没有决策者在运行)。与此同时,我启动了一个决策程序,但工作流直到原始决策任务超时,5 分钟后才移动。我想不出这将是所需行为的场景。对此有两种可能的防御措施:在开始新的执行之前运行决策程序,或者在决策任务上设置可接受的低超时(这些任务无论如何都应该立即执行)。

演员(决策者或工人)崩溃的问题是我熟悉的问题。先做一个简短的背景说明:

服务分三个阶段记录活动和决策任务:

预定 = 准备好被演员接走。 已开始 = 已被演员选中。 Completed/Failed 或 Timed out = 参与者在截止日期内失败或未完成任务。

一旦actor拿起一个任务并崩溃,它显然不会向服务报告任何内容(除非它能够恢复并且仍然记得任务令牌 已调度的任务 - 但大多数崩溃的演员不会那么聪明)。下一次调度决策任务时,将在最近调度的任务超时,这就是为什么所有参与者似乎在任务超时期间被阻塞的原因。这实际上是期望的行为:只要工作人员仍在其期限内工作,服务就无法知道任务是否正在处理。有一个简单的方法可以解决这个问题:为你的actors 设置一个try-catch 块,并在发生意外崩溃时使任务失败。我不鼓励对每个集成测试使用单独的任务列表。相反,我建议让teardown() 块中的任务失败。 SWF 允许为失败的任务指定 reason,这是记录失败并稍后通过 AWS 控制台查看它们的一种方式。

【讨论】:

感谢您的详尽解释。我认为我一直在做错事,但看起来一切都或多或少按预期工作。我自己还没有编写测试。 快乐是我的,我玩得很开心,最后学到了一些东西。

以上是关于Amazon SWF:至少必须有一名工作人员在运行,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Amazon SWF 在服务器之间进行通信

如何在内部使用 Amazon SWF?

Amazon AWS 简单工作流服务 SWF PHP 示例

在 Amazon SWF 中,我可以滥用决策任务来实际执行工作吗

如何使用 Amazon SWF [关闭]

基于 SQS 消息触发 SWF 工作流