Aplicação Serverless desenvolvida em PHP usando AWS Lambda

Se você não está familiarizado com o conceito, recomendo a leitura do artigo “Serverless: uma introdução“, que introduz os pilares dessa forma de utilizar a computação em nuvem.

Bref

O Bref é uma ferramenta PHP que permite publicarmos nossas funções no AWS Lambda.

O foco estará na parte prática, no desenvolvimento do exemplo, sem entrar nos pormenores sobre como é feito para funcionar o PHP lá na nuvem. Mas, em resumo, usa-se AWS Lambda Layers, uma nova API da AWS que permite que qualquer linguagem seja executada nesse serviço. Também usa o AWS SAM, um framework para gerenciamento, teste e publicação de lambdas. Um pouco mais sobre como essa integração funciona para fazer rodar o PHP pode ser visto nesse artigo: AWS Lambda Custom Runtime for PHP: A Practical Example. Basicamente o Bref faz o deploy de uma função que intermedia a execução da nossa aplicação através de um layer (runtime).

Daqui pra frente trabalharemos com:

  • Terminal;
  • PHP (é necessário que você tenha conhecimento ao menos intermediário em PHP e que também tenha o Composer instalado na sua máquina);
  • AWS (é necessário ter uma conta na AWS para a publicação da aplicação, pois o Framework só funciona com AWS Lambda nesse primeiro momento);

Se você ainda não tem uma conta na AWS, você pode criar uma clicando aqui e utilizá-la por 1 ano de forma gratuita (mas com limites) a maioria dos serviços. No caso do AWS Lambda, a conta gratuita permite que façamos 1 milhão de solicitações por mês sem pagar nada por isso (pelo período de 1 ano).

Criando um usuário na AWS

Se você já criou a sua conta na AWS, agora é a hora de termos uma chave de acesso, chave esta que será usada pelo SAM.

Vamos criar um usuário, pro nosso exemplo didático, chamado serverless-admin. Você deve usar o serviço IAM para criar esse usuário:

https://console.aws.amazon.com/iam/home?region=sa-east-1#/users

Em “Access type” escolha a opção “Programmatic access“:

Na próxima tela, vou dar permissão de administrador para esse usuário. Veja bem, essa chave de acesso estará disponível apenas no meu ambiente. Na vida real, usuários devem ter permissões bem mais “magras”, com apenas o que for suficiente para que desempenhem suas funções.

Basta avançar e depois concluir a criação do usuário:

Guarde a Access key ID e a Secret access key, pois as salveremos em breve no nosso ambiente através de variáveis de ambiente ou usando a AWS-CLI.

Preparando o ambiente com AWS-CLI e AWS-SAM

A AWS-CLI é a ferramenta de linha de comando da AWS, com ela é possível gerenciar todos os aspectos e serviços disponíveis. Para saber como instalar essa ferramenta é só seguir esse tutorial aqui.

Nota: É preciso ter Python e o gerenciador de dependências PIP instalados: https://pip.readthedocs.io/en/stable/installing/

Ou, se você usa macOS e tem o Homebrew instalado, é só executar:

$ brew install awscli

Uma vez instalada a AWS-CLI, tudo o que precisamos fazer é executar:

$ aws configure

Interativamente a ferramenta pedirá a Access key ID e a Secret access key:

(Quando ele pedir a região padrão, coloque: sa-east-1, que é a região de São Paulo da AWS).

Agora é hora de instalar o AWS SAM. Você pode ver como instalar clicando aqui. Se você usa macOS e tem o Homebrew:

$ brew upgrade
$ brew update
$ brew tap aws/tap
$ brew install aws-sam-cli

Por fim, vale lembrar que também é necessário ter o Composer instalado. O utilizaremos nas etapas seguintes.

Criando a aplicação

Na sua pasta preferida, onde você desenvolve os seus projetos, crie uma nova pasta chamada cep-serverless. Dentro dela, pelo terminal, execute:

$ composer require mnapoli/bref "^0.3.0"

Nota: O foco do artigo está no uso da versão 0.3 do Bref, futuras versões podem ter quebras de compatibilidade, mas certamente trarão melhorias e novidades.

Instalará o Bref como dependência do projeto. Em seguida, rode o comando que inicializará o template padrão do Bref na pasta que acabamos de criar:

$ vendor/bin/bref init

A ferramenta perguntará que tipo de aplicação estamos desenvolvendo. Vamos escolher a opção 1:

 What kind of lambda do you want to create? (you will be able to add more functions later by editing `template.yaml`) [PHP function]:
  [0] PHP function
  [1] HTTP application
  [2] Console application

Nota: Não deixe de ver, depois, a opção “PHP Function” descrita na documentação: https://bref.sh/docs/runtimes/function.html

Se tudo der certo, o resultado será:

[OK] Project initialized and ready to test or deploy.

Na raiz do projeto, abra o arquivo template.yaml. Nele temos diversas configurações que o Bref utiliza para o deploy do projeto.

Em layers temos:

arn:aws:lambda:us-east-1:209497400698:layer:php-73-fpm:1

Como o AWS Lambda não tem suporte nativo ao PHP, o Bref usa a API AWS Lambda Layers para executar o código numa compilação do PHP (mantida pelo próprio Bref), como pode ser visto na seção Runtimes da documentação.

Vamos alterar essa linha, para informarmos a versão que está na região da São Paulo da AWS: https://runtimes.bref.sh/?region=sa-east-1

Portanto, altere a linha acima no template.yamlpara:

arn:aws:lambda:sa-east-1:209497400698:layer:php-73-fpm:1

Outra propriedade que podemos alterar desde já é essa:

FunctionName: 'my-function'

Altere para:

FunctionName: 'cep-serverless'

Respondendo à requisições HTTP

Vamos usar o Slim (micro framework PHP) para responder à requisição de uma hipotética consulta de CEP. Na raiz do projeto, execute:

$ composer require slim/slim

Por fim, basta que alteremos o arquivo index.php, ele é o arquivo principal, é o bootstrapper de tudo o que for desenvolvido com o Bref. Como usamos Composer, poderíamos carregar qualquer dependência dentro dele. Poderíamos, inclusive, ter uma estrutura padrão MVC de uma aplicação configurada.

No nosso caso, faremos algo bem simples. Portanto, altere o index.php para:

<?php

declare(strict_types=1);

use Slim\Http\Response;
use Psr\Http\Message\ServerRequestInterface;

require __DIR__.'/vendor/autoload.php';

$slim = new Slim\App;

$slim->get('/cep/{cep}', function (ServerRequestInterface $request, Response $response) {
    return $response->withJson([
        'rua' => 'Rua do Cruzeiro',
        'bairro' => 'Cruzeiro',
        'cidade' => 'Belo Horizonte',
        'uf' => 'MG',
    ]);
});

$slim->run();

A função principal do nosso projeto é responder a uma requisição HTTP. Vamos sempre retornar a mesma resposta, mas poderíamos ter desenvolvido uma forma de extrair tais dados a partir do site dos Correios, por exemplo.

Testando a aplicação

O AWS SAM permite com que testemos localmente o projeto antes de fazer o deploy. É uma mão na roda! No nosso caso, uma aplicação HTTP, podemos rodar um comando do SAM que inicializa um container Docker que emula o AWS Lambda. É necessário que você tenha o Docker instalado e rodando na sua máquina.

Na raiz do projeto, execute:

$ sam local start-api

Na primeira vez que roda pode demorar um pouquinho, até ele baixar uma imagem do Docker. Quando tudo der certo, ele dará o feedback:

A aplicará ficará disponível no endereço: http://localhost:3000

Deploy no AWS Lambda

O deploy no AWS Lambda se dá em três etapas:

  • 1) A aplicação é enviada para um bucket S3 (serviço de armazenamento da AWS)
  • 2) Gera as configurações do CloudFormation que referencia o código da aplicação que está no bucket do S3;
  • 3) Faz o deploy da stack do CloudFormation;

Portanto, a primeira coisa que precisamos fazer é criar um bucket no S3 usando a AWS CLI:

$ aws s3 mb s3://cep-serverless-app

O Bref recomenda que antes do Deploy geremos uma versão otimizada do autoloader do composer, para que tenhamos uma melhor performance na execução:

$ composer install --optimize-autoloader --no-dev

Agora é hora de upar a nossa aplicação e gerar a configuração do CloudFormation:

$ sam package --output-template-file .stack.yaml --s3-bucket cep-serverless-app

Se tudo der certo, o resultado será algo como:

Uploading to b32c80c8d8f53725b43d2bca181d9286  3432727 / 3432727.0  (100.00%)
Successfully packaged artifacts and wrote output template to file .stack.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /Users/kennedytedesco/Documents/www/cep-serverless/.stack.yaml --stack-name <YOUR STACK NAME>

Por fim, o deploy da aplicação no AWS Lambda pode ser feito executando:

$ sam deploy --template-file .stack.yaml --capabilities CAPABILITY_IAM --stack-name cep-serverless-app

Com sucesso o resultado será:

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - cep-serverless-app

Agora é só acessar a stack da nossa aplicação criada na CloudFormation:

Entre na stack “cep-serverless-app” e clique na guia “Outputs“:

Aí está a URL para a nossa aplicação Serverless:

Não vou compartilhar aqui a URL dessa aplicação pois em breve a removerei da conta.

Vale ressaltar, também, que uma vez que temos que uma Lambda publicada, ela pode ser executada por qualquer linguagem através da SDK da AWS. Por exemplo, em PHP seria algo como:

<?php

$lambda = new \Aws\Lambda\LambdaClient([
    'version' => 'latest',
    'region' => 'sa-east-1',
]);

$result = $lambda->invoke([
    'FunctionName' => 'cep-serverless',
    'InvocationType' => 'RequestResponse',
    'LogType' => 'None',
    'Payload' => json_encode(['cep' => '99999999',]),
]);

$result = json_decode($result->get('Payload')->getContents(), true);

Ah, não menos importante, é interessante informar que é possível rodar até mesmo uma aplicação Laravel ou Symfony, como pode ser visto na documentação do Bref. As possibilidades são muitas.

Considerações finais

Quanto ao estado de Serverless com PHP, há muito o que ser feito. O Bref é ótimo, mas ainda está em suas versões iniciais, certamente muito amadurecerá com o tempo. Espero – e em algum momento isso vai acontecer – que as principais plataformas FaaS passem a suportar PHP de forma nativa, isso simplificará todo o processo acima de uma forma indescritível (sem precisar usar um Layer para intermediar as coisas, por exemplo).

Finalizo recomendando que se você se interessou pelo Bref, fique sempre atento ao Github do projeto e à documentação dele.

Até a próxima!

Deixe seu comentário
Share

Head de desenvolvimento. Vasta experiência em desenvolvimento Web com foco em PHP. Graduado em Sistemas de Informação. Pós-graduando em Arquitetura de Software Distribuído pela PUC Minas. Zend Certified Engineer (ZCE) e Coffee Addicted Person (CAP). @KennedyTedesco

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES