2013-07-04 48 views
1

我在使用新的Google雲存儲庫(appengine-gcs-client)在AppEngine上導出到CSV作業時遇到以下錯誤。我每晚需要輸出約30mb的數據。偶爾,我需要重建整個表格。今天,我不得不重建所有東西(總共約800MB),而我實際上只推出了300MB左右。我查了日誌,發現此異常:谷歌雲存儲(gcs)非最終塊上的錯誤200

/任務/ 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哈希:CRC32C = 72jksw == 的x goog哈希:MD5 = + H27rz96xWyLlgiOTBdH9g == 有所不同:原產 日期:星期四,2013年7月4日0點43分17秒GMT 服務器:HTTP上傳服務器建立於2013年6月28日13:27:54(1372451274) 內容長度:0 內容類型:text/html;字符集= UTF-8 X-谷歌-緩存控制:遠程取 途經: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開放嗎?還有其他問題嗎?

欣賞你可以借給你的任何提示!

謝謝!

Evan

回答

1

200響應表示文件已完成。如果在關閉以外的API上發生這種情況,則庫會引發錯誤,因爲這不是預期的。

這很可能發生在您重新計劃任務的方式。這可能是因爲當您重新安排任務時,任務隊列出於某種原因複製了任務的交付。 (這可能發生),如果沒有檢查來防止這種情況發生,則可能有兩個實例試圖同時寫入同一個文件。當一個人關閉文件時,另一個人看到一個錯誤。最終的結果是一個損壞的文件。

簡單的解決方案不是重新計劃任務。使用GCS客戶端可以保持文件的打開時間沒有時間限制。 (與棄用的文件API不同。)

+0

啊好吧好極了。我很高興聽到解除限期的問題;但是,可能會有導出任務在10分鐘的請求限制內運行。我應該如何安排這些?什麼是檢查? –

+0

您可以使用Java序列化對寫入器進行序列化,並將其寫入數據存儲區。在後續任務中,您需要確保它是唯一執行的任務。一種方法是更新數據存儲中的一個條目,說明「這個文件正在使用,直到__時間」。如果寫入過程中出現故障,它可以在經過很長時間後再次重試。很顯然,這種方案要求選擇的時間長於在寫入過程中更新條目的頻率。 – tkaitchuck

+0

好的,謝謝,會做。如果我們可以像使用Cursors一樣獲取.toWebSafeString和.fromWebSafeString,那就太棒了,只是爲了簡化開發。 –

相關問題