Serverless Saga #1: De Servermess para Serverless

Os desafios para usar serverless na criação de aplicações e APIs.

Pedro Correa
Oct 19 · 5 min read

Serverless é a execução de código na nuvem sem precisar de uma máquina virtual. Ele reage a eventos e não é previamente provisionado, aguardando serem chamados. A cobrança também difere pela quantidade de requests feitos.

Este tópico está em alta há muito tempo. Alguns anos atrás, uma arquitetura sem servidores seria considerada loucura, mas cá estamos. Apesar das incríveis vantagens, não observamos uma grande onda de migração ou adoção para essa tecnologia.

Os motivos para a não adoção do serverless vêm desde sua arquitetura bem diferente, inseguranças da tecnologia e o medo do lock-in devido ao alto acoplamento do serverless com suas respectivas nuvens.

Essa série de posts pretende explicar os desafios relacionados à utilização de serverless para criação de aplicações e APIs. Também vamos falar sobre uma possível solução “bala de prata” para migração e construção de forma desacoplada para o modelo serverless.

Primeiro, vamos limitar o escopo do que estamos tentando resolver usando serverless. Essa limitação não indica que o serverless não seja capaz de resolver outros problemas, apenas que precisamos definir o alvo antes de atirar. Dito isso, nosso cenário será o mais usual: uma API servida por HTTP.

Uma das grandes dificuldades de se implementar uma arquitetura serverless é a sua diferença fundamental de operação comparada a um serviço HTTP. No mundo serverless o núcleo que executa o código é conhecido como FaaS (Function as a Service), e as FaaS são executadas a partir de um evento da nuvem utilizada e não por meio de pedidos HTTP como estamos acostumados.

Dentre exemplos de eventos na nuvem, temos:

  • Arquivo criado num Bucket/Blob
  • Alarme lançado pelo CloudWatch
  • Item adicionado a uma fila SQS

Cada evento nada mais é que um amontoado de dados e metadados referentes ao evento ocorrido e, com isso, podemos automatizar processos na nuvem. Por exemplo, um evento de criação de objeto no S3 vem informando o nome do bucket e do objeto criado, e com esses dados conseguimos reagir como quisermos usando alguma linguagem.

Exemplo de um evento da AWS:

{
"Records": [
{
"Sns": {
"Timestamp": "2019-01-02T12:45:07.000Z",
"Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "Hello from SNS!",
...

Esse é o “feijão com arroz” do serverless. Você pode perceber que ele pouco se parece com uma API ou um serviço HTTP qualquer e, para transformar o serverless em uma API ou Aplicação, precisamos de uma camada acima do diagrama anterior.

Como dito anteriormente, as FaaS por si só apenas conseguem reagir a eventos dentro da nuvem e não a eventos externos a ela. Para isso ocorrer, precisamos de algum recurso que receba pedidos externos (como pedidos HTTP) e os transforme em eventos do nuvem vendor para que possam ser processados e, enfim, respondidos.

Bem, o que queremos então é criar uma API com FaaS. Como podemos fazer isso? Fácil, só precisamos de mais alguns blocos:

O AWS APIGateway e o Azure API Manager são os serviços que fazem essa “tradução” nas respectivas nuvens.

Até aí você encontra um monte de tutorial ensinando como fazer. A maioria da literatura sobre o assunto assume que você vai fazer o código para rodar como uma FaaS, ou seja, um código que espera por EVENTOS, e não pedidos HTTP.

Mas e se você já estiver rodando uma API com todo o código pensado em receber HTTP? E se você tem dezenas de Middlewares, centenas de decorators, todos baseados em um framework específico? Santo GIT que nos versiona! E se no futuro você quiser rodar em outra nuvem que tem outra estrutura de dados dos eventos? Ou simplesmente precisa rodar um binário e precise de uma arquitetura com servidores novamente? Como podemos migrar uma aplicação para serverless?

Fácil! Só precisaremos de mais caixas!

Apenas precisamos do inverso que o APIGateway ou APIManager fazem, ou seja: converter EVENTOS em chamadas HTTP e depois o contrário.

Nesse momento imagino o que você está pensando: “meu amigo, que gambiarra”. Mas antes de julgar os autores desse humilde post veja a implementação dessas duas caixinhas azuis na aplicação que migramos na Azure feita em Typescript:

import { Context, HttpRequest } from '@azure/functions';
import _ from 'lodash';
import supertest, { Response } from 'supertest';

export default (app: any) => async (context: Context, req: HttpRequest): Promise<void> => {
const server = supertest(app.callback());
const requestId = req.headers['request-id'];
const apiPath = (new URL(req.url)).pathname;
const methodFunc = _.get(server, `${(req.method || '').toLocaleLowerCase()}`);

// Router
const headers = {
...req.headers,
'request-id': requestId,
'content-length': undefined,
};

// Send Request to KoaJS router
const response:Response = await methodFunc(apiPath).send(req.body).set(headers).query(req.query);

// Build Response
context.res = {
body: response,
status: response.status,
headers: {
...response.header,
'content-length': undefined,
},
};
};

Esse é todo o código que você precisa para migrar uma API Node feita em KoaJS ou Express de serverness para serverless na Azure. Esse código é facilmente adaptado para rodar na AWS e outros frameworks. É claro que existem mais detalhes além dos mencionados, mas o que quero deixar claro é que o código acima funciona.

Dependendo da linguagem, framework e nuvem usadas a implementação pode ser ainda mais fácil! Veja como ficou a nossa implementação para uma aplicação Python/Django na Azure:

import loggingh  import os
import azure.functions as func
from xpto.wsgi import application

def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
return func.WsgiMiddleware(application).handle(req, context)

E é isso! O SDK da Azure já fornece um tradutor de Eventos para WSGI! Só precisamos importar do Django.

Phew, falamos bastante nesse post. Vamos dar um break e na parte 2 da série falamos sobre alguns benchmarks e análise de custo que fizemos para validar essa arquitetura. Se você tem alguma dúvida ou comentário até aqui, utilize os campos abaixo. E se você quer fazer parte de um time que tem automação como princípio, é só dar uma olhada aqui e se candidatar a alguma de nossas vagas. Até a próxima!

Leia mais:

Digital Product Dev

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

Digital Product Dev

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.

Pedro Correa

Written by

Calopsita Cibernética https://www.linkedin.com/in/pedrocorreasilva

Digital Product Dev

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.