2013-07-04 4 views
1

Je suis en cours d'exécution dans l'erreur suivante lors de l'exécution d'une exportation au travail CSV sur AppEngine en utilisant la nouvelle bibliothèque Google Cloud Storage (AppEngine-GCS-client). J'ai environ ~ 30mb de données que j'ai besoin d'exporter tous les soirs. De temps en temps, je devrai reconstruire toute la table. Aujourd'hui, j'ai dû tout reconstruire (~ 800mb au total) et je n'ai fait que pousser environ 300mb. J'ai vérifié les journaux et a trouvé cette exception:Google Cloud Storage (GCS) Erreur 200 sur Chunk non-finale

/tâche/BigQuery/ExportVisitListByDayTask java.lang.RuntimeException: code de réponse inattendue 200 sur morceau non-finale: Demande: PUT https://storage.googleapis.com/moose-sku-data/visit_day_1372392000000_1372898225040.csv?upload_id=AEnB2UrQ1cw0-Jbt7Kr-S4FD2fA3LkpYoUWrD3ZBkKdTjMq3ICGP4ajvDlo9V-PaKmdTym-zOKVrtVVTrFWp9np4Z7jrFbM-gQ x-goog-api version : 2 content-Range: octets 4718592-4980735/*

262144 octets de contenu

Réponse: 200 avec 0 octets de contenu ETag: "f87dbbaf3f7ac56c8b96088e4c1747f6" x-goog génération: 1372898591905000 x-goog-metageneration: 1 x -goog-hachage: CRC32C = 72jksw == x-goog-hachage: md5 = + H27rz96xWyLlgiOTBdH9g == Vary: Origine Date: Thu, 4 juillet 2013 00:43:17 GMT serveur: HTTP Télécharger serveur Construit sur 28 juin 2013 13:27:54 (1372451274) Content-Length: 0 Content-type: text/html; charset = UTF-8 X-Google-Cache-Control: distance-fetch 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) 

La tâche est assez simple, mais je me demande s'il y a quelque chose de mal avec la façon dont j'utilise waitForOutstandingWrites() ou la façon dont je suis en train de sérialiser mon outputChannel pour l'exécution de la tâche suivante. Une chose à noter, c'est que chaque tâche est divisée en groupes quotidiens, chacun émettant son propre fichier individuel. Les tâches de jour doivent être exécutées en même temps à 10 minutes l'une de l'autre afin d'éviter les 60 jours.

Dans la tâche, je crée un PrintWriter comme suit: OutputStream outputStream = Channels.newOutputStream (outputChannel); PrintWriter printWriter = nouveau PrintWriter (outputStream);

et écrire des données sur lui 50 lignes à la fois et appeler la fonction waitForOutstandingWrites() pour pousser tout vers GCS. Quand je viens à la limite fichier ouvert (~ 22 secondes) Je mets le outputChannel dans Memcache puis replanifier la tâche avec le curseur de données iterator.

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

Cela semble fonctionner la plupart du temps, mais j'obtenir ces erreurs ce qui crée ~ corrompus et les fichiers incomplets sur le GCS. Y at-il quelque chose d'évident que je fais mal dans ces appels? Puis-je avoir un seul canal ouvert à GCS à la fois par application? Y a-t-il un autre problème?

Appréciez des conseils que vous pourriez prêter!

Merci!

Evan

Répondre

1

Une réponse 200 indique que le fichier a été finalisé. Si cela se produit sur une API autre que close, la bibliothèque renvoie une erreur, car cela n'est pas attendu.

Cela est probablement fait pour se produisent la façon dont vous replanifiez la tâche.Il se peut que lorsque vous reprogrammez la tâche, la file d'attente de tâches duplique la livraison de la tâche pour une raison quelconque. (Cela peut arriver) et s'il n'y a pas de vérification pour empêcher cela, il pourrait y avoir deux instances essayant d'écrire dans le même fichier en même temps. Quand on ferme le fichier, l'autre voit une erreur. Le résultat net est un fichier corrompu.

La solution simple est de ne pas reprogrammer la tâche. Il n'y a pas de limite de temps sur la durée d'ouverture d'un fichier avec le client GCS. (Contrairement à l'API Fichiers obsolète.)

+0

Ah ça va super bien. Je suis heureux d'entendre parler de la levée de la limite de temps; Cependant, il peut y avoir des tâches d'exportation qui s'exécutent par rapport à la limite de demande de 10 minutes. Comment devrais-je les planifier? Quel serait le chèque? –

+0

Vous pouvez sérialiser l'enregistreur à l'aide de la sérialisation Java et l'écrire dans Datastore. Dans la tâche de suivi, vous devez être sûr que c'est le seul qui s'exécute. Une façon de le faire serait de mettre à jour une entrée dans la banque de données qui dit "Ceci est utilisé jusqu'à __ temps". Dans le cas où votre processus échoue pendant l'écriture, il peut réessayer à nouveau après que le temps s'est écoulé. Évidemment, ce schéma nécessite que l'heure sélectionnée soit aussi longue que la fréquence à laquelle vous mettez à jour l'entrée dans le processus d'écriture. – tkaitchuck

+0

Ok merci, fera l'affaire. Ce serait génial si nous pouvions obtenir un .toWebSafeString et un .fromWebSafeString comme nous l'avons pour les curseurs, juste pour simplifier un peu le développement. –

Questions connexes