由于缺少服务器时钟同步,AppEngine推送队列中的任务执行-ETA

时间:2013-09-05 19:40:36

标签: google-app-engine countdown task-queue clock-synchronization

如果使用AppEngine Push Queues选项添加任务,则

TaskOptions.etaMillis(...)允许安排任务以供将来执行。此方法需要long参数,该参数指定以绝对毫秒执行任务的时间,正如System.currentTimeMillis()返回的那样。

鉴于AppEngine不保证服务器时钟同步,并且时钟可以按照HOURS的顺序关闭! (见"Google I/O 2010 - Data pipelines with Google App Engine" at 0:36:07),这怎么可靠?

让我们考虑以下示例:

  • http请求进入并被路由到时钟恰好提前30分钟的实例
  • 在请求处理期间,我想将一些批处理推迟到后台任务
  • 我希望结果可以在10秒左右向用户报告
  • 因此,我使用System.currentTimeMillis() + 10,000
  • 的ETA安排任务
  • 考虑到30分钟的时钟偏差,这个ETA实际上相当于从现在开始的30分钟和10秒
  • 因此,如果任务现在由不同的实例处理,则可能暂停超过30分钟
  • 毋庸置疑,对于用户来说,似乎我的服务已经死了

在底层API中是否以某种方式阻止了这种情况?如果没有,任务ETA如何有用呢?难道不能将ETA指定为相对时间而不是绝对的时间吗?

真正令人悲伤的部分是,实际上有一个名为TaskOptions.countdownMillis(...)的函数确实需要相对时间,但是看一下 source code that ultimately handles this value,人们看到它只是根据同样高度不可靠的System.currentTimeMillis()转换为绝对时间规范。

更糟糕的是:如果您没有指定ETA或倒计时,此功能仅使用当前系统时间而不是0,因此即使您希望立即执行的任务也可能最终被搁置一小时或更!

这是一个主要的错误还是我错过了什么?

此外,同样适用于Pull Queues中的任务租约,对吧?

1 个答案:

答案 0 :(得分:0)

如果将倒计时设置为10,000 ms,则任务通常会在大约10秒内运行,但有时任务可能会延迟几分钟。它们适用于最终用户不等待的任务。

如果所有处理都由具有完美可用性的单个服务器处理,则相对时间将起作用。相反,我们有许多服务器,每个服务器都具有不完美的可用性,因此我们使用绝对时间添加任务,因为知道时钟偏差通常很小。