Como trabalhar com camadas para funções do Lambda em Java - AWS Lambda

Como trabalhar com camadas para funções do Lambda em Java

Uma camada do Lambda é um arquivo .zip que contém código ou dados complementares. As camadas geralmente contêm dependências de biblioteca, um runtime personalizado ou arquivos de configuração. A criação de uma camada envolve três etapas gerais:

  1. Empacotar o conteúdo da sua camada. Isso significa criar um arquivo .zip contendo as dependências que você deseja usar em suas funções.

  2. Criar a camada no Lambda.

  3. Adicionar a camada às suas funções.

Este tópico contém etapas e orientações sobre como empacotar e criar adequadamente uma camada do Lambda em Java com dependências externas de bibliotecas.

Pré-requisitos

Para seguir as etapas desta seção, você deve ter o seguinte:

nota

Certifique-se de que a versão Java à qual o Maven se refere seja a mesma versão Java da função que você pretende implantar. Por exemplo, para uma função em Java 21, o comando mvn -v deverá listar a versão 21 do Java na saída:

Apache Maven 3.8.6 ... Java version: 21.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home ...

Neste tópico, mencionamos a aplicação de amostra layer-java no repositório awsdocs no GitHub. Essa aplicação contém scripts que baixam as dependências e geram a camada. A aplicação também contém uma função correspondente que usa dependências da camada. Após criar uma camada, você pode implantar e invocar a função correspondente para verificar se tudo funciona corretamente. Como você usa o runtime do Java 21 para as funções, as camadas também devem ser compatíveis com o Java 21.

A amostra de aplicação layer-java contém um único exemplo em dois subdiretórios. O diretório layer contém um arquivo pom.xml que define as dependências da camada, bem como scripts para gerar a camada. O diretório function contém uma amostra de função para ajudar a testar se a camada funciona. Este tutorial explica como criar e empacotar essa camada.

Compatibilidade da camada em Java com o Amazon Linux

A primeira etapa para criar uma camada é agrupar todo o conteúdo da camada em um arquivo .zip. Devido às funções do Lambda serem executadas no Amazon Linux, seu conteúdo da camada deve ser capaz de compilar e criar em um ambiente Linux.

O código Java foi projetado para ser independente da plataforma, de modo que você possa empacotar suas camadas em sua máquina local mesmo que ela não use um ambiente Linux. Após fazer o upload da camada Java para o Lambda, ela ainda será compatível com o Amazon Linux.

Caminhos de camada para runtimes do Java

Quando você adiciona uma camada a uma função, o Lambda carrega o conteúdo da camada no diretório /opt desse ambiente de execução. Para cada runtime do Lambda, a variável PATH já inclui caminhos de pasta específica no diretório /opt. Para garantir que a variável PATH colete o conteúdo da camada, o arquivo .zip da camada deve ter suas dependências nos seguintes caminhos de pasta:

  • java/lib

Por exemplo, o arquivo .zip de camada resultante que você cria neste tutorial tem a seguinte estrutura de diretórios:

layer_content.zip └ java └ lib └ layer-java-layer-1.0-SNAPSHOT.jar

O arquivo JAR layer-java-layer-1.0-SNAPSHOT.jar (um uber-jar que contém todas as dependências necessárias) está localizado corretamente no diretório java/lib. Isso garante que o Lambda possa localizar a biblioteca durante as invocações da função.

Empacotar o conteúdo de camada

Neste exemplo, você empacota as duas seguintes bibliotecas Java em um único arquivo JAR:

  • aws-lambda-java-core: um conjunto mínimo de definições de interface para trabalhar com Java no AWS Lambda

  • Jackson: um conjunto popular de ferramentas de processamento de dados, especialmente para trabalhar com JSON.

Conclua as etapas a seguir para instalar e empacotar o conteúdo de camada.

Para instalar e empacotar seu conteúdo de camada
  1. Clone o repositório aws-lambda-developer-guide do GitHub, que contém a amostra de código de que você precisa no diretório sample-apps/layer-java.

    git clone https://github.com/awsdocs/aws-lambda-developer-guide.git
  2. Acesse o diretório layer do exemplo de aplicação layer-java. Esse diretório contém os scripts que você usa para criar e empacotar a camada corretamente.

    cd aws-lambda-developer-guide/sample-apps/layer-java/layer
  3. Examine os arquivos pom.xml Na seção <dependencies>, você define as dependências que deseja incluir na camada, ou seja, as bibliotecas aws-lambda-java-core e jackson-databind. Você pode atualizar esse arquivo para incluir quaisquer dependências que quiser incluir em sua própria camada.

    exemplo pom.xml
    <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.0</version> </dependency> </dependencies>
    nota

    A seção <build> desse arquivo pom.xml contém dois plug-ins. O maven-compiler-plugin compila o código-fonte. O maven-shade-plugin empacota seus artefatos em um único uber-jar.

  4. Verifique se você tem permissões para executar os dois scripts.

    chmod 744 1-install.sh && chmod 744 2-package.sh
  5. Execute o script 1-install.sh usando o comando a seguir:

    ./1-install.sh

    Esse script executa mvn clean install no diretório atual. Isso criará o uber-jar com todas as dependências necessárias no diretório target/.

    exemplo 1-install.sh
    mvn clean install
  6. Execute o script 2-package.sh usando o comando a seguir:

    ./2-package.sh

    Esse script cria a estrutura de diretórios java/lib que é necessária para empacotar adequadamente o conteúdo da camada. Em seguida, ele copia o uber-jar do diretório /target para o diretório java/lib recém-criado. Por fim, o script compacta o conteúdo do diretório java em um arquivo chamado layer_content.zip. Esse é o arquivo .zip da sua camada. É possível descompactar o arquivo e verificar se ele contém a estrutura de arquivo correta, conforme apresentado na seção Caminhos de camada para runtimes do Java.

    exemplo 2-package.sh
    mkdir java mkdir java/lib cp -r target/layer-java-layer-1.0-SNAPSHOT.jar java/lib/ zip -r layer_content.zip java

Como criar a camada

Nesta seção, você pega o arquivo layer_content.zip gerado na seção anterior e o carrega como uma camada do Lambda. É possível fazer upload de uma camada usando o AWS Management Console ou a API do Lambda por meio da AWS Command Line Interface (AWS CLI). Ao carregar seu arquivo .zip de camada, no seguinte comando PublishLayerVersion da AWS CLI, especifique java21 como o runtime compatível e arm64 como a arquitetura compatível.

aws lambda publish-layer-version --layer-name java-jackson-layer \ --zip-file fileb://layer_content.zip \ --compatible-runtimes java21 \ --compatible-architectures "arm64"

Na resposta, anote o LayerVersionArn, que será algo como arn:aws:lambda:us-east-1:123456789012:layer:java-jackson-layer:1. Você precisará desse nome do recurso da Amazon (ARN) na próxima etapa deste tutorial, ao adicionar a camada à função.

Como adicionar a camada à sua função

Nesta seção, você implanta uma amostra de função do Lambda que usa a biblioteca Jackson em seu código de função e, em seguida, você anexa a camada. Para implantar a função, você precisará de um Definir permissões de uma função do Lambda com um perfil de execução. Se ainda não tiver um perfil de execução, siga as etapas na seção recolhível. Caso contrário, pule para a próxima seção para implantar a função.

Para criar uma função de execução
  1. Abra a página Roles (Funções) no console do IAM.

  2. Selecione Create role (Criar função).

  3. Crie uma função com as propriedades a seguir.

    • Entidade confiávelLambda.

    • Permissions (Permissões): AWSLambdaBasicExecutionRole.

    • Role name (Nome da função): lambda-role.

    A política AWSLambdaBasicExecutionRole tem as permissões necessárias para a função gravar logs no CloudWatch Logs.

Para implantar a função do Lambda
  1. Navegue até o diretório function/. Se você estiver no diretório layer/, execute o seguinte comando:

    cd ../function
  2. Revise o código de função. A função recebe um Map<String, String> como entrada e usa a biblioteca Jackson para gravar a entrada como uma string JSON antes de convertê-la em um objeto Java F1Car predefinido. Por fim, a função usa campos do objeto F1Car para estruturar uma string que a função retorna.

    package example; import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.Map; public class Handler { public String handleRequest(Map<String, String> input, Context context) throws IOException { // Parse the input JSON ObjectMapper objectMapper = new ObjectMapper(); F1Car f1Car = objectMapper.readValue(objectMapper.writeValueAsString(input), F1Car.class); StringBuilder finalString = new StringBuilder(); finalString.append(f1Car.getDriver()); finalString.append(" is a driver for team "); finalString.append(f1Car.getTeam()); return finalString.toString(); } }
  3. Compile o projeto usando o seguinte comando do Maven:

    mvn package

    Esse comando produzirá um arquivo JAR chamado layer-java-function-1.0-SNAPSHOT.jar no diretório target/.

  4. Implantar a função. No seguinte comando da AWS CLI, substitua o parâmetro --role pelo ARN do seu perfil de execução:

    aws lambda create-function --function-name java_function_with_layer \ --runtime java21 \ --architectures "arm64" \ --handler example.Handler::handleRequest \ --timeout 30 \ --role arn:aws:iam::123456789012:role/lambda-role \ --zip-file fileb://target/layer-java-function-1.0-SNAPSHOT.jar

Nessa fase, é possível, opcionalmente, tentar invocar sua função antes de anexar a camada. Se tentar fazer isso, você deverá receber um ClassNotFoundException porque sua função não pode fazer referência ao pacote requests. Para invocar sua função, use o seguinte comando da AWS CLI:

aws lambda invoke --function-name java_function_with_layer \ --cli-binary-format raw-in-base64-out \ --payload '{ "driver": "Max Verstappen", "team": "Red Bull" }' response.json

Você deve ver uma saída semelhante a:

{ "StatusCode": 200, "FunctionError": "Unhandled", "ExecutedVersion": "$LATEST" }

Para ver o erro específico, abra o arquivo response.json de saída. Você deverá ver um ClassNotFoundException com a seguinte mensagem de erro:

"errorMessage":"com.fasterxml.jackson.databind.ObjectMapper","errorType":"java.lang.ClassNotFoundException"

Em seguida, anexe a camada à sua função. No seguinte comando da AWS CLI, substitua o parâmetro --layers pelo ARN da versão de camada que você anotou anteriormente:

aws lambda update-function-configuration --function-name java_function_with_layer \ --cli-binary-format raw-in-base64-out \ --layers "arn:aws:lambda:us-east-1:123456789012:layer:java-jackson-layer:1"

Por fim, tente invocar sua função usando o seguinte comando da AWS CLI:

aws lambda invoke --function-name java_function_with_layer \ --cli-binary-format raw-in-base64-out \ --payload '{ "driver": "Max Verstappen", "team": "Red Bull" }' response.json

Você deve ver uma saída semelhante a:

{ "StatusCode": 200, "ExecutedVersion": "$LATEST" }

Isso indica que a função conseguiu usar a dependência da biblioteca Jackson para executar adequadamente a função. Você pode verificar se o arquivo response.json de saída contém a string retornada correta:

"Max Verstappen is a driver for team Red Bull"

Agora você pode excluir os recursos criados para este tutorial, a menos que queira mantê-los. Excluindo os recursos da AWS que você não está mais usando, você evita cobranças desnecessárias em sua Conta da AWS.

Para excluir a camada do Lambda
  1. Abra a página Camadas do console do Lambda.

  2. Selecione a camada que você criou.

  3. Escolha Excluir, depois escolha Excluir novamente.

Como excluir a função do Lambda
  1. Abra a página Functions (Funções) no console do Lambda.

  2. Selecione a função que você criou.

  3. Escolha Ações, Excluir.

  4. Digite delete no campo de entrada de texto e escolha Delete (Excluir).