首页 文章

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

提问于
浏览
5

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

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

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

还有一些需要注意的事情:我正在使用单个任务列表来执行按顺序运行的两个单独的活动任务 . 工作者和决策者都在轮询相同的任务列表 .

这是我的 Worker :

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

EDIT

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

我认为原因是SWF没有立即识别长轮询连接关闭 . 当您杀死一名 Worker 时,该服务可以认为其连接有一段时间是打开的 . 所以它仍然可以向它发送任务 . 对你来说,看起来新 Worker 永远不会得到它 . 验证它的方法是检查工作流程历史记录 . 您将看到活动任务已启动事件,其中包含包含死亡 Worker 的主机和pid的标识字段 . 最终这样的任务将超时并且可以由决策者重试 . 请注意,在频繁终止连接的单元测试期间,这种情况很常见,对于任何 生产环境 应用程序来说都不是真正的问题 . 常见的解决方法是为每个单元测试使用不同的任务列表 .

这似乎是一个非常合理的解释 . 我打算试着证实这一点 .

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

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

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

    • 预定=准备好由演员接听 .

    • 已启动=已经被演员拾取 .

    • 已完成/失败或超时=演员要么失败,要么在截止日期前未完成任务 .

    一旦演员拾起任务并崩溃,显然不会向服务报告任何内容( unless 它能够恢复并仍然记得调度任务的任务标记 - 但是大多数崩溃的演员都不会知道任务是否完成只要工作人员仍然在其截止日期之前工作,工作是否正在进行 . 有一种简单的方法可以解决这个问题:使用try-catch块使你的演员适应并在意外崩溃发生时使任务失败 . 我会劝阻为每个集成测试使用单独的任务列表 . 相反,我建议在 teardown() 块中失败任务.SWF允许指定 reason 以使任务失败,这是记录失败并稍后通过AWS查看它们的一种方法安慰 .

相关问题