En este artículo les voy a explicar como crear AWS Lambdas usando Quarkus. Pero primeramente debemos saber que AWS Lambda nos permite ejecutar código sin aprovisionar o manejar servidores, es decir es serverless
. Por lo cual nos despreocupamos de todo lo que se necesita para que nuestro código ejecute y escale automáticamente en un entorno de alta disponibilidad.
Además, pagamos solo por el tiempo de computación que se consume, por lo cual es muy deseable que nuestro código sean tan rápido como sea posible, y es ahí donde hace mucho sentido usar Quarkus.
Las funciones en Lambda se pueden escribir en múltiples lenguajes, que a la fecha son:
- .NET Core 3.1/2.1 (C#/PowerShell)
- Go 1.x
- Java 11/8
- Node.js 12x/10x
- Python 3.8/3.6/2.7
- Ruby 2.7
- Un
runtime
personalizado (he visto Perl funcionando así)
Dicho lo anterior, para este ejercicio vamos a usar Quarkus 1.3.1 el cual ya usa por omisión Java 11. Para crear el proyecto ejecutamos lo siguiente desde la terminal empleando el siguiente arquetipo.
Debo aclarar que la extensión de quarkus para Lambda esta en una fase de preview
, pero yo la he usado sin ningún inconveniente en ambientes productivos. Pero si deben tener presente que la especificación puede cambiar entre releases
de Quarkus.
mvn archetype:generate \
-DarchetypeGroupId=io.quarkus \
-DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
-DarchetypeVersion=1.3.1.Final
Por supuesto, también pueden generar lo anterior desde https://code.quarkus.io/ y seleccionar la extensión desde ahí y descargar el proyecto.
Una vez que generamos nuestro proyecto, observaremos que nos crea varias clases con código de ejemplo. Una de ellas se llama TestLambda
. Esta posee el handler
que se requiere para integrarnos al Lambda.
@Named("test")
public class TestLambda
implements RequestHandler<InputObject, OutputObject> {
@Inject
ProcessingService service;
@Override
public OutputObject handleRequest(InputObject input,
Context context) {
return service.process(input)
.setRequestId(context.getAwsRequestId());
}
}
Debemos notar varias cosas aquí:
- La clase esta anotada con @Named y el nombre que indiquemos ahí debemos tenerlo presente para ajustar la propiedad
quarkus.lambda.handler
del archivoapplication.properties
. - Implementa
RequestHandler
e indicamos la clase que representa la entrada/salida y que corresponde a un JSON. - Se puede hacer uso de CDI, como por ejemplo este @Inject de un servicio.
- El método de interés es el
handleRequest
. El cual sobreescribimos con nuestra lógica. Este recibe como segundo parámetro el contexto de ejecución de AWS Lambda.
Ahora generemos el jar de nuevo primer lambda.
mvn clean package
Primero vamos a subir nuestra función por la consola de AWS y damos click en Create function
. Debemos seleccionar el runtime de Java 11 y colocar un nombre adecuado para nuestra función. Es importante seleccionar el permiso adecuado o bien crear un rol básico, esto en la parte de permisos.
El siguiente paso involucra subir nuestro jar, es importante que el handler sea exactamente este: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest
Para probar nuestro código hacemos un test, el cual se hace en la parte superior del menu y debemos digitar lo siguiente:
y cuyo resultado es:
Observen que demoró 1.32 ms, nada mal.
Ahora, vamos a hacer un cambio y es genera una imagen nativa. Lo que debemos hacer es primero compilar nuestro proyecto como un ejecutable nativo. Es importante que tengas instalado GraalVM 19.3.1, docker y los prerequisitos indicados aquí.
mvn clean install -Pnative -Dnative-image.docker-build=true
Dado que esta prueba la hago en MacOS, necesito agregar la propiedad -Dnative-image.docker-build=true
para indicarle a quarkus que use un build
de docker, pues Amazon Lambda requiere de un binario linux.
El resultado es un archivo llamado function.zip
en el directorio target. Este zip lo que tiene es el ejecutable renombrado a bootstrap
; pues es un requerimiento de AWS Lambda.
Debemos actualizar nuestro lambda con este nuevo zip y seleccionar que el runtime
es custom
Luego debemos agregar una variable de ambiente DISABLE_SIGNAL_HANDLERS
y que posea el valor true
. Si no lo hacemos, tendremos un error de ejecución.
Si repetimos nuestra pruebe tendremos un resultado satisfactorio y además, un excelente tiempo de arranque en frío.
Otra manera de crear, actualizar y eliminar nuestra función es usar el comando manage.sh
que nos generó el arquetipo de maven. Les sugiero que lo revisen para que vean como funciona.
Conclusión
Espero que este artículo les impulse a usar Java en funciones Lambda de AWS, es bastante sencillo y tiene excelentes tiempos de ejecución gracias a Quarkus.
Comentarios