1

我已经实现了一个 Google App Engine 应用程序,它将文档上传到 Google Docs 中的特定文件夹。一个月前,在 Google Docs 中查询特定文件夹时,我开始遇到响应时间问题(GdataClient.GetDocList、fetch-url 调用、Gdata 客户端中的截止日期已超过)。这导致很多任务在任务队列中排队。

当我看到这个时,我暂停了一段时间 - 大约 24 小时。当我重新启动队列时,几乎所有的 where 都再次上传了,除了 10 个文件/任务。

当我实现 GetDocList 调用时,我实现了重试/睡眠功能,以避免我在 .GetNextLink().href 循环期间遇到的有时间歇性的“DeadLineExceeded”。我知道这不是一个好的“云”设计。但是我被迫这样做以使其足够稳定以进行生产。对于每次睡眠,我都会延长等待时间,并且只重试 5 次。我最后一次等待大约 25 秒后重试。

我认为队列中的所有任务都重试了很多次(即使我已将任务限制为以串行模式运行,一次一个。最多每分钟 5 次)以至于 App Engine 应用程序被列入黑名单谷歌文档 API。

这会发生吗?

我需要做什么才能再次从同一个 App Engine 实例查询 Google Docs Api?

我是否需要将 App Engine 应用迁移到新的应用 ID?

当我从我的开发环境中尝试这个时,代码可以工作,它会查询文件夹结构并在时间限制内返回结果。

我要查询的文件夹结构相当大,这意味着我需要通过 .GetNextLink().href 获取它们。在我的开发环境中,文件夹结构包含的文件夹要少得多。

无论如何,这在生产 AppEngine 实例中已经运行了大约一年。但在 3 月 4 日至 5 日左右停止工作。

查询的用户帐户当前正在使用可用 205824 MB 的 7000 MB (3%)。

当我使用 dev-env 中的代码但使用完全不同的 Google Apps 域/app-id/google 帐户时,我无法重现该错误。

当我将最大结果更改为 1(而不是 100、50 或 20)时,我会间歇性地成功。但是由于最大结果为 1,我需要查询 1000 次,并且由于我只能连续获得最大 3 次成功,因此在我的指数回退退出之前,我永远不会得到我的整个结果集。结果集(我查询的文件夹包含 300 到 400 个文件夹(其中至少包含 2 - 6 个包含 pdf 文件的子文件夹)

我尝试过使用 max-result 2,然后每次都获取失败。如果我改回 max-result 1 ,那么它会连续进行一两次提取,但这还不够。因为我需要整个文件夹结构才能找到正确的文件夹来存储文件。

我已经从我的本地环境中尝试过这个 - 即从一个完全不同的 IP 地址,它仍然失败。这意味着应用引擎应用不会被阻止访问 google 文档。max-result 从 2 到 1 的变化也证明了这一点。

结论:Google Docs API 的缓慢返回时间一定是由于我正在循环的集合中的大量文件和集合。请记住,此集合包含大约 3500 Mb。这是一个问题吗?

日志:DocListUrl 从 = https://docs.google.com/feeds/default/private/full/folder:XXXXXXX/contents?max-results=1获取条目。

重试 RetryGetDocList,等待 1 秒。
重试 RetryGetDocList,等待 1 秒。
重试 RetryGetDocList,等待 4 秒。
重试 RetryGetDocList,等待 9 秒。
重试 RetryGetDocList,等待 16 秒。
重试 RetryGetDocList,等待 25 秒。


ApplicationError:5
Traceback(最近一次调用最后一次):文件“/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py”,第 703 行,调用中 handler.post(*groups) 文件“/base/data/home/apps/XXXX/prod-43.358023265943651014/DocsHandler.py”,第 418 行,发布成功 = uploader.Upload(blob_reader, fileToUpload.uploadSize, fileToUpload.MainFolder, fileToUpload.ruleTypeReadableId ,fileToUpload.rootFolderId,fileToUpload.salesforceLink,fileToUpload.rootFolder, fileToUpload.type_folder_name, fileToUpload.file_name, currentUser, client, logObj) File "/base/data/home/apps/XXXX/prod-43.358023265943651014/DocsClasses.py ",第 404 行,在上传集合 = GetAllEntries('https://docs.google.com/feeds/default/private/full/%s/contents?max-results=1' % (ruleTypeFolderResourceId), client) File" /base/data/home/apps/XXXX/prod-43.358023265943651014/DocsClasses.py”,第 351 行,在 GetAllEntries chunk = RetryGetDocList(client.GetDocList , chunk.GetNextLink().href) 文件“/base/data/home/apps/XXX/prod-43.358023265943651014/DocsClasses.py”,第 202 行,RetryGetDocList 返回 functionCall(uri) 文件“/base/data/home/apps/XXX /prod-43.358023265943651014/gdata/docs/client.py”,第 142 行,在 get_doclist auth_token=auth_token,**kwargs) 文件“/base/data/home/apps/XXXX/prod-43.358023265943651014/gdata/client.py” ,第 635 行,在 get_feed **kwargs) 文件“/base/data/home/apps/XXXXX/prod-43.358023265943651014/gdata/client.py”,第 265 行,在请求 uri=uri,auth_token=auth_token,http_request=http_request , **kwargs) 文件“/base/data/home/apps/XXXX/prod-43.358023265943651014/atom/client.py”,第 117 行,在请求中返回 self.http_client.request(http_request) 文件“/base/data/主页/应用程序/XXXXX/prod-43。358023265943651014/atom/http_core.py”,第 420 行,在请求 http_request.headers,http_request._body_parts)文件“/base/data/home/apps/XXXXX/prod-43.358023265943651014/atom/http_core.py”,第 497 行,在_http_request 返回 connection.getresponse() 文件“/base/python_runtime/python_dist/lib/python2.5/httplib.py”,第 206 行,在 getresponse 期限=self.timeout) 文件“/base/python_runtime/python_lib/versions/1 /google/appengine/api/urlfetch.py​​”,第 263 行,在 fetch 中返回 rpc.get_result() 文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py”,第 592 行,在 get_result 中返回 self.__get_result_hook(self)358023265943651014/atom/http_core.py”,第 497 行,在 _http_request 返回 connection.getresponse() 文件中“/base/python_runtime/python_dist/lib/python2.5/httplib.py”,第 206 行,在 getresponse 截止日期=self.timeout ) 文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py​​”,第 263 行,在 fetch 返回 rpc.get_result() 文件“/base/python_runtime/python_lib/versions/1/google /appengine/api/apiproxy_stub_map.py",第 592 行,在 get_result 中返回 self.__get_result_hook(self)358023265943651014/atom/http_core.py”,第 497 行,在 _http_request 返回 connection.getresponse() 文件中“/base/python_runtime/python_dist/lib/python2.5/httplib.py”,第 206 行,在 getresponse 截止日期=self.timeout ) 文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py​​”,第 263 行,在 fetch 返回 rpc.get_result() 文件“/base/python_runtime/python_lib/versions/1/google /appengine/api/apiproxy_stub_map.py",第 592 行,在 get_result 中返回 self.__get_result_hook(self)/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py​​”,第 263 行,在 fetch 返回 rpc.get_result() 文件“/base/python_runtime/python_lib/versions/1/google/appengine/ api/apiproxy_stub_map.py",第 592 行,在 get_result 中返回 self.__get_result_hook(self)/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py​​”,第 263 行,在 fetch 返回 rpc.get_result() 文件“/base/python_runtime/python_lib/versions/1/google/appengine/ api/apiproxy_stub_map.py",第 592 行,在 get_result 中返回 self.__get_result_hook(self)

_get_fetch_result 中的文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py​​”,第 371 行引发 DeadlineExceededError(str(err)) DeadlineExceededError: ApplicationError: 5

问候/詹斯

4

1 回答 1

2

有时,来自 Google Documents List API 的响应会超过 App Engine HTTP 请求的截止日期。这可能是在 API 中返回的非常大的文档语料库的情况。

要解决此问题,请将max-results参数设置为小于1000.

此外,使用指数退避重试请求。

要解决上传失败的问题,请使用 App Engine 中的任务队列来完成上传,以及使用 API恢复上传。

您可以请求 App Engine 团队将您的应用程序的 HTTP 超时大小增加到允许此请求成功的大量秒数。但是,很少有团队在没有强烈需求的情况下批准这样的请求。

于 2012-04-05T16:02:57.887 回答