Criar e implantar uma UDF com o Lambda
Para criar uma UDF personalizada, crie uma nova classe Java ao estender a classe UserDefinedFunctionHandler
. O código-fonte para UserDefinedFunctionHandler.java
As etapas nessa seção demonstram a criação e compilação de um arquivo Jar da UDF usando Apache Maven
Execute as etapas a seguir para criar uma UDF personalizada para o Athena usando o Maven
Clonar o SDK e preparar o ambiente de desenvolvimento
Antes de começar, certifique-se de que o git esteja instalado no sistema usando sudo
yum install git -y
.
Como instalar o Query Federation SDK da AWS
-
Digite o seguinte na linha de comando para clonar o repositório do SDK. Este repositório inclui o SDK, exemplos e um conjunto de conectores de fonte de dados. Para obter mais informações sobre conectores de fonte de dados, consulte Usar a consulta federada do Amazon Athena.
git clone https://github.com/awslabs/aws-athena-query-federation.git
Como instalar pré-requisitos para este procedimento
Se você trabalha em uma máquina de desenvolvimento que já tem o Apache Maven, a AWS CLI e a ferramenta de compilação do AWS Serverless Application Model instalados, pode ignorar esta etapa.
-
Na raiz do diretório
aws-athena-query-federation
criado ao executar a clonagem, execute o script prepare_dev_env.shque prepara o ambiente de desenvolvimento. -
Atualize o shell para fornecer novas variáveis criadas pelo processo de instalação ou reinicie a sessão do terminal.
source ~/.profile
Importante
Se você ignorar essa etapa, receberá erros posteriormente sobre a AWS CLI ou a ferramenta de compilação do AWS SAM não conseguir publicar a função do Lambda.
Criar um projeto Maven
Execute o seguinte comando para criar o projeto Maven. Substitua groupId
pelo ID exclusivo da organização e substitua my-athena-udf
pelo nome do aplicativo. Para obter mais informações, consulte Como criar meu primeiro projeto Maven?
mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DgroupId=
groupId
\ -DartifactId=my-athena-udfs
Adicionar dependências e plugins ao projeto Maven
Adicione as configurações a seguir ao arquivo pom.xml
do projeto Maven. Para ver um exemplo, consulte o arquivo pom.xml
<properties> <aws-athena-federation-sdk.version>2022.47.1</aws-athena-federation-sdk.version> </properties> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-athena-federation-sdk</artifactId> <version>${aws-athena-federation-sdk.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.1</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Escrever código Java para UDFs
Crie uma nova classe ao estender UserDefinedFunctionHandler.java
No exemplo a seguir, dois métodos Java para UDFs, compress()
e decompress()
, são criados dentro da classe MyUserDefinedFunctions
.
*package *com.mycompany.athena.udfs; public class MyUserDefinedFunctions extends UserDefinedFunctionHandler { private static final String SOURCE_TYPE = "MyCompany"; public MyUserDefinedFunctions() { super(SOURCE_TYPE); } /** * Compresses a valid UTF-8 String using the zlib compression library. * Encodes bytes with Base64 encoding scheme. * * @param input the String to be compressed * @return the compressed String */ public String compress(String input) { byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8); // create compressor Deflater compressor = new Deflater(); compressor.setInput(inputBytes); compressor.finish(); // compress bytes to output stream byte[] buffer = new byte[4096]; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length); while (!compressor.finished()) { int bytes = compressor.deflate(buffer); byteArrayOutputStream.write(buffer, 0, bytes); } try { byteArrayOutputStream.close(); } catch (IOException e) { throw new RuntimeException("Failed to close ByteArrayOutputStream", e); } // return encoded string byte[] compressedBytes = byteArrayOutputStream.toByteArray(); return Base64.getEncoder().encodeToString(compressedBytes); } /** * Decompresses a valid String that has been compressed using the zlib compression library. * Decodes bytes with Base64 decoding scheme. * * @param input the String to be decompressed * @return the decompressed String */ public String decompress(String input) { byte[] inputBytes = Base64.getDecoder().decode((input)); // create decompressor Inflater decompressor = new Inflater(); decompressor.setInput(inputBytes, 0, inputBytes.length); // decompress bytes to output stream byte[] buffer = new byte[4096]; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length); try { while (!decompressor.finished()) { int bytes = decompressor.inflate(buffer); if (bytes == 0 && decompressor.needsInput()) { throw new DataFormatException("Input is truncated"); } byteArrayOutputStream.write(buffer, 0, bytes); } } catch (DataFormatException e) { throw new RuntimeException("Failed to decompress string", e); } try { byteArrayOutputStream.close(); } catch (IOException e) { throw new RuntimeException("Failed to close ByteArrayOutputStream", e); } // return decoded string byte[] decompressedBytes = byteArrayOutputStream.toByteArray(); return new String(decompressedBytes, StandardCharsets.UTF_8); } }
Compilar o arquivo JAR
Execute mvn clean install
para compilar o projeto. Após a compilação com êxito, um arquivo JAR é criado na pasta target
do projeto nomeado como
, no qual artifactId
-version
.jarartifactId
é o nome fornecido por você no projeto Maven, por exemplo, my-athena-udfs
.
Implantar o JAR no AWS Lambda
Você tem duas opções para implantar o código no Lambda:
-
Implantar usando AWS Serverless Application Repository (recomendado)
-
Criar uma função do Lambda do arquivo JAR
Opção 1: implantar no AWS Serverless Application Repository
Ao implantar o arquivo JAR no AWS Serverless Application Repository, você cria um arquivo YAML de modelo do AWS SAM que representa a arquitetura do aplicativo. Em seguida, você especifica esse arquivo YAML e um bucket do Amazon S3 no qual os artefatos da aplicação são carregados e disponibilizados para o AWS Serverless Application Repository. O procedimento abaixo usa o script publish.shathena-query-federation/tools
do Athena Query Federation SDK clonado anteriormente.
Para obter mais informações e conhecer os requisitos, consulte Publicar aplicações no Guia do desenvolvedor do AWS Serverless Application Repository, Conceitos de modelo do AWS SAM no Guia do desenvolvedor do AWS Serverless Application Model e Publicar aplicações com tecnologia sem servidor usando a CLI do AWS SAM.
O exemplo a seguir demonstra parâmetros em um arquivo YAML. Adicione parâmetros similares ao arquivo YAML e salve-o no diretório de projetos. Consulte athena-udf.yaml
Transform: 'AWS::Serverless-2016-10-31' Metadata: 'AWS::ServerlessRepo::Application': Name:
MyApplicationName
Description: 'The description I write for my application
' Author: 'Author Name
' Labels: - athena-federation SemanticVersion: 1.0.0 Parameters: LambdaFunctionName: Description: 'The name of the Lambda function that will contain your UDFs.
' Type: String LambdaTimeout: Description: 'Maximum Lambda invocation runtime in seconds. (min 1 - 900 max)' Default: 900 Type: Number LambdaMemory: Description: 'Lambda memory in MB (min 128 - 3008 max).' Default: 3008 Type: Number Resources: ConnectorConfig: Type: 'AWS::Serverless::Function' Properties: FunctionName: !Ref LambdaFunctionName Handler: "full.path.to.your.handler. For example, com.amazonaws.athena.connectors.udfs.MyUDFHandler
" CodeUri: "Relative path to your JAR file. For example, ./target/athena-udfs-1.0.jar
" Description: "My description of the UDFs that this Lambda function enables.
" Runtime: java8 Timeout: !Ref LambdaTimeout MemorySize: !Ref LambdaMemory
Copie o script publish.sh
para o diretório de projetos no qual você salvou o arquivo YAML e execute o comando:
./publish.sh
MyS3Location
MyYamlFile
Por exemplo, se o local do bucket for s3://amzn-s3-demo-bucket/mysarapps/athenaudf
e o arquivo YAML for salvo como my-athena-udfs.yaml
:
./publish.sh amzn-s3-demo-bucket/mysarapps/athenaudf my-athena-udfs
Criar uma função do Lambda
-
Abra o console do Lambda em https://console.aws.amazon.com/lambda/
, escolha Create function (Criar função) e selecione Browse serverless app repository (Procurar repositório de aplicações sem servidor) -
Selecione Private applications (Aplicativos privados), localize o aplicativo na lista ou procure usando palavras-chave e selecione-o.
-
Verifique, forneça detalhes do aplicativo e selecione Deploy (Implantar).
Agora você pode usar os nomes dos métodos definidos no arquivo JAR da função do Lambda como UDFs no Athena.
Opção 2: criar uma função do Lambda diretamente
Você também pode criar uma função do Lambda diretamente usando o console ou a AWS CLI. O exemplo a seguir demonstra o uso do comando da CLI create-function
do Lambda.
aws lambda create-function \ --function-name
MyLambdaFunctionName
\ --runtime java8 \ --role arn:aws:iam::1234567890123:role/my_lambda_role
\ --handlercom.mycompany.athena.udfs.MyUserDefinedFunctions
\ --timeout 900 \ --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar