Как загрузить небольшие файлы в Amazon S3 эффективно в Python
В последнее время мне нужно как можно быстрее реализовать программу для загрузки файлов в Amazon EC2 на S3 в Python. Размер файлов - 30 КБ.
Я пробовал некоторые решения, используя несколько потоков, множественную обработку, совместную работу. Ниже приведен мой результат теста производительности на Amazon EC2.
3600 (количество файлов) * 30K (размер файла) ~~ 105M (Всего) --- >
**5.5s [ 4 process + 100 coroutine ]**
10s [ 200 coroutine ]
14s [ 10 threads ]
Код, показанный ниже
Для многопоточности
def mput(i, client, files):
for f in files:
if hash(f) % NTHREAD == i:
put(client, os.path.join(DATA_DIR, f))
def test_multithreading():
client = connect_to_s3_sevice()
files = os.listdir(DATA_DIR)
ths = [threading.Thread(target=mput, args=(i, client, files)) for i in range(NTHREAD)]
for th in ths:
th.daemon = True
th.start()
for th in ths:
th.join()
Для сопрограммы
client = connect_to_s3_sevice()
pool = eventlet.GreenPool(int(sys.argv[2]))
xput = functools.partial(put, client)
files = os.listdir(DATA_DIR)
for f in files:
pool.spawn_n(xput, os.path.join(DATA_DIR, f))
pool.waitall()
Для многопроцессорной обработки
def pproc(i):
client = connect_to_s3_sevice()
files = os.listdir(DATA_DIR)
pool = eventlet.GreenPool(100)
xput = functools.partial(put, client)
for f in files:
if hash(f) % NPROCESS == i:
pool.spawn_n(xput, os.path.join(DATA_DIR, f))
pool.waitall()
def test_multiproc():
procs = [multiprocessing.Process(target=pproc, args=(i, )) for i in range(NPROCESS)]
for p in procs:
p.daemon = True
p.start()
for p in procs:
p.join()
Конфигурация машины Ubuntu 14.04, 2 процессора (2.50 ГГц), 4G памяти
Самая высокая достигнутая скорость составляет 19 Мбит/с (105/5.5). В целом, это слишком медленно. Любой способ ускорить его? Может ли ускоренный python делать это быстрее?
Ответы
Ответ 1
Пример параллельного времени загрузки для Amazon S3 с помощью Python boto SDK можно найти здесь:
Вместо написания кода вы можете также обратиться к интерфейсу командной строки AWS, который может выполнять закачки в параллельны друг другу. Он также написан на Python и использует boto.
Ответ 2
Мне недавно потребовалось загрузить около 5 ТБ небольших файлов в AWS и без проблем достигнет полной пропускной способности сети ~ 750 Мбит (соединение 1 Гб на сервер), установив более высокое значение "max_concurrent_request" в файле ~/.aws/config.
Я ускорил процесс, запустив несколько заданий загрузки через bash for-loop и отправив эти задания на разные серверы.
Я также попытался использовать python, например. s3-parallel-put, но я думаю, что этот подход быстрее. Конечно, если файлы слишком маленькие, следует учитывать: Сжатие → Загрузка в EBS/S3 и распаковка там
Вот какой код может помочь.
$cat .aws/config
[default]
region = eu-west-1
output = text
s3 =
max_concurrent_requests = 100
Запустите несколько копий копий aws, например.
for folder in `ls`; do aws s3 cp $folder s3://<bucket>/$folder/whatever/; done
Ответ 3
У меня та же проблема, что и у вас. Мое решение было отправить данные в AWS SQS, а затем сохранить их на S3 с помощью AWS Lambda.
Итак, поток данных выглядит:
приложение → SQS → Lambda → S3
Весь процесс асинхронен, но почти в режиме реального времени:)