亚马逊SWF:至少有一名工人必须在运营,为什么?

时间:2013-02-20 18:07:59

标签: amazon-web-services amazon-swf

我刚开始使用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 个答案:

答案 0 :(得分: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分钟后原始决策任务超时才移动。我想不出这可能是期望的行为。两种可能的防御措施:让决策者在开始新的执行之前运行,或者在决策任务上设置一个可接受的低超时(这些任务应该是立即的)。

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

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

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

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