Rinha de Serverless: AWS Lambda vs. OCI Functions
Tags: aws, oracle, cloud, serverless
Published: 2021-01-15 15:28:30

Olá, seja bem vindo ao meu primeiro artigo, fique a vontade pra dar o seu feedback =)

Dias atrás fui incumbido de avaliar se era possível migrar o ambiente da AWS para a OCI (Oracle Cloud Infrastructure). Uma das necessidades seria de portar as funções lambda para Oracle Functions, o que me levou a fazer uma das minhas atividades favoritas: Colocar os serviços lado a lado e apontar seus prós e contras, o que eu carinhosamente gosto de resumir como **botar defeito**. Para o texto não ficar mais longo do que já está, coloquei apenas alguns pontos-chave, talvez eu faça uma parte 2.

## Mecanismo de funcionamento
Antes da comparação, é necessário elucidar o funcionamento em cada uma das clouds:

A Oracle faz uso do [Fn Project](fnproject.io) como motor para o seu serviço. Esse é um projeto Open Source que tem como objetivo universalizar o uso de serverless, possibilitando o deploy de funções tanto em cloud quanto on-premise ou até mesmo em sua máquina.

A AWS Lambda utiliza de uma tecnologia proprietária na qual não se tem muita informação de como funciona por baixo dos panos, apesar de sabermos que ela não foge do formato de outras tecnologias nesse meio. Possivelmente escreverei um texto para explicar como o serverless funciona de forma geral.

## Runtimes
Basicamente os runtimes são as linguagens ou frameworks que são suportados pela nuvem. Nesse tópicos podemos dizer que há praticamente um empate, visto que ambos os serviços suportam as linguagens **Python, Ruby, Node.js, Java, Go e C#.** Contudo, a AWS tem uma maior flexibilidade para a criação de contêineres com runtimes personalizados (se você precisa fazer isso pra usar serverless eu aconselho acompanhamento psicológico).

## Teste do Hello World
A primeira impressão é a que fica. Assim como a maioria de vocês, o primeiro teste que eu faço usando uma tecnologia nova é o clássico Hello World. Isso me possibilita saber a complexidade não só do código, mas também para montar um ambiente de desenvolvimento produtivo.

Criei subtópicos abaixo sobre o processo de criação e configuração nos dois ambientes:

### Criação
Criar uma Function é um trabalho que exige paciência, ainda mais se você for utilizar triggers da nuvem para dispará-la. É necessário criar roles e definir várias permissões de forma quase manual para que isso funcione adequadamente, criar VCNs, definir diretivas de rede, etc. A Oracle disponibiliza os passos e os comandos em sua documentação (em inglês), mas mesmo assim é incômodo e abre muito espaço para falhas. Enquanto isso, a AWS abstrai praticamente toda a dificuldade para criação de um Lambda, sendo possível o fazer com alguns cliques, o que me surpreendeu positivamente.

Outro inconveniente da OCI é a necessidade de ter que criar um Docker Registry na nuvem para disponibilizar as imagens das Functions, o que é completamente transparente para o usuário na concorrente. Calma que fica pior.

### Ambiente de desenvolvimento
Aqui é um dos pontos mais negativos para o OCI. Além de ter o OCI-CLI (utilitário de linha de comando da nuvem), é necessário instalar o Fn Project para criação, build e deploy da function, além de precisar do Docker. Você como dev provavelmente já tem o Docker na sua máquina, mas pense numa situação em que você precisa fazer uma atualização emergencial sem ter acesso ao seu ambiente. Até você configurar tudo para fazer o deploy alguém já vai estar com a orelha quente de tanto receber ligações.

Já no lado laranja da força precisamos apenas do utilitário de linha de comando da AWS e o utilitário zip (que já vem em praticamente todas as distros linux - usuários de Arch por favor se retirem do post) para empacotar o código. Na primeira vez em que subi o código eu tive aquele sentimento de "isso aqui tá fácil de mais, tá errado".

> **EDIT**: Você também pode editar o código da sua lambda diretamente no console AWS, o que dispensa a instalação de qualquer coisa na sua máquina. Obrigado Mamutinho por ter me lembrado disso!

### Estrutura do código
Aqui as duas clouds tem pontos a se considerar:
No OCI você está dependente da lib do Fn - o fdk, no qual você vai consumir a classe `Response` para elaborar as repostas das requisições (a galera do SOLID se treme toda). Segue um Hello World fornecido pela [documentação](https://fnproject.io/tutorials/python/intro/):
```python
import io
import json

from fdk import response


def handler(ctx, data: io.BytesIO=None):
    name = "World"
    try:
        body = json.loads(data.getvalue())
        name = body.get("name")
    except (Exception, ValueError) as ex:
        print(str(ex))

    return response.Response(
        ctx, response_data=json.dumps(
            {"message": "Hello {0}".format(name)}),
        headers={"Content-Type": "application/json"}
    )
```
Além disso você terá de ter mais dois arquivos, o `requirements.txt` onde você lista as dependências e o `func.yaml` onde você define os metadados da sua função, como nome, versão, memória RAM, runtime e até outras opções mais avançadas. Segue o exemplo da documentação:
```yaml
schema_version: 20180708
name: pythonfn
version: 0.0.1
runtime: python
entrypoint: /python/bin/fdk /function/func.py handler
memory: 256
```

A AWS mais uma vez deixa as coisas mais simples. Aqui tudo o que você precisa é do código e configurar qual o entrypoint no qual precisa retornar um `dict` com status code, body e headers que desejar definir. Segue exemplo:
```python

def lambda_handler(event, context):
    return {
         "statusCode": 200,
         "body": "Tão fácil que eu escrevi direto no editor do dev.to",
    }

```
Na AWS os metadados da Lambda são gerenciados majoritariamente pela interface ou pelo CLI, e aqui um ponto em que ela peca (ao menos no runtime Python): Você precisa instalar as dependências na mão. Enquanto no OCI você manda o `requirements.txt` e ele se vira, aqui é necessário instalar tudo na pasta do projeto usando o pip, zipar e mandar pra cima (pelo menos alguma coisa eu tinha que achar pra reclamar).

### Build e deploy
Outro ponto pra AWS: Uma das alternativas para deploy é simplesmente zipar o projeto e mandar pra nuvem com o AWS CLI. É tão rápido que dá um vazio de não ter tempo pra pegar o cafézinho enquanto rola o build.

Já no OCI, dependendo da sua internet dá pra tomar um café, comer uma bolachinha e ainda dar uma proseada enquanto o Fn cria a imagem e manda pro Registry na nuvem. Um detalhe que eu reparei é que a OCI tem um certo delay pra de fato usar a nova imagem, então pode ir lá pegar mais um café enquanto você espera.

## Conclusão
Nessa altura do campeonato eu tenho que dizer que meu primeiro contato com serverless foi através da plataforma da Oracle, aprendi e fixei meu conhecimento por ela. 
E também devo dizer que se você é **desenvolvedor** ainda não teve contato com essa tecnologia recomendo extremamente que comece pela a AWS, afinal a dor de cabeça é MUITO menor. A minha opinião franca sobre o Oracle Functions é de que ela é uma grandissíssima **gambiarra.** É anti-produtiva, demanda recursos locais e como eu disse anteriormente, abre muito espaço pra falhas. Apenas recomendaria por conta do custo que é menor e se tem na sua equipe alguém que saiba o que está fazendo. 

# **AWS for the Win.**

That's All Folks, e como meu vô sempre me dizia: *"Para de fazer as coisas na mão e automatiza que tu resolve metade desses problemas ae".*