6

我刚刚开始使用 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 的识别字段。最终,此类任务将超时,并且可以由决策者重试。

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

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

4

1 回答 1

9

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

我根据您的观察进行了一项实验,实际上,当新的工作流执行开始并且没有决策者轮询 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 分钟后才移动。我想不出这将是所需行为的场景。对此有两种可能的防御措施:在开始新的执行之前让决策者运行,或者在决策任务上设置可接受的低超时(这些任务无论如何都应该立即执行)。

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

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

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

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

于 2013-02-23T00:17:04.830 回答