未记录的托管VM任务队列RPCFailedError

时间:2015-12-04 00:14:25

标签: google-app-engine google-app-engine-python managed-vm

我遇到了GAE托管虚拟机和任务队列的一个非常奇怪且无法记录的问题。据我所知,托管虚拟机服务处于测试阶段,所以这个问题可能永远无法解决,但它确实让我感到很头疼。

问题的主要症状是,在某些情况下(我并不完全知道),我看到以下错误/追溯:

  File "/home/vmagent/my_app/some_file.py", line 265, in some_ndb_tasklet
    res = yield some_task.add_async('some-task-queue-name')
  File "/home/vmagent/python_vm_runtime/google/appengine/ext/ndb/tasklets.py", line 472, in _on_rpc_completion
    result = rpc.get_result()
  File "/home/vmagent/python_vm_runtime/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
    return self.__get_result_hook(self)
  File "/home/vmagent/python_vm_runtime/google/appengine/api/taskqueue/taskqueue.py", line 1948, in ResultHook
    rpc.check_success()
  File "/home/vmagent/python_vm_runtime/google/appengine/api/apiproxy_stub_map.py", line 579, in check_success
    self.__rpc.CheckSuccess()
  File "/home/vmagent/python_vm_runtime/google/appengine/ext/vmruntime/vmstub.py", line 312, in _WaitImpl
    raise self._ErrorException(*_DEFAULT_EXCEPTION)
RPCFailedError: The remote RPC to the application server failed for call taskqueue.BulkAdd().

我已经通过我的本地App Engine SDK来跟踪这一点,我可以到达跟踪的最后一行,但我的机器上根本不存在google/appengine/ext/vmruntime/,所以我有不知道vmstub.py发生了什么。通过查看本地代码,some_task.add_async('the-queue')正在启动RPC并等待它完成,但是这个错误不是taskqueue.py第1949行的except apiproxy_errors.ApplicationError, e:所期望的......

生成错误的代码如下所示:

@ndb.tasklet
def kickoff_tasks(batch_of_payloads):
    for task_payload in batch_of_payloads:
        # task_payload is a dict
        task = taskqueue.Task(
            url='/the/handler/url',
            params=payload)
        res = yield task.add_async('some-valid-task-queue-name')

其他值得注意的事情:

  • 此代码本身在另一个任务启动的任务处理程序中运行。
  • 我在实现这种批处理之前首先看到了这个错误,并认为问题是因为我在任务处理程序中添加了太多任务。
  • 在某些情况下,我可以成功运行批量大小为100,但在其他情况下,它会在100处始终失败(取决于有效负载中的数据),有时在批量大小为50时成功。
  • 任务有效负载本身包括批量项目,并且被调整为足够小以适应任务。 App Engine宣称最大任务大小为100KB,因此我现在将有效负载保持在90,000字节以下。降低尺寸似乎没有任何帮助。
  • 我还尝试实现指数退避,以便在出现此错误时重试kickoff_tasks方法,但似乎一旦出现错误,我就无法在其中添加任何其他任务处理程序(即我不能启动“从你离开的地方继续”任务,我只需让这一个失败并重新启动)

所以,我的问题是,究竟是什么导致了这个错误?我该如何避免它,或者解决这个问题,以便我正确处理它?<​​/ p>

2 个答案:

答案 0 :(得分:2)

这是一个正在处理的已知问题。实际上有两个问题 - RPC失败本身以及SDK缺乏对RPCFailedError异常的处理。

有一些关于该问题的公开讨论here

答案 1 :(得分:0)

如果您正在使用App Engine Flexible和python-compat-multicore图片,则会使用较新版本的请求库弹出与App Engine相关的新错误,从而破坏App Engine Flexible与数据存储区之间的通信。您可以通过在appengine_config.py文件中修补库来修复此错误。

将以下代码添加到appengine_config.py

try:
    import appengine.ext.vmruntime.vmstub as vmstub
except ImportError:
    pass
else:
    if isinstance(vmstub.DEFAULT_TIMEOUT, (int, long)):
        # Newer requests libraries do not accept integers as header values. 
        # Be sure to convert the header value before sending. 
        # See Support Case ID 11235929.
        vmstub.DEFAULT_TIMEOUT = bytes(vmstub.DEFAULT_TIMEOUT)

请注意,如果您没有appengine_config.py文件,则可以在基础项目目录中创建它(无论您将app.yaml文件放在何处)。此文件在App Engine启动期间运行..