Se você tem acompanhado meu conteúdo, deve se lembrar que escrevi um artigo intitulado, Use o AWS Lambda e o API Gateway com Node.js e Couchbase NoSQL. Neste artigo, exploramos o uso dos serviços sem servidor da Amazon para criar funções Lambda que interagem com o Couchbase, nosso banco de dados NoSQL.

No entanto, o Lambda não é a única tecnologia sem servidor, também conhecida como funções como serviço (FaaS), no mercado. Veja Apache OpenWhisk por exemplo. Com o OpenWhisk, você pode criar funções de modo semelhante ao que faria com o Lambda, mas implantá-las em um conjunto mais diversificado de locais, sendo o mais popular o IBM Bluemix.

Veremos como criar funções sem servidor usando o OpenWhisk para se comunicar com nosso Servidor Couchbase banco de dados.

Em seguida, há alguns aspectos a serem observados. Você precisará hospedar o Couchbase Server em algum lugar acessível ao mundo exterior. Isso significa que seu computador local não funcionará. Você precisará do Docker para que possamos compilar nossas dependências para trabalhar com o OpenWhisk. Por fim, você precisará de uma conta Bluemix, pelo menos para este exemplo.

Instalação das ferramentas de CLI do Bluemix para o OpenWhisk

Como mencionei anteriormente, o OpenWhisk é um projeto da Apache Foundation. No entanto, por conveniência, vamos usá-lo no Bluemix da IBM.

Crie uma conta para o Nuvem IBM se você ainda não o fez.

Em vez de usar uma ferramenta de estrutura como o Serverless, usaremos a CLI do Bluemix. Faça o download do CLI do IBM Cloud Functions para podermos interagir com o OpenWhisk na IBM.

Antes de começar a trabalhar com sua conta IBM Cloud, é necessário fazer login por meio da CLI. Na linha de comando, execute o seguinte:

Ao fazer o download da CLI, você receberá o comando exato, mas ele deve ser semelhante ao que apresentei acima.

Agora podemos começar a criar nosso projeto.

Entendendo a estrutura do projeto e o processo de criação de pacotes do OpenWhisk

Se você nunca trabalhou com FaaS antes, as coisas são feitas de forma um pouco diferente da criação de um aplicativo autônomo e dificilmente escalável.

Por exemplo, cada endpoint em nosso projeto FaaS será uma função separada. Combinadas, essas funções criam o que é chamado de pacote. Essas funções são dimensionadas conforme necessário para atender às mudanças na demanda do seu aplicativo.

Dito isso, crie o seguinte:

O projeto deve ter um diretório para cada função que desejamos criar. Cada função terá seu próprio package.json arquivo. Cada package.json pode ser criado executando o seguinte em cada um dos diretórios:

Em cada uma das package.json você também precisará definir qual arquivo é o seu código de função. Por exemplo, abrir create/package.json e adicione ou altere a seguinte linha:

Ao definir o principal estamos informando qual arquivo JavaScript contém nossa função.

Quando começarmos a implementar nossas funções, faremos isso de modo que elas façam parte do mesmo pacote.

Projetando uma função para criar dados

Vamos começar o desenvolvimento com a criação de dados em nosso banco de dados. Navegue até o diretório criar e execute o seguinte comando em sua linha de comando:

O comando acima instalará nossas dependências de funções. Usaremos o SDK do Couchbase para Node.js, a biblioteca UUID para gerar chaves exclusivas e a biblioteca Joi para validar a entrada.

Revisaremos a instalação da dependência, mas, pelo menos, ela nos ajudará por enquanto.

Agora, abra o arquivo criar/criar.js e inclua o seguinte:

O código acima é um pouco exagerado, portanto, precisamos descobrir o que está acontecendo. Vamos começar com a variável que existe fora de nossa função:

Não é a melhor ideia estabelecer uma nova conexão toda vez que a função é chamada. Em vez disso, podemos manter uma instância global do Couchbase Bucket aberto e, enquanto ele existir, usá-lo. Observe que ele nem sempre existirá porque o OpenWhisk destruirá as funções após algum tempo de inatividade.

Dentro de nossa função, verificamos se o Bucket já está aberto. Se o Bucket não estiver aberto, estabelecemos uma conexão usando os parâmetros passados para a função. Quando chegar a hora, definiremos parâmetros padrão que contêm essas informações de conexão.

Como estamos criando dados, precisamos validar se a entrada está correta.

Estamos esperando um primeiro nome e sobrenome esteja presente. Também estamos esperando um tipo não esteja presente. Podemos validar isso com o seguinte:

O stripUnknown removerá os dados não definidos no esquema. Precisamos remover os dados porque nossas informações de entrada e conexão existirão na mesma carga útil. Não queremos que as informações de conexão sejam salvas em nossos documentos. Se houver um erro de validação, ele será retornado. Se não houver erro de validação, podemos prosseguir com a inserção dos dados.

Podemos gerar uma nova chave exclusiva e salvar os dados validados como um documento. Os dados em si serão retornados como uma resposta.

As outras funções seguirão essa mesma estratégia, mais ou menos.

Projetando uma função para recuperar dados com N1QL

Agora que temos dados, vamos tentar recuperá-los do banco de dados com uma invocação de função. Navegue até seu recuperar e execute o seguinte na linha de comando:

Como não criaremos dados, não precisamos gerar valores exclusivos nem validar nenhum dado do usuário. Por esse motivo, precisamos apenas do SDK do Couchbase para essa função.

Abra o arquivo recuperar/retrieve.js e inclua o seguinte:

Vamos pular o que já vimos na função anterior e pular para o que há de novo. Quando estivermos conectados a um Bucket aberto, poderemos criar uma consulta N1QL.

Essa consulta N1QL é do tipo SQL e nos permitirá recuperar todos os documentos que correspondem a determinados critérios. Se houver algum erro, retorne-o como resposta; caso contrário, retorne o conjunto de resultados.

Como não estamos validando nada, essa função de recuperação de dados foi muito mais simples.

Projetando uma função para atualizar dados com mutações de subdocumentos

Agora, digamos que queiramos atualizar documentos no banco de dados. Em vez de recuperar documentos, fazer alterações e salvá-las, enviaremos as alterações diretamente ao banco de dados e deixaremos que ele resolva o problema.

Navegue até a seção atualização e execute o seguinte na linha de comando:

Como estamos aceitando dados de usuários, queremos validar esses dados. Como não estamos criando dados, não precisamos gerar nenhuma chave exclusiva.

Abra o arquivo update/update.js e inclua o seguinte:

O código acima lhe parece familiar? Deveria, porque estamos seguindo a mesma estratégia.

Nossa lógica de validação é ligeiramente diferente neste exemplo:

Queremos editar um documento específico, portanto, uma chave é necessária. Como não sabemos o que o usuário deseja atualizar, definimos as propriedades como opcionais.

Para fazer atualizações, faremos operações de subdocumento em nossos documentos. Para fazer isso, podemos usar um construtor de mutação.

Fornecemos um documento para alterar e quaisquer caminhos nos quais as propriedades existam. Os caminhos podem ser muito mais complexos do que os exemplos usados aqui.

Com o conjunto de mutações definido, podemos executá-las no banco de dados.

Dependendo do resultado, uma resposta será retornada da invocação da função.

Projetando uma função para remoção de dados

Estamos em nossa função final em um pacote de operações CRUD. Chegou a hora de excluir dados do banco de dados.

Navegue até a seção excluir e execute o seguinte comando:

Aceitaremos a exclusão de chaves de documentos, portanto, precisaremos validar a entrada. Da mesma forma, também precisamos do Couchbase SDK para trabalhar com o banco de dados.

Abra o arquivo delete/delete.js e inclua o seguinte código JavaScript:

Você provavelmente está vendo o panorama geral agora em relação à criação de funções com o OpenWhisk e o Couchbase, portanto, não vamos analisar a função acima para excluir documentos.

Empacotamento e implementação das funções no OpenWhisk com o Docker

Temos um conjunto de funções prontas para uso, mas não podemos simplesmente empacotá-las e implantá-las no Bluemix. Se fizéssemos isso, teríamos uma série de erros. O Bluemix usa uma versão especial do Linux com uma determinada arquitetura. Baixei as dependências em meu Mac, que não é compatível.

Lembre-se do artigo que escrevi há algum tempo, intitulado, Implantação de dependências nativas do Node.js no AWS Lambda? Precisamos fazer algo semelhante para o OpenWhisk com o Docker.

Com o Docker instalado e pronto para funcionar, execute o seguinte na CLI:

Os comandos acima farão o download de uma imagem apropriada do OpenWhisk Docker para o Node.js. Em seguida, implantamos um contêiner com essa imagem no modo de terminal interativo. Esse contêiner também terá um volume mapeado. Estou mapeando meu diretório de projeto local para um diretório dentro do contêiner.

Depois que o comando for executado e o contêiner for implantado, você deverá estar no shell dentro do contêiner.

Para cada função, execute o seguinte:

Lembre-se de que instalar as dependências de nosso computador host não é suficiente. Precisamos compilar as dependências para o Bluemix. O Docker compilará essas dependências e, como o diretório está mapeado, podemos usá-las no computador host.

Depois que todos os pacotes de funções forem instalados, podemos agrupá-los e implantá-los.

No computador host, crie um arquivo ZIP de cada uma das funções. O arquivo deve conter os arquivos package.json o arquivo JavaScript e o arquivo módulos_nó diretório.

Se você estiver em um Mac ou computador com uma CLI do ZIP, execute o seguinte:

Quando você tiver um ZIP de cada função, eles poderão ser implantados executando o seguinte:

Introduzi algumas coisas novas no comando acima.

Primeiro, estamos criando um pacote chamado couchbase e, nesse pacote, temos um excluir que é baseada na função delete.zip arquivo. Também estou passando alguns parâmetros padrão. Esses parâmetros serão nossas informações de conexão. Como essas informações são confidenciais, não as estamos passando ao invocar a função, mas sim ao criar a função.

Execute uma variação do comando acima para cada uma de suas funções.

Para executar sua função, tente executar algo como o seguinte:

O comando acima deve passar alguns parâmetros para passar pela validação. A função é chamada de forma bloqueada e, se for bem-sucedida, nossos dados serão salvos no banco de dados e retornados na resposta.

Conclusão

Você acabou de ver como criar um pacote de funções sem servidor para o OpenWhisk que se comunica com o banco de dados NoSQL, Couchbase. O OpenWhisk pode ser usado como uma alternativa ao AWS Lambda, mas os dois certamente não são as únicas opções disponíveis. Independentemente da sua escolha, as funções como serviço (FaaS) são soluções muito escalonáveis para aplicativos de grande porte.

Deseja ver outro exemplo do OpenWhisk? Dê uma olhada em um tutorial que escrevi com o título, Converta uma API RESTful do Node.js em Serverless com o OpenWhisk.

Autor

Postado por Nic Raboy, defensor dos desenvolvedores, Couchbase

Nic Raboy é um defensor das modernas tecnologias de desenvolvimento móvel e da Web. Ele tem experiência em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experiências de desenvolvimento relacionadas a tornar o desenvolvimento móvel e da Web mais fácil de entender.

3 Comentários

  1. Oi 👋 Nick, ótimo post
    Aprendi algo novo hoje sobre o pacote joi 👍🏼

    Algumas dicas
    Você pode tornar suas ações uma ação da Web e ter um URL público ao criar -web true

    Além disso, você pode ignorar o JSON.stringify e definir o corpo como um objeto que será stringify para você.

    Para obter o URL público da ação da Web, você pode executar wsk action get couchbase/delete -url

    Você pode ler mais sobre o uso de ações da Web nos documentos aqui https://console.bluemix.net/docs/openwhisk/openwhisk_webactions.html

Deixar uma resposta