2011-01-18 22 views
24

He intentado usar Python + boto + multiprocesamiento, S3cmd y J3tset, pero tengo problemas con todos ellos.La forma más rápida de descargar 3 millones de objetos de un cubo S3

¿Alguna sugerencia, tal vez una secuencia de comandos ya hecha que ha estado usando o de otra manera que yo no sepa?

EDIT:

eventlet + boto es una solución que vale la pena como se menciona a continuación. Encontré un buen artículo de referencia de evento aquí http://web.archive.org/web/20110520140439/http://teddziuba.com/2010/02/eventlet-asynchronous-io-for-g.html

He agregado la secuencia de comandos python que estoy usando en este momento a continuación.

+0

Amazon Importar/Exportar http://aws.amazon.com/importexport/ :) –

+0

¿De qué tamaño son los objetos individuales? – Amber

+0

@ J.16.SDiZ No puedo esperar tanto :( –

Respuesta

29

Bien, descubrí una solución basada en la pista de @Matt Billenstien. Utiliza la biblioteca de eventos. El primer paso es más importante aquí (parche mono de bibliotecas IO estándar).

Ejecute este script en segundo plano con nohup y ya está todo listo.

from eventlet import * 
patcher.monkey_patch(all=True) 

import os, sys, time 
from boto.s3.connection import S3Connection 
from boto.s3.bucket import Bucket 

import logging 

logging.basicConfig(filename="s3_download.log", level=logging.INFO) 


def download_file(key_name): 
    # Its imp to download the key from a new connection 
    conn = S3Connection("KEY", "SECRET") 
    bucket = Bucket(connection=conn, name="BUCKET") 
    key = bucket.get_key(key_name) 

    try: 
     res = key.get_contents_to_filename(key.name) 
    except: 
     logging.info(key.name+":"+"FAILED") 

if __name__ == "__main__": 
    conn = S3Connection("KEY", "SECRET") 
    bucket = Bucket(connection=conn, name="BUCKET") 

    logging.info("Fetching bucket list") 
    bucket_list = bucket.list(prefix="PREFIX") 

    logging.info("Creating a pool") 
    pool = GreenPool(size=20) 

    logging.info("Saving files in bucket...") 
    for key in bucket.list(): 
     pool.spawn_n(download_file, key.key) 
    pool.waitall() 
+2

Tenga en cuenta que he tenido problemas si no creo una conexión en cada greenlet. ¿Estabas en la mesa para descargar todos tus objetos usando esto? –

+2

No. Yo también tenía problemas. Dejó de funcionar después de descargar 4000 objetos. No tuve tiempo para depurarlo, así que terminé usando * s3cmd get * de un script de shell para cada archivo. Dividí la lista de nombres de archivo en S3 en varios conjuntos y ejecuté el script en 7-8 conjuntos a la vez (así que tenía 7-8 * s3cmd get * solicitudes en cualquier momento). Use el método boto's * bucket.list() * para obtener una lista de archivos y luego use el comando * split * shell para crear conjuntos de igual tamaño. Esto podría consumir más CPU que el enfoque eventlet pero es simple y hace el trabajo. –

+0

He editado el código para crear una nueva conexión para cada descarga de archivos (esto funciona bien con hilos verdes). –

4

Use eventlet para darle el paralelismo de E/S, escriba una función simple para descargar un objeto usando urllib, luego use un GreenPile para asignarlo a una lista de urls de entrada, una pila con 50 a 100 verdos. ..

+1

Gracias por la sugerencia. Pero, ¿no es esto algo así como usar multiprocesamiento.Pool? –

Cuestiones relacionadas