Como criar Lambda com Java

Spring Cloud Function x SDK AWS

Image for post
Image for post

Você sabe o que é Lambda? Se você quiser entender um pouco mais sobre esse serviço da AWS e por a mão na massa, esse post é pra você. AWS Lambda é um serviço (serveless) que executa o código de tempos em tempos dado um estímulo/evento de “entrada”. O serviço tem suporte às principais linguagens e plataforma do mercado, tais como: Java, Pyhton, Node.JS, .NET Core, e Go.

Além disso, os serviços Lambda só são cobrados pelo consumo da execução deles, ou seja, você só paga por aquilo que usar. Mas cuidado! Quanto maior o tempo de duração e maior o consumo de memória, maior será o custo, então é necessário fazer um estudo de viabilidade, mesmo que simples.

O que é serveless?

Serverless é um modelo de serviço de nuvem que, com ele, você não precisa se preocupar com a infraestrutura da sua aplicação. O servidor ainda existe, entretanto ele é totalmente gerenciado pelo provedor de nuvem, o que te permite focar somente na lógica do seu negócio. (Treinaweb, 2020).

Empresas que oferencem serviços serveless, tais como Google, Amazon, Azure, IBM, entre outras, oferecem um ambiente em que o cliente se preocupa minimamente com infraestrutura. O máximo que ele vai ter que informar é quantidade de memória que precisa e/ou alguma configuração relativa ao que vai consumir ou que espera que esteja disponível para sua função durante a execução do seu código.

Isso permite que o cliente consiga escalar seu sistema com maior facilidade e ter um serviço com alta disponibilidade e maior segurança, entre outros benefícios.

Mão na massa!

Depois dessa introdução, bora pra prática. Vamos implementar uma função que usa Java e Spring Cloud Function e executá-la no ambiente AWS, comparar o tempo de execução com funções Node.js e Python e, por fim, vamos avaliar os prós e contras de usar o Spring Cloud Function.

Neste exercício, vamos implementar dois Lambdas que buscam informações referentes ao CEP na API ViaCep.

Primeiro vamos criar o projeto, implementar (utilizando Spring Cloud Function) e testar (localmente e no ambiente AWS).

Implementando um AWS Lambda com Java e Spring Cloud Function:

Passo 1:
Gerar o projeto, utilizando o Spring Initializr

Passo 2:
Configurar o projeto

Antes de tudo é necessário termos os adapters Spring Cloud Function Web or Stream em tempo de execução do Lambda. Para isso, precisamos excluí-los antes de criar o JAR. Uma aplicação Lambda também precisa ser sombreada, por isso precisamos fazer essa configuração para que sejam gerados dois arquivos jar: um com terminação “aws” e outro sem. O arquivo com a aws será utilizado para fazer o deploy na AWS e outro para ser executado localmente.

Segue o exemplo:

Passo 3:
Implementar a função:

Vejamos a estrutura do projeto.

Estrutura do projeto
Estrutura do projeto
Estrutura do projeto

Como ficou a classe principal?

O Spring Cloud Function nos oferece um jeito simples de criar nossas funções por meio da annotation @Bean, porém seu desempenho não é dos melhores e, seguindo a recomendação da própria documentação, o jeito mais eficiente é implementando a classe ApplicationContextInitializer e o método initialize. Nesse método, vamos instanciar a nossa classe que vai criar nossa Function.

Nosso model de exemplo:

Precisamos ter o construtor vazio para que, no momento em que nossa função for receber o evento, ele não tenha um comportamento inesperado. Se não tivermos o construtor vazio, ele acaba gerando uma Exception no momento em que a Classe Handler recebe a requisição.

Agora podemos implementar também nossa function. Vejamos:

Aqui nós implementamos a interface Function, na qual precisamos dizer quais são os tipos dos objetos que ela vai receber e devolver (request e response da function). O primeiro tipo de objeto é o que ela recebe, e o segundo é o tipo de objeto que vai devolver, além é claro do método apply que precisamos implementar.

Agora precisamos criar um Handler para que possamos referenciá-lo no momento do deploy.

Apesar de ser uma classe vazia, quando extendemos o SpringBootRequestHandler ele fica responsável e implementa o RequestHandler, além de enviar a solicitação para nossa função. A única razão pela qual precisamos implementá-lo é especificar o tipo de entrada e os parâmetros de saída da função, para que a AWS possa serializá-los ou desserializá-los para nós. Assim nós finalizamos a implementação com Spring Cloud Function.

Implementando um AWS Lambda com Java e SDK AWS.

Para nosso segundo meio de implementar uma função, eu acabei usando um novo projeto com as mesmas configurações, model e classe principal (só retirei o método com o @Bean), e também não precisaremos da classe no package functions, pois tudo vai acontecer dentro do Handler.

Image for post
Image for post
Estrutura do Projeto 2

Vejamos o nosso como ficou a nossa classe:

Agora nós mesmos implementamos o RequestHandler e para isso precisamos implementar o método handlerRequest, que é o responsável por processar o objeto de entrada e enviar o objeto de saída.

Obs.: Os testes locais dessa aplicação só foram possíveis com uso das ferramentas AWS SAM CLI, Plugin AWS Toolkit e Docker. Eu descrevo como testar nesse outro post.

Agora vamos aos testes:
Primeiro vamos testar localmente, começando pela função exposta na classe principal:

Image for post
Image for post

Obs: estou rodando a aplicação pela própria IDE e executando os testes com o Postman.

Teste no console AWS:
Primeiro precisamos buildar o projeto, para gerar o jar que vamos inserir no console da AWS.

Image for post
Image for post

Agora, com o Lambda já criado (aqui nesse tópico não vamos abordar a criação do Lambda do início), podemos subir nosso código e configurá-lo:

Image for post
Image for post

No campo do “Manipulador” devemos colocar o path da nossa classe Handler e o nome dela. No nosso exemplo ficou assim:

com.example.viacep.handler.aws.ViaCepHandler

Clicamos no botão com círculo vermelho e selecionamos o jar com terminação “aws.jar”.

Image for post
Image for post

Agora, precisamos adicionar algumas variáveis de ambiente para o funcinamento da nossa função. Primeiro vamos testar a função ViaCep.

Image for post
Image for post

Obs: a variável MAIN_CLASS só é necessária caso a classe principal não seja encontrada no jar. A documentação não deixou claro o porquê de isso acontecer.

Agora, na parte superior da página, podemos configurar um teste “manual”:

Image for post
Image for post

Basta clicar em “configurar eventos de teste” e vai abrir um modal no qual vamos inserir o JSON com formato do objeto que esperamos receber na função:

Image for post
Image for post

Agora é só criar/salvar e testar.

Image for post
Image for post

Para testarmos o Lambda implementado diretamente no Handler, não precisamos das variavéis de ambiente, basta indicar o path completo do arquivo manipulador (com.function.sample.handler.GetViaCepHandler)

Image for post
Image for post

Impressões:
Resumidamente, é uma ótima ferramenta e possibilidade para implementação. Ajuda bastante em casos mais complexos em que necessitamos criar uma arquitetura para o serviço, além de utilizar uma linguagem já conhecida e um framework de mercado, o que facilita para usuários da linguagem na implementação de testes unitários e, claro, testes locais.

Por outro lado, o desempenho não foi dos melhores. Mas temos que entender o contexto de cada caso e aplicação dessa stack. Se for só um disparo simples, que ocorre várias vezes ao dia, talvez não seja o mais adequado. Mas se for algo que precise de um pouco mais de robustez e que só rode uma vez ao dia ou semana ou mês, pode ser que funcione melhor.

Outro ponto negativo é que há uma grande complexidade na configuração, e talvez pessoas com menos experiência demorem a entender como funciona ou talvez nem entendam. Se o foco for só usar a configuração já fornecida, acredito que não tenha problema, a implementação é relativamente simples e intuitiva, há uma flexibilidade para usar Function, Consumer e Supplier.

Outros lambdas que fazem a mesma coisa tiveram um desempenho melhor, como podemos ver a seguir:

Lambda node.js (javascript)

Image for post
Image for post

Lambda python (3.8)

Image for post
Image for post

Se você quiser mais detalhes, pode dar uma olhada nos repositórios:

Ficou alguma dúvida ou tem algum feedback do que poderia ser melhorado nos projetos? É só deixar um comentário. Quer aprender continuamente em um time que adora compartilhar? Saiba mais aqui e se candidate! Vamos aprender juntos. Até a próxima!

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade…

Diogenes Victor Medeiros Rabelo

Written by

Desenvolvedor web — Cristão — Casado — Aprendendo sempre.

Concrete

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.

Diogenes Victor Medeiros Rabelo

Written by

Desenvolvedor web — Cristão — Casado — Aprendendo sempre.

Concrete

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store