未记录的托管 VM 任务队列 RPCFailedError
Undocumented Managed VM task queue RPCFailedError
我正在 运行 遇到一个非常特殊且未记录的问题,该问题与 GAE 管理的 VM 和任务队列有关。我知道托管 VM 服务处于测试阶段,所以这个问题可能不会永远相关,但现在肯定让我很头疼。
该问题的主要症状是,在某些(我不完全了解)情况下,我看到以下 error/traceback:
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
方法,但似乎一旦出现错误,我就无法从内部添加任何其他任务相同的处理程序(即我无法启动 "continue from where you left off" 任务,我只需要让它失败并自行重启)
所以,我的问题是,到底是什么导致了这个错误?我怎样才能避免或解决这个问题以便正确处理它?
这是一个正在处理的已知问题。实际上有两个问题 - RPC 失败本身和 SDK 缺乏对 RPCFailedError 异常的处理。
有一些 public 问题的讨论 here。
如果您使用的是 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 启动期间获得 运行..
我正在 运行 遇到一个非常特殊且未记录的问题,该问题与 GAE 管理的 VM 和任务队列有关。我知道托管 VM 服务处于测试阶段,所以这个问题可能不会永远相关,但现在肯定让我很头疼。
该问题的主要症状是,在某些(我不完全了解)情况下,我看到以下 error/traceback:
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
方法,但似乎一旦出现错误,我就无法从内部添加任何其他任务相同的处理程序(即我无法启动 "continue from where you left off" 任务,我只需要让它失败并自行重启)
所以,我的问题是,到底是什么导致了这个错误?我怎样才能避免或解决这个问题以便正确处理它?
这是一个正在处理的已知问题。实际上有两个问题 - RPC 失败本身和 SDK 缺乏对 RPCFailedError 异常的处理。
有一些 public 问题的讨论 here。
如果您使用的是 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 启动期间获得 运行..