我刚刚开始使用 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 的识别字段。最终,此类任务将超时,并且可以由决策者重试。
请注意,这种情况在频繁终止连接的单元测试中很常见,对于任何生产应用程序来说都不是问题。常见的解决方法是为每个单元测试使用不同的任务列表。
这似乎是一个相当合理的解释。我将尝试确认这一点。