【问题标题】:Google Cloud Storage (gcs) Error 200 on non-final Chunk非最终块上的 Google Cloud Storage (gcs) 错误 200
【发布时间】:2013-07-01 21:52:24
【问题描述】:

使用新的 Google Cloud Storage 库 (appengine-gcs-client) 在 AppEngine 上运行导出到 CSV 作业时遇到以下错误。我有大约 30mb 的数据需要每晚导出。有时,我需要重建整个表。今天,我不得不重建所有东西(总共约 800mb),而我实际上只推了约 300mb。我检查了日志,发现了这个异常:

/task/bigquery/ExportVisitListByDayTask java.lang.RuntimeException:非最终块上的意外响应代码 200:请求:PUT https://storage.googleapis.com/moose-sku-data/visit_day_1372392000000_1372898225040.csv?upload_id=AEnB2UrQ1cw0-Jbt7Kr-S4FD2fA3LkpYoUWrD3ZBkKdTjMq3ICGP4ajvDlo9V-PaKmdTym-zOKVrtVVTrFWp9np4Z7jrFbM-gQ x-goog-api 版本:2 内容范围:字节 4718592-4980735/*

262144 字节的内容

响应:200,内容为 0 字节 ETag:“f87dbbaf3f7ac56c8b96088e4c1747f6” x-goog-代:1372898591905000 x-goog-metageneration:1 x-goog-hash: crc32c=72jksw== x-goog-hash: md5=+H27rz96xWyLlgiOTBdH9g== 变化:起源 日期:2013 年 7 月 4 日星期四 00:43:17 GMT 服务器:HTTP 上传服务器建于 2013 年 6 月 28 日 13:27:54 (1372451274) 内容长度:0 内容类型:文本/html;字符集=UTF-8 X-Google-Cache-Control:远程获取 通过:HTTP/1.1 GWA

at com.google.appengine.tools.cloudstorage.oauth.OauthRawGcsService.put(OauthRawGcsService.java:254)
at com.google.appengine.tools.cloudstorage.oauth.OauthRawGcsService.continueObjectCreation(OauthRawGcsService.java:206)
at com.google.appengine.tools.cloudstorage.GcsOutputChannelImpl$2.run(GcsOutputChannelImpl.java:147)
at com.google.appengine.tools.cloudstorage.GcsOutputChannelImpl$2.run(GcsOutputChannelImpl.java:144)
at com.google.appengine.tools.cloudstorage.RetryHelper.doRetry(RetryHelper.java:78)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:123)
at com.google.appengine.tools.cloudstorage.GcsOutputChannelImpl.writeOut(GcsOutputChannelImpl.java:144)
at com.google.appengine.tools.cloudstorage.GcsOutputChannelImpl.waitForOutstandingWrites(GcsOutputChannelImpl.java:186)
at com.moose.task.bigquery.ExportVisitListByDayTask.doPost(ExportVisitListByDayTask.java:196)

任务非常简单,但我想知道我使用 waitForOutstandingWrites() 的方式或我为下一个任务运行序列化 outputChannel 的方式是否有问题。需要注意的一点是,每个任务都分为每日组,每个组都输出自己的个人文件。每日任务计划以 10 分钟的间隔同时运行,以推出所有 60 天。

在任务中,我创建了一个 PrintWriter,如下所示: OutputStream outputStream = Channels.newOutputStream( outputChannel ); PrintWriter printWriter = new PrintWriter( outputStream );

然后一次将数据写入 50 行,并调用 waitForOutstandingWrites() 函数将所有内容推送到 GCS。当我达到打开文件限制(约 22 秒)时,我将 outputChannel 放入 Memcache,然后使用数据迭代器的光标重新安排任务。

 printWriter.print( outputString.toString() );
 printWriter.flush();
 outputChannel.waitForOutstandingWrites();

这似乎大部分时间都在工作,但我收到了这些错误,这些错误正在 GCS 上创建〜损坏和不完整的文件。这些电话中有什么明显的我做错了吗?每个应用程序一次只能向 GCS 开放一个渠道吗?还有其他问题吗?

感谢您提供的任何提示!

谢谢!

埃文

【问题讨论】:

    标签: google-app-engine google-cloud-storage task-queue


    【解决方案1】:

    200 响应表示文件已完成。如果这发生在不是 close 的 API 上,则库会抛出错误,因为这不是预期的。

    这可能与您重新安排任务的方式有关。可能是当您重新安排任务时,任务队列由于某种原因重复了任务的交付。 (这可能发生)如果没有检查来防止这种情况,可能有两个实例试图同时写入同一个文件。当一个人关闭文件时,另一个人会看到错误。最终结果是一个损坏的文件。

    简单的解决方案是不要重新安排任务。文件可以在 GCS 客户端打开多长时间没有时间限制。 (与已弃用的 Files API 不同。)

    【讨论】:

    • 啊,很好。我很高兴听到取消时限的消息;但是,可能存在超出 10 分钟请求限制的导出任务。我应该如何安排这些?支票是什么?
    • 您可以使用 Java 序列化对编写器进行序列化并将其写入 Datastore。在后续任务中,您需要确保它是唯一执行的任务。一种方法是更新数据存储中的一个条目,该条目显示“这是在使用中直到 __ 时间”。如果您的进程在写入时失败,它可以在经过这么长时间后重试。显然这种方案要求选择的时间要长于你在写作过程中更新条目的频率。
    • 好的,谢谢,会的。如果我们能像 Cursors 一样获得 .toWebSafeString 和 .fromWebSafeString ,那就太棒了,只是为了简化开发。
    猜你喜欢
    • 2019-05-17
    • 2020-02-08
    • 2022-01-27
    • 2015-06-29
    • 2017-09-30
    • 1970-01-01
    • 2014-05-30
    • 2017-04-08
    • 2015-07-18
    相关资源
    最近更新 更多