AWS Lambda (Python) не может распаковать и сохранить файлы в S3 - PullRequest
0 голосов
/ 11 мая 2018

Проект в настоящее время поддерживает корзину S3, которая содержит большой zip-файл размером 1,5 ГБ, содержащий файлы .xpt и .sas7dbat.Размер распакованного файла - 20 ГБ.

Попытка разархивировать файл и передать ту же структуру папок на S3

Следующий код работает для небольших ZIP-файлов, но не работает для больших Zip-файлов (1,5 ГБ):

for obj in bucket.objects.all():
    #file_name = os.path.abspath(obj.key) # get full path of files
    key = urlparse(obj.key.encode('utf8'))
    obj = client.get_object(Bucket='my-zip-bucket', Key=obj.key)

    with io.BytesIO(obj["Body"].read()) as tf:
        # rewind the file
        tf.seek(0)

        with zipfile.ZipFile(tf, mode='r') as zipf:
            for file in zipf.infolist():
                fileName = file.filename
                putFile = client.put_object(Bucket='my-un-zip-bucket-', Key=fileName, Body=zipf.read(file))
                putObjects.append(putFile)

Ошибка: Размер памяти: 3008 МБ Макс. Используемая память: 3008 МБ

Я хотел бы проверить:

  1. AWS-Lambda не подходит для больших файлов?
  2. Стоит ли использовать другие библиотеки / подходы вместо чтения всего в памяти

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Существует безсерверное решение с использованием AWS Glue! (я чуть не умер, когда понял это)

Это решение состоит из двух частей:

  1. Лямбда-функция, которая запускается S3 при загрузке ZIP-файла и создает GlueJobRun - передавая ключ объекта S3 в качестве аргумента Glue.
  2. Задание Glue, которое распаковывает файлы (в памяти!)и загружает обратно на S3.

См. Мой код ниже, который распаковывает ZIP-файл и помещает содержимое обратно в ту же корзину (настраивается).

Пожалуйста, подтвердите, если это полезно:)

Лямбда-скрипт (python3), который вызывает задание по склеиванию под названием YourGlueJob

import boto3
import urllib.parse

glue = boto3.client('glue')

def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    print(key)    
try:
    newJobRun = glue.start_job_run(
        JobName = 'YourGlueJob',
        Arguments = {
            '--bucket':bucket,
            '--key':key,
        }
        )
    print("Successfully created unzip job")    
    return key  
except Exception as e:
    print(e)
    print('Error starting unzip job for' + key)
    raise e         

Скрипт задания по склеиванию AWS дляраспакуйте файлы

import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME','bucket','key'],)

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

import boto3
import zipfile
import io
from contextlib import closing

s3 = boto3.client('s3')
s3r = boto3.resource('s3')

bucket = args["bucket"]
key = args["key"]

obj = s3r.Object(
    bucket_name=bucket,
    key=key
)

buffer = io.BytesIO(obj.get()["Body"].read())
z = zipfile.ZipFile(buffer)
list = z.namelist()
for filerr in list:
    print(filerr)
    y=z.open(filerr)
    arcname = key + filerr
    x = io.BytesIO(y.read())
    s3.upload_fileobj(x, bucket, arcname)
    y.close()
print(list)


job.commit()
0 голосов
/ 11 мая 2018

Как описано в этой Ссылке на AWS Lambda Limits :

Но существуют ограничения, которые AWS Lambda накладывает, например, на размер вашего пакета развертывания или объем памяти, которую ваша функция Lambda выделяет на вызов.

Здесь возникает проблема, связанная с тем, что «объем лямбда-функции памяти выделяется на один вызов». К сожалению, лямбда не подходит для этого случая. Вы должны пойти с подходом EC2.

Когда ваши общие требования к памяти высоки, я не считаю Lambda отличным решением. Я не о том, как работают указанные типы файлов, но в общем случае для чтения / обработки больших файлов используется фрагментарный подход, чтобы избежать больших требований к памяти. Работает ли фрагментарный подход или нет, зависит от ваших бизнес-требований.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...