Invocar função do AWS Lambda - Amazon Simple Storage Service

Invocar função do AWS Lambda

Você pode usar o Operações em Lote do Amazon S3 para executar operações em lote de grande escala em objetos do Amazon S3. A operação do Operações em Lote da função Invocar do AWS Lambda inicia as funções do AWS Lambda para executar ações personalizadas em objetos que estão listados em um manifesto. Esta seção descreve como criar uma função do Lambda para uso com as operações em lote do S3 e como criar um trabalho para chamar a função. O trabalho de Operações em lote do S3 usa a operação LambdaInvoke para executar uma função do Lambda em cada objeto listado em um manifesto.

Você pode trabalhar com o Operações em Lote do S3 usando o console do Amazon S3, a AWS Command Line Interface (AWS CLI), SDKs da AWS ou a API REST do Amazon S3. Para obter mais informações sobre como usar o Lambda, consulte Conceitos básicos do AWS Lambda no Guia do desenvolvedor do AWS Lambda.

As seções a seguir explicam como começar a usar as operações em lote do S3 com o Lambda.

Usar o Lambda com o Operações em Lote

Ao usar o S3 Batch Operations com o AWS Lambda, crie novas funções do Lambda especificamente para uso com o S3 Batch Operations. Não é possível reutilizar funções baseadas em eventos do Amazon S3 existentes com operações em lote do S3. As funções de eventos só podem receber mensagens; elas não retornam mensagens. As funções do Lambda usadas com operações em lote do S3 devem aceitar e retornar mensagens. Para obter mais informações sobre como usar o Lambda com eventos do Amazon S3, consulte Uso do AWS Lambda com o Amazon S3 no Guia do desenvolvedor do AWS Lambda.

Crie um trabalho de operações em lote do S3 que chame a função do Lambda. O trabalho executa a mesma função do Lambda em todos os objetos listados no manifesto. É possível controlar quais versões da função do Lambda usar durante o processamento dos objetos no manifesto. As operações em lote do S3 são compatíveis com nomes de recursos da Amazon (ARNs) não qualificados, aliases e versões específicas. Para obter mais informações, consulte Introdução ao versionamento do AWS Lambda no Guia do desenvolvedor do AWS Lambda.

Se você fornecer ao trabalho de operações em lote do S3 um ARN de função que usa um alias ou o qualificador $LATEST, e atualizar a versão indicada por um deles, as operações em lote do S3 começarão a chamar a nova versão dessa função do Lambda. Isso pode ser útil quando você quer atualizar a funcionalidade durante um trabalho grande. Se você não quer que o Operações em Lote do S3 altere a versão usada, forneça a versão específica no parâmetro FunctionARN ao criar o trabalho.

Usar o Lambda e o Operações em Lote com buckets de diretório

Os buckets de diretório são um tipo de bucket do Amazon S3 projetado para workloads ou aplicações essenciais à performance que requerem latência consistente inferior a dez milissegundos. Para obter mais informações, consulte Directory buckets.

Há requisitos especiais para usar a funcionalidade Operações em Lote para invocar funções do Lambda que atuam em buckets de diretório. Por exemplo, você deve estruturar a solicitação do Lambda usando um esquema JSON atualizado e especificar InvocationSchemaVersion 2.0 (não 1.0) ao criar o trabalho. Esse esquema atualizado permite que você especifique pares opcionais de chave e valor para UserArguments, que você pode usar para modificar determinados parâmetros de funções do Lambda existentes. Consulte mais informações em Automate object processing in Amazon S3 directory buckets with S3 Batch Operations and AWS Lambda no Blog de armazenamento da AWS.

Códigos de resultado e resposta

A funcionalidade Operações em Lote do S3 invoca a função do Lambda com uma ou mais chaves, cada uma com um TaskID associado. A funcionalidade Operações em Lote do S3 espera um código de resultado por chave das funções do Lambda. Todos os IDs de tarefas enviados na solicitação que não forem retornados com um código de resultado por chave receberão o código de resultado do campo treatMissingKeysAs. treatMissingKeysAs é um campo de solicitação opcional e o padrão é TemporaryFailure. A tabela a seguir contém os outros códigos de resultado e valores possíveis para o campo treatMissingKeysAs.

Código de resposta Descrição
Succeeded A tarefa foi concluída normalmente. Se você solicitou um relatório de conclusão do trabalho, a string do resultado da tarefa será incluída no relatório.
TemporaryFailure A tarefa sofreu uma falha temporária e será redirecionada antes da conclusão do trabalho. A string de resultado é ignorada. Se esse for o redirecionamento final, a mensagem de erro será incluída no relatório final.
PermanentFailure A tarefa sofreu uma falha permanente. Se você solicitou um relatório de conclusão do trabalho, a tarefa será marcada como Failed e incluirá a string da mensagem de erro. As strings de resultado de tarefas com falha são ignoradas.

Criar uma função do Lambda para uso com operações em lote do S3

Essa seção fornece um exemplo de permissões do AWS Identity and Access Management (IAM) que devem ser usadas com a função do Lambda. Ela também contém um exemplo de função do Lambda para uso com operações em lote do S3. Se você nunca criou uma função do Lambda antes, consulte Tutorial: Como usar um trigger do Amazon S3 para invocar uma função do AWS Lambda no Guia do desenvolvedor do AWS Lambda.

Crie funções do Lambda especificamente para uso com as operações em lote do S3. Não é possível reutilizar funções do Lambda baseadas em eventos do Amazon S3, pois as funções do Lambda que são usadas para o Operações em Lote do S3 devem aceitar e mostrar campos de dados especiais.

Importante

Funções do AWS Lambda escritas em Java aceitam interfaces de manipulador RequestHandler ou RequestStreamHandler. No entanto, para oferecer suporte ao formato de solicitação e resposta do S3 Batch Operations, o AWS Lambda requer a interface RequestStreamHandler para serialização e desserialização personalizadas de uma solicitação e resposta. Essa interface permite que o Lambda passe um InputStream e um OutputStream para o método Java handleRequest.

Use a interface RequestStreamHandler ao usar funções do Lambda com operações em lote do S3. Se você usar uma interface RequestHandler, o trabalho em lote falhará com “Invalid JSON returned in Lambda payload (JSON inválido retornado no payload do Lambda)” no relatório de conclusão.

Para obter mais informações, consulte Interfaces do manipulador no Guia do usuário do AWS Lambda.

Exemplo de permissões do IAM

Veja a seguir exemplos das permissões do IAM necessárias para usar uma função do Lambda com operações em lote do S3.

exemplo Política de confiança de operações em lote do S3

Veja a seguir um exemplo da política de confiança que pode ser usada para a função do IAM de operações em lote. Essa função do IAM é especificada quando você cria o trabalho e concede às operações em lote permissão para assumir a função do IAM.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "batchoperations.s3.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
exemplo Política do IAM do Lambda

Veja a seguir um exemplo de uma política do IAM que concede permissão às operações em lote do S3 para chamar a função do Lambda e ler o manifesto de entrada.

{ "Version": "2012-10-17", "Statement": [ { "Sid": "BatchOperationsLambdaPolicy", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectVersion", "s3:PutObject", "lambda:InvokeFunction" ], "Resource": "*" } ] }

Exemplo de solicitação e resposta

Esta seção fornece exemplos de solicitação e resposta para a função do Lambda.

exemplo Solicitação

Veja a seguir um exemplo do JSON de uma solicitação para a função do Lambda.

{ "invocationSchemaVersion": "1.0", "invocationId": "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo", "job": { "id": "f3cc4f60-61f6-4a2b-8a21-d07600c373ce" }, "tasks": [ { "taskId": "dGFza2lkZ29lc2hlcmUK", "s3Key": "customerImage1.jpg", "s3VersionId": "1", "s3BucketArn": "arn:aws:s3:us-east-1:0123456788:amzn-s3-demo-bucket1" } ] }
exemplo Resposta

Veja a seguir um exemplo do JSON de uma resposta para a função do Lambda.

{ "invocationSchemaVersion": "1.0", "treatMissingKeysAs" : "PermanentFailure", "invocationId" : "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo", "results": [ { "taskId": "dGFza2lkZ29lc2hlcmUK", "resultCode": "Succeeded", "resultString": "[\"Mary Major", \"John Stiles\"]" } ] }

Exemplo de função do Lambda para operações em lote do S3

O exemplo Lambda em Python a seguir remove um marcador de exclusão de um objeto versionado.

Como mostra o exemplo, as chaves das operações em lote do S3 são codificadas por URL. Para usar o Amazon S3 com outros produtos da AWS, é importante que seu URL decodifique a chave passada pelo S3 Batch Operations.

import logging from urllib import parse import boto3 from botocore.exceptions import ClientError logger = logging.getLogger(__name__) logger.setLevel("INFO") s3 = boto3.client("s3") def lambda_handler(event, context): """ Removes a delete marker from the specified versioned object. :param event: The S3 batch event that contains the ID of the delete marker to remove. :param context: Context about the event. :return: A result structure that Amazon S3 uses to interpret the result of the operation. When the result code is TemporaryFailure, S3 retries the operation. """ # Parse job parameters from Amazon S3 batch operations invocation_id = event["invocationId"] invocation_schema_version = event["invocationSchemaVersion"] results = [] result_code = None result_string = None task = event["tasks"][0] task_id = task["taskId"] try: obj_key = parse.unquote(task["s3Key"], encoding="utf-8") obj_version_id = task["s3VersionId"] bucket_name = task["s3BucketArn"].split(":")[-1] logger.info( "Got task: remove delete marker %s from object %s.", obj_version_id, obj_key ) try: # If this call does not raise an error, the object version is not a delete # marker and should not be deleted. response = s3.head_object( Bucket=bucket_name, Key=obj_key, VersionId=obj_version_id ) result_code = "PermanentFailure" result_string = ( f"Object {obj_key}, ID {obj_version_id} is not " f"a delete marker." ) logger.debug(response) logger.warning(result_string) except ClientError as error: delete_marker = error.response["ResponseMetadata"]["HTTPHeaders"].get( "x-amz-delete-marker", "false" ) if delete_marker == "true": logger.info( "Object %s, version %s is a delete marker.", obj_key, obj_version_id ) try: s3.delete_object( Bucket=bucket_name, Key=obj_key, VersionId=obj_version_id ) result_code = "Succeeded" result_string = ( f"Successfully removed delete marker " f"{obj_version_id} from object {obj_key}." ) logger.info(result_string) except ClientError as error: # Mark request timeout as a temporary failure so it will be retried. if error.response["Error"]["Code"] == "RequestTimeout": result_code = "TemporaryFailure" result_string = ( f"Attempt to remove delete marker from " f"object {obj_key} timed out." ) logger.info(result_string) else: raise else: raise ValueError( f"The x-amz-delete-marker header is either not " f"present or is not 'true'." ) except Exception as error: # Mark all other exceptions as permanent failures. result_code = "PermanentFailure" result_string = str(error) logger.exception(error) finally: results.append( { "taskId": task_id, "resultCode": result_code, "resultString": result_string, } ) return { "invocationSchemaVersion": invocation_schema_version, "treatMissingKeysAs": "PermanentFailure", "invocationId": invocation_id, "results": results, }

Criar um trabalho de operações em lote do S3 que chama uma função do Lambda

Ao criar um trabalho de operações em lote do S3 para chamar uma função do Lambda, forneça o seguinte:

  • O ARN da função do Lambda (que pode incluir o alias da função ou o número de uma versão específica)

  • Uma função do IAM com permissão para invocar a função

  • O parâmetro de ação LambdaInvokeFunction

Para obter mais informações sobre como criar um trabalho de operações em lote do S3, consulte Criar um trabalho de operações em lote do S3 e Operações suportadas pelo S3 Batch Operations.

O exemplo a seguir cria um trabalho do Operações em Lote do S3 que invoca uma função do Lambda usando a AWS CLI. Para usar esse exemplo, substitua os user input placeholders por suas próprias informações.

aws s3control create-job --account-id account-id --operation '{"LambdaInvoke": { "FunctionArn": "arn:aws:lambda:region:account-id:function:LambdaFunctionName" } }' --manifest '{"Spec":{"Format":"S3BatchOperations_CSV_20180820","Fields":["Bucket","Key"]},"Location":{"ObjectArn":"arn:aws:s3:::amzn-s3-demo-manifest-bucket","ETag":"ManifestETag"}}' --report '{"Bucket":"arn:aws:s3:::amzn-s3-demo-bucket","Format":"Report_CSV_20180820","Enabled":true,"Prefix":"ReportPrefix","ReportScope":"AllTasks"}' --priority 2 --role-arn arn:aws:iam::account-id:role/BatchOperationsRole --region region --description "Lambda Function"

Fornecer informações em nível de tarefa em manifestos do Lambda

Ao usar funções do AWS Lambda com o Operações em Lote do S3, talvez você queira que dados adicionais acompanhem cada tarefa em que são operados. Por exemplo, você pode querer fornecer uma chave de objeto de origem e uma nova chave de objeto. A função do Lambda pode copiar a chave de origem em um novo bucket do S3 com um novo nome. Por padrão, o Operações em Lote permite especificar apenas o bucket de destino e uma lista de chaves de origem no manifesto de entrada do trabalho. Os exemplos a seguir descrevem como você pode incluir dados adicionais no manifesto para poder executar funções do Lambda mais complexas.

Para especificar parâmetros por chave no manifesto de operações em lote do S3 para usar no código da função do Lambda, use o seguinte formato JSON codificado por URL. O campo key é passado para a função do Lambda como se fosse uma chave de objeto do Amazon S3. Porém, ele pode ser interpretado pela função do Lambda como contendo outros valores ou várias chaves, conforme mostrado nos exemplos a seguir.

nota

O número máximo de caracteres para o campo key no manifesto é 1.024.

exemplo – Manifesto que substitui as “chaves do Amazon S3” por strings JSON

A versão codificada por URL deve ser fornecida para operações em lote do S3.

amzn-s3-demo-bucket,{"origKey": "object1key", "newKey": "newObject1Key"} amzn-s3-demo-bucket,{"origKey": "object2key", "newKey": "newObject2Key"} amzn-s3-demo-bucket,{"origKey": "object3key", "newKey": "newObject3Key"}
exemplo – Manifesto codificado por URL

Essa versão codificada por URL deve ser fornecida para operações em lote do S3. A versão não codificada em URL não funciona.

amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object1key%22%2C%20%22newKey%22%3A%20%22newObject1Key%22%7D amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object2key%22%2C%20%22newKey%22%3A%20%22newObject2Key%22%7D amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object3key%22%2C%20%22newKey%22%3A%20%22newObject3Key%22%7D
exemplo função do Lambda com formato de manifesto que grava resultados no relatório de trabalho

Esse exemplo de manifesto codificado em URL contém chaves de objeto delimitadas por pipe para que a função do Lambda a seguir analise.

amzn-s3-demo-bucket,object1key%7Clower amzn-s3-demo-bucket,object2key%7Cupper amzn-s3-demo-bucket,object3key%7Creverse amzn-s3-demo-bucket,object4key%7Cdelete

Essa função do Lambda mostra como analisar uma tarefa delimitada por pipe que é codificada no manifesto do Operações em Lote do S3. A tarefa indica qual operação de revisão é aplicada ao objeto especificado.

import logging from urllib import parse import boto3 from botocore.exceptions import ClientError logger = logging.getLogger(__name__) logger.setLevel("INFO") s3 = boto3.resource("s3") def lambda_handler(event, context): """ Applies the specified revision to the specified object. :param event: The Amazon S3 batch event that contains the ID of the object to revise and the revision type to apply. :param context: Context about the event. :return: A result structure that Amazon S3 uses to interpret the result of the operation. """ # Parse job parameters from Amazon S3 batch operations invocation_id = event["invocationId"] invocation_schema_version = event["invocationSchemaVersion"] results = [] result_code = None result_string = None task = event["tasks"][0] task_id = task["taskId"] # The revision type is packed with the object key as a pipe-delimited string. obj_key, revision = parse.unquote(task["s3Key"], encoding="utf-8").split("|") bucket_name = task["s3BucketArn"].split(":")[-1] logger.info("Got task: apply revision %s to %s.", revision, obj_key) try: stanza_obj = s3.Bucket(bucket_name).Object(obj_key) stanza = stanza_obj.get()["Body"].read().decode("utf-8") if revision == "lower": stanza = stanza.lower() elif revision == "upper": stanza = stanza.upper() elif revision == "reverse": stanza = stanza[::-1] elif revision == "delete": pass else: raise TypeError(f"Can't handle revision type '{revision}'.") if revision == "delete": stanza_obj.delete() result_string = f"Deleted stanza {stanza_obj.key}." else: stanza_obj.put(Body=bytes(stanza, "utf-8")) result_string = ( f"Applied revision type '{revision}' to " f"stanza {stanza_obj.key}." ) logger.info(result_string) result_code = "Succeeded" except ClientError as error: if error.response["Error"]["Code"] == "NoSuchKey": result_code = "Succeeded" result_string = ( f"Stanza {obj_key} not found, assuming it was deleted " f"in an earlier revision." ) logger.info(result_string) else: result_code = "PermanentFailure" result_string = ( f"Got exception when applying revision type '{revision}' " f"to {obj_key}: {error}." ) logger.exception(result_string) finally: results.append( { "taskId": task_id, "resultCode": result_code, "resultString": result_string, } ) return { "invocationSchemaVersion": invocation_schema_version, "treatMissingKeysAs": "PermanentFailure", "invocationId": invocation_id, "results": results, }

Tutorial Operações em lote do S3

O tutorial a seguir apresenta procedimentos completos para algumas tarefas do recurso Operações em Lote com o Lambda. Nesse tutorial, você aprenderá a configurar o Operações em Lote para invocar uma função do Lambda para transcodificação em lote de vídeos armazenados em um bucket de origem do S3. A função do Lambda chama o AWS Elemental MediaConvert para transcodificar os vídeos.