Salve galera! Tudo certo?

A partir de hoje, iniciarei com vários artigos, cobrindo assuntos diferentes, sobre uso de tecnologias diferentes, fora do escopo C# / .NET, no Azure.

Antes de começarmos, gostaria de explicar minha motivação com estes artigos… Tenho visto que na maioria dos lugares que vou, Azure é sinônimo de uma plataforma Cloud para .NET, e não é nada disso. Azure é uma plataforma de cloud com espaço e suporte para todos, sejam soluções em .NET como NodeJS, Java, Python, GoLang…

Neste artigo, vamos ver como podemos utilizar o TypeScript para criar um pequeno endpoint HTTP através do Azure Functions.

Por que Azure Functions?

Em boa parte de nossas aplicações, quando precisamos de algumas APIs para processamento (entende-se, não estou falando de CRUD neste momento), principalmente em background, ao invés de gastar com uma aplicação / API que fique o tempo todo consumindo recursos e mesmo sendo mais complexa de escalar, podemos utilizar funções serverless.

Uma Azure Function é uma função simples, onde podemos utilizar linguagens conhecidas como C#, Java, TypeScript, JavaScript, etc. para criar trigers que irão acionar nosso código. Estas trigger podem ser desde um endpoint HTTP até consumidores de filas e contas de armazenamento.

Lembrando que uma Azure Function, tem uma “cota” de requisições já inclusa, onde somente vamos começar a pagar após exceder este limite mensal, o que torna o produto bastante atraente para soluções novas, em fase de testes com clientes, como em Startups.

Outro ponto muito interessante de usarmos Serverless no Azure é a escalabilidade, sendo muito mais rápida que no App Service, por exemplo, baseado diretamente na quantidade de requests e tempo de processamento da funçao. Precisamos tomar um cuidado com o tempo de processamento, pois uma função serverless tem um tempo limite de processamento que varia de 5 a 10 minutos dependendo do tipo de trigger e versão da API do Azure Function, sendo que a trigger HTTP (veremos detalhes a seguir), possui um limite de 230 segundos, independente de versão da API.

Configurando o ambiente

Primeiramente, precisamos configurar nosso ambiente de desenvolvimento. Vamos instalar o NodeJS, a partir do endereço https://nodejs.org, podendo ser tanto a versão LTS ou Current, ambas funcionarão para este artigo. A instalação é bem simples, bastando seguir as instruções do setup.

Após a instalação, vamos instalar o Azure Fuctions Core Tools, para podermos trabalhar com Functions. Para isso, vamos executar o comando a seguir:

npm install -g azure-functions-core-tools

Agora, vamos abrir o Visual Studio Code e instalar o plugin abaixo:

https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions

Este plugin é responsável por permitir que criemos, através do Visual Studio Code, um projeto de Azure Functions e ainda que façamos a publicação no Azure.

Feito isto, vamos inciar o projeto!

Configurando o projeto

Primeiramente, vamos criar um diretório para nosso projeto. Vou utilizar o nome de slack-bot (criativo, não?), mas podem utilizar o nome que acharem melhor, ok?

Dentro deste novo diretório, vamos abrir o Visual Studio Code. Com o VS Code aberto, vamos acessar o ícone do Azure na barra de ferramentas lateral, e dentro da seção de functions, vamos clicar no ícone para criar um novo projeto.

Pode ser necessário logar em sua conta do Azure, caso ainda não tenha feito. Ele irá solicitar que faça o login, abrindo uma janela do navegador padrão de seu sistema. Após o login, basta fechar o navegador e o VS Code estará autenticado em sua conta do Azure.

Criando um novo projeto do Azure Functions.

Após clicar em New Project, ele irá solicitar o diretório para criar o projeto. Teremos já a opção do diretório que temos aberto ou Browse, para procurar outra localização para o projeto. Vamos selecionar o diretório atual.

Selecionando o diretório do projeto.

Em seguida, será solicitada a linguagem que vamos utilizar. Temos algumas opções como JavaScript, TypeScript, C#, Python, Java… Vamos escolher TypeScript.

Selecionando qual linguagem vamos utilizar para nossa função.

Em seguida, será solicitado qual o tipo de trigger que irá acionar nossa função. A seguir temos o screenshot da tela de seleção, mas antes de escolher uma opção, vamos entender melhor o que cada um pode fazer.

Selecionando o tipo de trigger da função.

TLDR: Caso não queira ver agora os tipos de triggers que temos disponíveis no Azure, iremos utilizar o tipo HTTP trigger para nossa função, de modo que possamos acessar nossa função via HTTP.

Triggers

Temos alguns tipos de trigger para funções no Azure, sendo:

  • Timer: Uma trigger onde definimos uma expressão Cron para que nossa função seja acionada em intervalos pré-definidos.
  • HTTP: Uma trigger onde um endpoint HTTP é criado, onde podemos utilizar os verbos GET, POST, PUT, DELETE, e a cada requisição, um acionamento da função é feito, podendo inclusive fornecer parâmetros via query string ou através do body da requisição.
  • Azure Blog Storage: Esta trigger permite que quando um blob for criado ou atualizado em uma conta de armazenamento, nossa função seja acionada, com informações do blob em questão. Precisamos tomar cuidado caso estejamos utilizando o plano de consumo, pois se nossa função estiver em estado de “Idle” e tiver um tempo de carregamento grande, podemos impactar no processo de liberação do blob em questão até que a função seja carregada e finalize o processamento. O ideal nestes casos é utilizar o plano de App Service, com a feature de Always On.
  • Azure Cosmos DB: Segue o mesmo padrão, inclusive com recomendações, da trigger de Blob Storage, mas neste caso, monitorando uma determinada collection do Cosmos DB.
  • Azure Event Grid: O Azure Event Grid é um gerenciador de eventos, onde repassa notificações através de uma chamada HTTP ou no caso para a Azure Function, que ele recebe de publicadores. Um blob storage pode ser um publicador, o que quer dizer que o Event Grid é um centralizador de eventos que podemos utilizar para acionar nossa função.
  • Azure Event Hub: O Azure Event Hub é uma plataforma de streaming para big data, podendo receber e processar milhões de registros / eventos por segundo. Cada um destes eventos, inclusive baseados em filtros / condições, pode acionar uma Azure Function.
  • Azure Queue Storage: Nossa função será acionada através de mensagens de uma fila, criada através de contas de armazenamento no Azure. Assim como temos o Blob Storage, temos o Queue Storage, onde recebemos mensagens que serão processadas e armazenadas seguindo o padrão de uma fila, First In First Out.
  • Azure Service Bus Queue and Topic: Temos dois tipos de Service Bus no Azure, o Queue e o Topic, onde basicamente a diferença é que o Queue faz a entrega de 1 para 1, ou seja, ao consumir uma mensagem, ela já não existe mais para outros consumidores. O Topic faz um broadcast, para que vários consumidores, ou subscribers, possam receber uma mesma mensagem e decidirem neles se existe processamente a ser feito ou não. Podemos utilizar o Azure Functions para processar estas mensagens, através desta integração dos serviços.
  • Durable Functions: São funções que permitem um controle e armazenamento de stado em um ambiente serverless, onde além do estado, temos pontos de verificação e até reinicializações gerenciados pelo Azure. Basicamente temos uma função de orquestração, onde outras funções serverless podem ser chamadas, assim como funções internas do código, com pontos de verificação, onde a cada ponto alcançado, temos um progresso atualizado para nossa função orquestradora.

Continuando

Agora que sabemos as triggers existentes, vamos continuar com a criação de nossa trigger. Vamos escolher agora o tipo de controle de autorização que nossa função terá, podendo ser :

  • Anonymous: Qualquer um com o endpoint de nossa trigger HTTP poderá chamar a função. Caso desejemos validar um usuário ou token, precisamos fazer manualmente.
  • Function: Apenas outras funções ou o Admin da conta no Azure tem acesso para chamar a trigger HTTP, sendo que usuários externos não podem acessar.
  • Admin: Apenas o administrador, no caso seu usuário no Azure, poderá fazer uma chamada para esta trigger HTTP.
Escolhendo o tipo de autorização da trigger HTTP.

Vamos escolher a opção Anonymous, assim poderemos chamar nossa função sem problemas pelo Postman.

Agora que temos nossa função criada, assim como a trigger dela, vamos editar o código e colocar um tratamento para calcular a soma de dois números. Para isto, vamos abrir o diretório HTTPTrigger (se não estiver visualizando no projeto, clique no ícone de refresh) em nosso projeto e o arquivo index.ts.

Vamos alterar o arquivo para que fique com o conteúdo a seguir:

Arquivo de código da função alterado.

Resumindo, recebemos dois parâmetros via query string, n1 e n2, e realizamos a soma deles, devolvendo na resposta o número da soma. Caso algum dos parâmetros não seja informado, devolvemos o código HTTP 400 e uma mensagem de erro. Poderíamos fazer alguns tratamentos extras para validar erros, valores inválidos, mas por agora, este exemplo simples serve para testarmos nossa função.

Podemos testar ela localmente apenas executando um Debug, ou teclando F5, no Visual Studio Code. Ao criar uma nova Azure Function, ele já traz o diretório .vscode com os arquivos de configuração para Debug prontos.

Aplicação com Debugger em execução.

Podemos ver no console que nossa função foi carregada localmente, e temos uma URL para acesso, onde ela pode receber uma requisição GET ou POST. Vamos abrir o Postman e fazer uma requisição GET com os valores n1 e n2 na URL, como na imagem a seguir.

Teste no Postman com a função sendo executada localmente.

Podemos ver que ele fez a soma corretamente. Se não informarmos uma das variáveis n1 ou n2, ou enviarmos um caractere não numérico para alguma delas, a função Number em nosso código irá retornar undefined e não irá realizar a soma, devolvendo uma mensagem de erro com código 400.

Teste da mensagem de erro no Postman.

Agora podemos interromper o processo de Debug no Visual Studio Code e começar os procedimentos para publicar nossa função no Azure.

Publicando no Azure

Podemos publicar nossa função diretamente pelo Visual Studio Code, com o plugin do Azure Functions. Após interromper o Debug, vamos acessar novamente o plugin do Azure Functions e clicar no terceiro botão, o de Publish.

Botão publish, indicado pela seta vermelha.

Ele irá questionar qual a assinatura do Azure que você quer utilizar. Em meu caso, vou utilizar a Pago pelo Uso.

Escolhendo a assinatura após clicar no botão Publish.

Após isto, ele irá perguntar qual função no Azure irá receber nosso código. Como ainda não temos nenhuma publicada, vamos escolher a opção de criar uma nova função. Caso tenhamos alguma função já publicada e selecionemos ela, todo o código já publicado será sobreescrito pelo que estamos publicando agora, ok? Cuidado nessa parte.

Escolhendo a opção de criar uma nova função.

Após isto, precisamos dar um nome para nossa Azure Function. Utilizei o nome demo-function-artigo-medium, mas fique a vontade para usar o nome que desejar.

Dando um nome para nossa função.

Podemos verificar agora no Visual Studio Code, na aba Output (existente no painel do Terminal), selecionando os logs da extensão Azure Functions no dropdown a direita do painel, que um Resource Group e a Azure Function estão sendo criados. Ele também criará uma Conta de Storage para armazenar o código de nossa função.

VS Code criando os recursos no Azure.

Ao final ele irá apresentar nos logs que a Azure Function foi criada e a URL base desta. Após alguns segundos, dependendo de sua conexão, ele irá fazer também o deployment de nossa função.

Deployment finalizado da função.

No final dos logs, teremos a URL final com o path para nossa trigger HTTP. Em meu caso, ficou https://demo-function-artigo-medium.azurewebsites.net/api/HttpTrigger, onde posso simplesmente chamar pelo Postman e testar minha função.

A primeira requisição pode demorar mais que o normal, pois nossa função será iniciada, ja que foi criada, por padrão, no plano de consumo. Este tempo, chamamos de warm up, onde nossa função sai do estado de standby para execução. Isto é algo que temos que ter em mente quando utilizamos Functions como APIs para uma aplicação de front-end por exemplo.

Já para processamento em Background, dificilmente este tempo inicial será um problema, podendo ser contornado com o uso do plano de App Service para nossa function, onde podemos definir a configuração de Always On para ela. Isto torna seu custo mais elevado, quando comparamos ao plano de consumo, mas temos o benefício de não ter este tempo de warm up.

Função executando corretamente a soma já publicada no Azure.

Concluindo

Vimos hoje como podemos utilizar o Azure functions para criar pequenos endpoints ou processamento de filas, arquivos, etc., de forma simples, organizada, isolada e com escalabilidade rápida e barata, onde pagamos apenas pelo que usarmos.

Convite!!!

Aproveitando, gostaria de deixar um convite a todos para o Visual Studio Summit 2019, em São Paulo nos dias 21/06/2019 e 22/06/2019, onde estarei apresentando o tema “Blazor, WebAssembly e o futuro do Browser“, com insights sobre o Blazor e como ele pode mudar a forma como construímos aplicações Web e o que temos de novidades com a transição de fase de experimental para preview.

Participe da maior conferência sobre desenvolvimento de software usando Visual Studio e obtenha insights valioso para os seus projetos de software.

Cupom de desconto: palestrante-gustavo (válido até 20/05).

Para mais informações em:
http://vssummit.com.br

Nos vemos lá!

Um abraço a todos e até a próxima.