我遇到了一个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().
我已经通过我的本地应用程序引擎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,所以我现在将有效载荷控制在90000字节以下。再缩小尺寸似乎也无济于事
- 当出现此错误时,我还尝试实现一个指数后退来重试
kickoff_tasks
方法,但似乎一旦出现错误,我就无法在同一处理程序中添加任何其他任务(即,我无法启动"从停止的地方继续"任务,我只需要让这个任务失败并重新启动它自己)
所以,我的问题是,究竟是什么导致了这个错误?我如何避免它,或者解决它,以便正确处理它?
这是一个正在处理的已知问题。实际上有两个问题-RPC失败本身和SDK没有处理RPCFailedError异常。
这里有一些关于这个问题的公开讨论。
如果您使用的是App Engine Flexible和python-compat-multicore
映像,则会弹出一个与使用较新版本请求库的App Engine相关的新错误,该错误中断了App Engine Flexsible和数据存储之间的通信。您可以通过monkey修补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
文件放在哪里)。此文件在应用程序引擎启动期间运行。。