2013-07-04 1 views
1

При запуске экспорта в CSV-приложение на AppEngine я использую следующую ошибку при использовании новой библиотеки Google Cloud Storage (appengine-gcs-client). У меня около ~ 30 мб данных, которые нужно экспортировать на ночной основе. Иногда мне нужно будет перестроить всю таблицу. Сегодня мне пришлось перестроить все (~ 800 мб), и я только натолкнулся на это ~ 300 мб. Я проверил журналы и нашел это исключение:Ошибка в облачном хранилище Google (gcs) Ошибка 200 в нерабочее время Chunk

/задача/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 х-GOOG-Апи-версию : 2 Content-Range: байт 4718592-4980735/*

262144 байт содержания

Ответ: 200 с 0 байта содержание ETag: "f87dbbaf3f7ac56c8b96088e4c1747f6" х-GOOG поколения: 1372898591905000 х-GOOG-metageneration: 1 х-GOOG-хэш: crc32c = 72jksw == х-GOOG-хэш: md5 = + H27rz96xWyLlgiOTBdH9g == Варах: Происхождение Дата: Чт, 04 июл 2013 00:43:17 GMT Сервер: HTTP Upload Server Построен 28 июня 2013 13:27:54 (1372451274) Content-Length: 0 Content-Type: text/html; кодировка = UTF-8 X-Google-Cache-Control: дистанционное выборки Via: 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 = новый PrintWriter (outputStream);

, а затем записать данные на него по 50 строк за раз и вызвать функцию waitForOutstandingWrites(), чтобы перетащить все на GCS. Когда я подхожу к пределу открытого файла (~ 22 секунды), я помещаю outputChannel в Memcache, а затем перенаправляю задачу с помощью курсора итератора данных.

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

Это, кажется, работает большую часть времени, но я получаю эти ошибки, которые создают ~ испорченные и неполные файлы на ГКСЕ. Есть ли что-то очевидное, что я ошибаюсь в этих звонках? Могу ли я иметь только один канал, открытый для GCS за время на приложение? Есть ли другая проблема?

Цените любые советы, которые вы могли бы предоставить!

Спасибо!

Evan

ответ

1

А 200 ответ указывает, что файл был завершен. Если это происходит в API, отличном от закрытого, библиотека выдает ошибку, так как этого не ожидается.

Это, вероятно, происходит с тем, как вы перенаправляете задачу.Возможно, при перепланировании задачи очередь задач дублирует задачу доставки по какой-либо причине. (Это может произойти), и если для предотвращения этого не существует проверок, могут быть два экземпляра, пытающихся записать в один и тот же файл одновременно. Когда кто-то закрывает файл, другой видит ошибку. Конечным результатом является поврежденный файл.

Простым решением является не перепланировать задачу. Не существует ограничения по времени на то, как долго файл может быть открыт с клиентом GCS. (В отличие от устаревших файлов API.)

+0

Ах хорошо отлично. Я рад слышать об отмене срока; однако могут быть задачи экспорта, которые работают против 10-минутного лимита запроса. Как я должен их планировать? Что будет проверкой? –

+0

Вы можете сериализовать запись с использованием сериализации Java и записать ее в хранилище данных. В последующей задаче вы должны быть уверены, что это единственный исполняемый файл. Один из способов сделать это - обновить запись в хранилище данных, в котором говорится: «Это используется до __ раза». В случае сбоя процесса при записи, он может повторить попытку после того, как прошло много времени. Очевидно, что для этой схемы требуется, чтобы выбранное время было больше, чем частота, которую вы обновляете в процессе записи. – tkaitchuck

+0

Хорошо, спасибо, сделаю. Было бы замечательно, если бы мы могли получить .toWebSafeString и .fromWebSafeString, как у нас для курсоров, просто для того, чтобы немного упростить разработку. –