Buenas Practicas creando AWS Lambdas con Java

En esta entrada recopilaré buenas practicas que he aprendido al momento de crear Lambdas en AWS con Java y Maven. Algunas son mis recomendaciones y otras son desde AWS (sobre todo como evitar el cold start). Comenzamos:

  • Todo lo que pueda ser estático tiene que ser estático, de esta manera serán reutilizados en los siguientes request que se realicen en la misma instancia del Lambda.
  • inicializar todo lo que puedan en el handler del lambda en un bloque estático: 
    1. public class LambdaHandler implements RequestStreamHandler {
    2. static {
    3. // acá
    4. }
    5. @Override
    6. public void handleRequest(InputStream is, OutputStream os, Context ctx) throws IOException {
    7. }
    8. }
    Hay que hacer esto porque cuando se instancia la clase hay más poder de computo que el configurado como límite para la lambda, si hay conexiones a DynamoDB hay que instanciar la conexión y hacer una Query (cualquiera) lo importante es que se instancien todas las dependencias. Lo mismo ocurre para conexiones con RDS o cualquier otro recurso.
  • Utilizar CloudFormation o Serverless para automatizar nuestra solución.
  • No ocupar el plugin shade de maven para crear el Jar (no me gusta 😊), prefiero dejar dentro del jar una carpeta lib con todas las librerías la cual quedará disponible cuando se ejecute en el entorno de AWS:
    1. <plugin>
    2. <groupId>org.apache.maven.plugins</groupId>
    3. <artifactId>maven-dependency-plugin</artifactId>
    4. <version>3.1.1</version>
    5. <executions>
    6. <execution>
    7. <id>copy-dependencies</id>
    8. <phase>prepare-package</phase>
    9. <goals>
    10. <goal>copy-dependencies</goal>
    11. </goals>
    12. <configuration>
    13. <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
    14. <overWriteReleases>false</overWriteReleases>
    15. <overWriteSnapshots>false</overWriteSnapshots>
    16. <overWriteIfNewer>true</overWriteIfNewer>
    17. <includeScope>runtime</includeScope>
    18. </configuration>
    19. </execution>
    20. </executions>
    21. </plugin>
  • Utilizar el logger de log4j por su versatilidad:
    1. <dependencies>
    2. <dependency>
    3. <groupId>com.amazonaws</groupId>
    4. <artifactId>aws-lambda-java-log4j2</artifactId>
    5. <version>1.1.0</version>
    6. </dependency>
    7. <dependency>
    8. <groupId>org.apache.logging.log4j</groupId>
    9. <artifactId>log4j-core</artifactId>
    10. <version>2.12.1</version>
    11. </dependency>
    12. <dependency>
    13. <groupId>org.apache.logging.log4j</groupId>
    14. <artifactId>log4j-api</artifactId>
    15. <version>2.12.1</version>
    16. </dependency>
    17. </dependencies>
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <Configuration packages="com.amazonaws.services.lambda.runtime.log4j2">
    3. <Appenders>
    4. <Lambda name="Lambda">
    5. <PatternLayout>
    6. <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1}:%L - %m%n</pattern>
    7. </PatternLayout>
    8. </Lambda>
    9. </Appenders>
    10. <Loggers>
    11. <Root level="info">
    12. <AppenderRef ref="Lambda" />
    13. </Root>
    14. </Loggers>
    15. </Configuration>
    1. private static final Logger LOGGER = LogManager.getLogger(LambdaHandler.class);
  • Usar sam para ejecuciones locales del lambda:
    1. sam local invoke NombreFuncion -t src/main/aws/template.yml
  • Para testing usar testcontainers con localstack, tendremos los servicios de AWS en nuestro ambiente de pruebas (es genial 😍):
    1. <dependency>
    2. <groupId>org.testcontainers</groupId>
    3. <artifactId>testcontainers</artifactId>
    4. <version>${test.containers}</version>
    5. <scope>test</scope>
    6. </dependency>
    7. <dependency>
    8. <groupId>org.testcontainers</groupId>
    9. <artifactId>localstack</artifactId>
    10. <version>${test.containers}</version>
    11. <scope>test</scope>
    12. </dependency>
  • No usar frameworks somo spring, jersey o similares, no es necesario (salvo que quieran utilizar graalvm para compilarlos), las lambdas deberían ser simples (muy personal, nada en contra de los frameworks)
El código de ejemplo está en Github 😇

No hay comentarios.:

Publicar un comentario