我在Google App Engine(Python)上运行一个实验性应用程序,该应用程序包含一个API和一个执行长期运行任务的Worker。
API是具有云端点的标准模块,而Worker是ManagedVM模块。
用户在数据库上创建一个Task,它将任务作为任务放在pull-queue上。工人通过扩展租约来拉动该任务并无限地执行它。 Worker还将在数据库上设置任务的状态(例如“正在运行”或“错误”)。
目标是永远执行任务,直到用户再次停止它。我通过将状态设置为“stop”并在Worker上调用处理程序来停止任务(workerUrl保存到任务模型)来实现此功能。然后,工作人员将状态设置为“已停止”并删除它租借的任务。
到目前为止,这有一些小问题(例如,将任务放两次)。但我想知道是否有更好的方法来应对这一挑战?基本上问题是如何将远程工作程序执行与数据库模型同步。
此外我确实遇到了问题,如果我停止应用程序,任务应该根据其状态重新放回队列(可以故意停止)。在实时服务器上这不是什么大问题,因为应用程序基本上永远不会停止,但在开发服务器上它是。也许这适合一个cron工作?
更新1:
有关任务的信息实际存储在数据库中。队列上的任务包含数据库中模型的id,请注意图中的状态在api上更新。
Worker(MVM)和API之间的通信是通过Cloud Endpoints实现的,我在Worker端使用python客户端。这非常可靠。
确实,为避免重复任务,我应该使用任务名称。我遇到的唯一问题是你不能重复使用相同的名字很长一段时间,所以我需要找出一些任务名称,可能包括时间戳。
我选择任务队列而不是某种数据库方法的原因是随之而来的故障转移机制。由于我的工人可能会失败,另一名工人将完成任务。此外,它还减少了数据库调用和api调用。
我想我会在自己的模型中重构“任务状态”以获得一种命令模型。这也将作为任务的日志,因此可以看到执行级别上发生的事情。也许这与任务队列一起工作,如果不是,我将看看我是否可以删除队列。
答案 0 :(得分:1)
听起来您只是希望Worker和API前端共享存储,而您的解决方案是将任务队列用作该存储。更好的方法是使用来自Worker的Cloud Datastore的REST API。您仍然可以使用pull队列来启动工作(并避免将同一任务租给多个worker),但随后使用相应的数据存储记录在API前端和Worker之间传递更新。例如,API前端存储"停止"请求,然后工作人员在运行时对此进行轮询。
请注意,App Engine上的API前端可以同时提交到同一事务中的数据存储区和任务队列。这样可以更加健壮地设置共享记录和任务。
至于避免重复任务,请考虑任务名称。您可以为任务指定名称,以防止使用相同名称创建两个任务。
如果他们共享数据存储区,我不确定如何在开发期间最好地设置GAE API前端和托管VM工作人员后端。也许他们都需要使用Datastore REST API和特定于dev的项目,并且API前端需要一个"如果开发服务器使用REST,则使用本机数据存储API"包装。 (如果有更好的方式,我会很高兴知道它。我仍然是托管虚拟机的新手。)对于您的问题,我将添加开发服务器将保留其自己的本地运行之间的模拟数据存储,除非告知不要,这样可以帮助在运行之间保持工作者状态。
我假设您将任务留在任务队列上并无限期延长租约的技术意味着允许新工作人员接收中断的工作,同时仍然避免多个工作人员执行相同的工作。对于无限的任务,您可能还可以基于数据存储区构建类似的机制,并使用保持活动过程根据需要重新启动工作。我很难说这会好得多,但它可能会简化开发环境问题。