Introdução às funções serverless em Kotlin e AWS Lambda
A arquitetura Serverless tornou-se padrão para criar aplicações escaláveis e econômicas. AWS Lambda é um dos serviços mais populares para executar código sem gerenciar servidores. No entanto, a maioria dos exemplos e documentações é voltada para Java ou Python. Kotlin, sendo uma linguagem moderna para JVM, oferece sintaxe concisa e total compatibilidade com o ecossistema Java, tornando-se uma excelente escolha para funções Lambda.
Neste artigo, abordaremos o ciclo completo: desde a configuração do projeto até o deploy e monitoramento. Você aprenderá a escrever funções serverless eficientes em Kotlin, processar eventos do API Gateway, S3 e DynamoDB, além de otimizar o cold start.
1. Configuração do projeto e dependências
Para começar, criaremos um projeto Gradle com suporte a Kotlin. A dependência principal é com.amazonaws:aws-lambda-java-core, que fornece interfaces para handlers.
Passo 1.1: Estrutura do build.gradle.kts
plugins { kotlin("jvm") version "1.9.22" id("io.github.microutils:kotlin-logging") version "3.0.5"}
dependencies { implementation("com.amazonaws:aws-lambda-java-core:1.2.2") implementation("com.amazonaws:aws-lambda-java-events:3.11.3") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.3") implementation("org.slf4j:slf4j-simple:2.0.9")}
tasks.register<Zip>("buildLambda") { from(sourceSets.main.get().output) from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) into("build/libs") archiveFileName.set("lambda.zip")}Observe a tarefa buildLambda — ela cria um "fat JAR" que o AWS Lambda poderá executar. Sem esta etapa, o deploy não funcionará.
Passo 1.2: Função handler básica
Crie o arquivo Handler.kt com uma função simples que recebe Map<String, String> e retorna uma string:
import com.amazonaws.services.lambda.runtime.Contextimport com.amazonaws.services.lambda.runtime.RequestHandler
class HelloHandler : RequestHandler<Map<String, String>, String> { override fun handleRequest(input: Map<String, String>, context: Context): String { val name = input["name"] ?: "World" context.logger.log("Processing request for $name") return "Hello, $name!" }}A interface RequestHandler é parametrizada com dois tipos: o tipo de entrada e o tipo de retorno. Kotlin permite usar Map, String, bem como qualquer data class.
2. Trabalhando com eventos AWS (API Gateway, S3, DynamoDB)
Funções serverless raramente funcionam isoladamente. Na maioria das vezes, elas reagem a eventos de outros serviços AWS. Vamos considerar três cenários populares.
2.1 Processamento de requisições HTTP via API Gateway
Para integração com API Gateway, use a classe APIGatewayProxyRequestEvent do aws-lambda-java-events:
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEventimport com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEventimport com.amazonaws.services.lambda.runtime.Contextimport com.amazonaws.services.lambda.runtime.RequestHandler
class ApiHandler : RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { override fun handleRequest(input: APIGatewayProxyRequestEvent, context: Context): APIGatewayProxyResponseEvent { val body = "Received: ${input.body}" return APIGatewayProxyResponseEvent() .withStatusCode(200) .withBody(body) .withHeaders(mapOf("Content-Type" to "text/plain")) }}Neste exemplo, extraímos o corpo da requisição e retornamos uma resposta HTTP.