JB

Cloud Computing: File Upload with Node.JS, Azure Storage and MongoDB Atlas

javascriptazure storagemongo db atlascloud computingfile uploadnode js
Nov 08, 2020

--- Translation in progress

This week I'm migrating my focus from learning Storage and Database tools, from Microsoft Azure Storage and MongoDB Atlas to Amazon S3 and Amazon DynamoDB, I'm still starting in cloud infrastructure.

Entretanto, desde Outubro eu não satisfeito com a forma que cursos, tutoriais, tópicos e issues abordavam a feature de upload de imagens sendo gravado na Database ou no próprio disco do Server, escolhi buscar uma alternativa que permitisse um iniciante utilizar recursos de computação em nuvem. Abordarei os benefícios ao longo desse texto em que implementarei a feature de upload de arquivos utilizando um Storage da Azure e Database do MongoDB Atlas num projeto de escopo reduto do zero.

cloud-computing.png

Conceitos essenciais

O que é Cloud Computing (Computação em nuvem)?

É uma nomenclatura amplamente utilizada para a disponibilidade/utilização de serviços computacionais por meio da internet baseado em demanda.

Isto é, a oferta de um serviço que possibilite alguém (empresa ou até mesmo consumidor comum) poder consumir recursos computacionais como armazenamento e/ou poder de processamento e pagar somente pelo o que usar, podendo ser esse serviço em Software, Funcionalidades, Infraestrutura, Plataforma e muito mais!

SaaS, FaaS, BaaS, CaaS, IaaS, e PaaS — Tantas siglas de computação em nuvem, o que realmente são?

Software as a Service

Software como serviço é a disponibilização de soluções de tecnologias/softwares como um serviço pela internet, como por exemplo, permitir que o usuário faça seu pagamento com base no que ele usou ou quais funções ele adquiriu.

Function as a Service (Serverless)

Função como serviço (um dos modelos “sem servidor”), é a oferta de um serviço que possibilite a capacidade de implementar soluções, aplicações/softwares sem que haja qualquer envolvimento com a infraestrutura, de forma que os recursos são alocados dinâmicamente.

Backend as a service (Serverless)

Backend como serviço, é o serviço que possibilita a criação de toda infra de dados e execução de código sem ter que provisionar servidores para isso, disponibilizando APIs ou SDKs para que possam ser integradas em uma aplicação web e mobile.

Container as a service (Serverless)

Contêiner como serviço, é uma forma de virtualização baseada em blocos, ou contêineres virtuais, um contêiner é um pacote totalmente isolado, com um código, podendo ser um programa ou uma aplicação que pode ser alterada ou personalizada.

Infrastructure as a Service

Infraestrutura como serviço é o fornecimento de uma infraestrutura totalmente escalável sem que a empresa tenha que se preocupar com a infraestrutura física, e ainda sim pagando pelo o que usar.

Platform as a Service

Plataforma como serviço é a oferta de um ambiente em nuvem feito especificamente para desenvolvimento e a execução de aplicações, podendo oferecer armazenamento e outros recursos que possibilitem customização, testes e muito mais! Isso tudo sem o desenvolvedor ter que se preocupar com infraestrutura e poder focar em desenvolver. Este recurso é o que vamos experimentar!

Serverless realmente é sem servidor?

Não!

Serverless é um modelo arquitetural, que nos permite executar funções na nuvem sem a necessidade de configuração do servidor.

Ou seja, de forma prática seria hospedar uma funcionalidade enquanto dispensa o trabalho de gerenciar um servidor por causa que a plataforma em nuvem será paga para fazer isso, o que torna inexistente o tempo de execução para instalação, mantimento ou admnistração do servidor e propõe uma escalabilidade flexível que culmina em alta disponibilidade e é feita de forma automatizada. Continuam sim existindo servidores em que a aplicação está rodando, mas são contratados como um serviço na nuvem e são alocados dinâmicamente, dado isso, se torna ausente toda preocupação que uma empresa poderia ter em relação a servidores, sendo como se nem existissem, mas existirão e será possível notar na dashbord da cloud utilizada, nos boletos da empresa e na aplicação no ar.

O que exatamente será abordado?

Nesse texto tenho como principal objetivo apresentar a solução encontrada por mim como um início da utilização de ferramentas que te permitam experimentar o mínimo da facilidade e escalabilidade que a computação em nuvem proporciona para uma aplicação.

Dado isso, apresentarei um backend que permite listar nome e imagem de usuários e gravar esses dados no MongoDB Atlas e a imagem no blob storage da Azure, em que demonstrarei passo a passo como fazer.

Não abordarei aspectos super técnicos na parte do I/O envolvendo hardware, pois quero fazer isso futuramente num post de upload de arquivos “na unha” (sem uso de bibliotecas com grande abstração para capturar o arquivo e tratá-lo), será uma saga divertida.

Caso já conheça as tecnologias e tenha o setup inicial, recomendo a navegação com CTRL+F.

O texto está dividido em:

  • TECNOLOGIAS
  • SETUP INICIAL
  • PRÁTICA
  • CONCLUSÕES

Sem mais delongas, vamos a motivação das tecnologias que utilizaremos!

TECNOLOGIAS

Primeiramente, por quê Node.JS?

  • Non-blocking I/O

“Entrada e saída não bloqueante” é a possibilidade de fazer operações de entrada e saída (acesso do sistema de database, filesystem, servers e etc), de forma que a aplicação não fique impedida de executar outros processos em paralelo.

Comumente a entrada e saída demora para ocorrer por causa do hardware que manipula essa operação, mas consome baixo processamento, e dado isso seria um grande desperdício não deixar a aplicação resolver outros processos.

Com isso, algumas técnicas são utilizadas para paralelizar a execução dos processos, cada uma busca atender uma necessidade diferente. Hoje vejo que a mais popular é a Assincronicidade.

Embora seja possível utilizar outras linguagens com suas respectivas bibliotecas e plataformas que podem possibilitar práticas de Assincronicidade, vou usar do Javascript com Node.JS por além de ele ser bom com I/O, também é uma plataforma que eu estou dominando e queria fazer a feature com ela.

Por que não gravar o arquivo no banco de dados ou no disco do servidor?

Quando falamos da base de dados, alguns imaginam que não há local melhor para armazenar um arquivo, simplesmente por imaginarem “ah , também é um dado”, mas não é bem assim que funciona.

Pois, por definição um dado é algo que isoladamente tem seu signifcado implícito e quando se trata de um arquivo, ele pode ou não explicitar uma informação, sem entrar no mérito da discussão entenda que uma boa prática é usar sistema de arquivos para armazenar arquivos e sistemas de dados para armazenar dados.

Infra, espaço de armazenamento tem custo, seja por Gigabyte, disponibilidade, funcionalidade e etc… Um banco de dados te dá possibilidades maiores do tratamento/manipulação/gerenciamento dos dados, não é somente um HD em que os dados são estocados, lembre que também é um sistema e quanto mais dados, maior o custo para prover toda disponibilidade, gerenciamento e espaço de armazenamento.

  • Conclui-se que se você armazenar arquivos no banco de dados, fará com que ele cresça rapidamente, assim diminuindo sua performance de escrita e leitura.

O mesmo serve para guardar os arquivos no servidor que hospeda sua aplicação backend, independente de onde se abriga a sua aplicação, utilizar HD ou SSD, em algum momento a armazenagem de arquivos afetarão a performance da sua aplicação.

Com isso, o melhor dos mundos para armazenar seus arquivos caso você tenha muitos ou o servidor tenha inúmeras requisições que lidam com os arquivos, seria utilizar um serviço de hospedagem de arquivos, como Amazon S3, ou Microsoft Azure Storage ou o Google Cloud Storage, entre outros. E essa solução é interessante por causa que:

  • O seu banco de dados irá salvar somente uma referência para essa imagem que vai estar no seu Storage e não a imagem inteira. Como por exemplo:
https://<contaDoStorage>.blob.core.windows.net/<nomeDoConteiner>/1604761281474-nome-do-usuario_crop.jpg
  • Menor banda sendo tráfegada durante os responses.
  • Pagar somente pelo o que usar, com isso redução de custos.

Com tudo isso explanado, acredito que tenha ficado clara a motivação do uso de um Storage, agora vamos iniciar o setup.

SETUP INICIAL

Pré-requisitos

Recomendável

Com as contas criadas e instalações feitas, vamos ver como seria experimentar recursos de computação em nuvem (PaaS) em 2020,

FINALMENTE,

BORA CODAR!

PRÁTICA

Faremos uma API que possibilitará a criação de um usuário com nome e imagem e também permitirá listagem de todos os usuários, os dados serão persistidos no MongoDB Atlas, sendo eles o nome e a referência da imagem do usuário (um link), que será armazenada no Blob Storage da Azure (Utilizaremos 2 PaaS).

Setup do Projeto

Iniciarei o projeto com yarn e, após isso, adicionarei algumas dependências, da seguinte forma:

yarn init -yyarn add express mongoose dotenv multer multer-azure-storageAlternativa para quem usa npm:npm init -ynpm install express mongoose dotenv multer multer-azure-storage
  • express é um framework que pode servir para construir aplicações web.
  • mongoose é o ODM que utilizaremos para criar um Schema, persistir a coleção e conectar na database.
  • dotenv utilizaremos para carregar as variáveis ambientes.
  • multer é a middleware que irá tratar os arquivos.
  • multer-azure-storage é a integração do multer com o storage da azure.

OBS: Também adicionei o nodemon como dependência de desenvolvimento com o comando `yarn add nodemon -D`, se estiver de npm: npm install nodemon -D, que fará a reinicialização do servidor toda vez que eu salvar um arquivo do app.

Primeiros arquivos!


Estrutura inicial do projeto

Agora na raíz do projeto, eu criarei um arquivo chamado .env e outro arquivo chamado .env.example. No primeiro, colocarei as variáveis ambientes, e no segundo, o exemplo de quais variáveis ambientes são utilizadas nessa aplicação.

No arquivo .env vou colocar as variáveis ambientes do app, mas por hora, somente a porta em que o servidor irá rodar:

⁠#SERVER CONFIG
SERVER_PORT='3333'

#STORAGE
AZURE_STORAGE_CONNECTION_STRING=''
AZURE_STORAGE_ACCESS_KEY=''
AZURE_STORAGE_ACCOUNT=''
AZURE_STORAGE_CONTAINER_NAME=''

#BANCO DE DADOS
MONGODB_CONNECTION_STRING='mongodb://<username>:<password>@cluster0-shard-00-00.8yqbq.mongodb.net:27017,cluster0-shard-00-01.8yqbq.mongodb.net:27017,cluster0-shard-00-02.8yqbq.mongodb.net:27017/<dbname>?ssl=true&replicaSet=atlas-142np6-shard-0&authSource=admin&retryWrites=true&w=majority'

E após isso, vou criar a seguinte estrutura de diretórios no projeto:

./src/config/server.js

No arquivo server.js implementarei a configuração do servidor, como ela mudará conforme escrevermos as rotas, por hora ficará desta forma:


Exportaremos o “app” para colocar o código que inicializa a aplicação na pasta ‘src’.

Agora finalmente inicializaremos o servidor, dentro da pasta src vou criar um arquivo chamado app.js com o seguinte código:

Código do arquivo app.js

Repare que carreguei as variáveis ambientes que vou utilizar para acessar a porta que foi colocada no arquivo .env, também faço a importação da configuração do servidor e por fim adiciono as linhas que inicializam o servidor numa porta.


Scripts start e dev do app

Por fim, no arquivo package.json na raíz do projeto, vou adicionar os scripts ‘start’ e ‘dev’.

  • O script ‘start’ será para inicializar o app.
  • E o script ‘dev’ ficará responsável por inicializar o app com o nodemon fazendo reload do servidor ao salvar um arquivo do app.

Com isso, você já pode utilizar de um dos dois scripts para rodar o app 😉!

Antes de fazermos o modelo, repositório, controladora e rota é importante que façamos o setup da infra na nuvem para que tenhamos em mãos o restante das nossas variáveis ambientes para partir ao restante do código, então bora criar a infra do banco de dados e do storage!

Hora do PaaS! — Criando Cluster no MongoDB e Blob Storage na Azure

MongoDB Atlas

Criando a infra na nuvem da base de dados.

Após acessar a sua conta no MongoDB Atlasa, você estará em uma tela como a imagem abaixo, crie uma organização clicando em “Create New Organization”:

Esse post está sendo migrado do Mediu para cá, caso queira terminar de ler, está disponível pelo Medium nesse Medium.