Conhecendo o Azure Functions
Tags: dotnet, csharp, azure, azurefunctions
Published: 2021-04-01 19:52:32

Nesse artigo vamos conhecer o Azure Functions, o serviço de computação em nuvem **serverless** da Azure. Além de explicar o que é o Azure Functions, vamos ver suas vantagens e desvantagens, suas diferentes formas de executar e exemplos de como implementar. Mais artigos sobre o assunto serão postados em breve por possuir bastante recursos para explorarmos.

## O que é Azure Functions?

Azure Functions é um serviço computacional capaz de executar pedaços de código sem a necessidade de construir uma infraestrutura para isso, por isso é chamado de **serverless**.

As Azure Functions são disparadas/executadas a partir de um evento, os principais eventos utilizados são:
* **HTTP Request** - Executado quando requisitado via http (igual uma api).
* **Timer** - Executado de tempos em tempos ou em uma data específica.
* **Service Bus** - Executado quando uma nova mensagem chega na fila ou tópico. 

Existem outros eventos que podem disparar uma Azure Function e a cada atualização é adicionado novos triggers, você pode checar todos os triggers disponíveis [clicando aqui](https://docs.microsoft.com/pt-br/azure/azure-functions/functions-triggers-bindings?tabs=csharp#supported-bindings).

## Vantagens e desvantagens

### Principais vantagens ao utilizar Azure Functions:
* **Sem infraestrutura para dar manutenção** - Por possuir a infraestrutura totalmente abstraída dentro do serviço, não é necessário se preocupar em administrar ou dar manutenção na infraestrutura, tudo isso é feito pela Azure.
* **Não é cobrado quando não executado** - No plano de consumo as funções são cobradas por execuções realizadas, então mesmo o serviço estando disponível 24 horas por dia, você não é cobrado pela disponibilidade do serviço, diferente de uma VM ou o App Service. Isto não se aplica no plano "App Service Plan".
* **Escalável automaticamente** - o serviço auto gerencia as execuções das funções e sempre garante disponibilidade escalando automaticamente recursos caso necessário, tudo isso invisível para nós.
* **Redução da complexidade do sistema** - Com uma plataforma serverless podemos escrever e executar trechos de código sem se preocupar com complexidades de implantação como sistema operacional, hardware ou servidores. 

### Principais desvantagens:
* **Ficar preso ao fornecedor** - Desenvolver uma aplicação utilizando Azure Functions acaba te prendendo ao fornecedor, neste caso a Azure, isso pode dificultar uma possível mudança de plataforma.
* **Dificuldade em debugar** - É possível debugar as Azure Functions, mas nem sempre é uma tarefa simples recriar o cenário desejado, principalmente quando o número de funções é muito grande.

## Bindings de entrada e saída
Uma das facilidades em utilizar o Azure Functions são os bindings de entrada e saída. Você pode criar uma função onde ela se comunica com recursos externos de uma forma automática e transparente, sem você se preocupar em codificar para isso. Os bindings podem te ajudar tanto a receber um dado de algum recurso como também enviar um dado para algum recurso.

Vamos ver o exemplo abaixo:
```csharp
public static IActionResult Run([HttpTrigger("POST")] HttpRequest request, 
    [Blob("content/settings.json")] string json)
```

Podemos ver que usamos um **HttpTrigger** que além de ser nossa trigger que irá disparar a função ela também recebe os dados da requisição http na variável request, e do lado temos um binding do tipo **Blob** onde recebe na variável json o conteúdo do arquivo settings.json que está armazenado em um serviço de Blob Storage na Azure. Você pode checar todas as possibilidades de binding [clicando aqui](https://docs.microsoft.com/pt-br/azure/azure-functions/functions-triggers-bindings?tabs=csharp#supported-bindings).

Vamos fazer um exemplo para vermos na prática o uso de trigger e os bindings.

## Demonstração 

O Azure Functions permite que você escreva seu código em diversas linguagens como C#, Javascript e Python, esse exemplo será usando C#. Para o nosso exemplo iremos utilizar o Azure Storage Table, um banco NoSQL bem simples e barato da Azure.

Então vamos começar logando no portal da Azure (https://portal.azure.com/) e vamos criar uma nova **storage account** para conseguirmos utilizar o banco Azure Storage Table.
![Criando uma nova storage account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7mnr2vzs1w53arop0xm3.PNG)

Após o portal terminar de criar o recurso, vamos entrar na storage account e clicar em **access keys** no menu lateral e copiar a connectionstring do recurso (pode ser qualquer uma das duas).
![Acessando access keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/geyq1n8not33b5y490cm.PNG)

Agora vamos pro Visual Studio e criar um novo projeto escolhendo Azure Functions.
![Novo projeto azure functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3frq99ox7lx9kvo8y31.PNG)

Vamos criar uma nova função utilizando a trigger Http trigger.
![Escolhendo uma function http trigger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22uuf4cx0puj7qzwh0go.PNG)

Projeto criado, vamos adicionar o pacote nuget via Visual Studio ou comando:

```csharp
dotnet add package Microsoft.Azure.WebJobs.Extensions.Storage
```
Com este pacote conseguiremos usar a nossa storage account na Azure.

Próximo passo é setarmos a connectionstring da storage account, para isso edite o arquivo local.settings.json

```json
{
  "Values": {
    "AzureWebJobsStorage": "<sua-connectionstring>",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}
```

Pronto, agora o projeto está preparado para fazermos nossa Azure Function.

```csharp
using Microsoft.Azure.WebJobs;
using System;

namespace AzureFunctionsExemplo
{
    public class FunctionUsuarioSalvar
    {
        [FunctionName("UsuarioSalvar")]
        [return: Table("Usuario")]
        public Usuario UsuarioSalvar([HttpTrigger("POST")] dynamic request)
        {
            return new Usuario
            {
                PartitionKey = "Http",
                RowKey = Guid.NewGuid().ToString(),
                Login = request.Login
            };
        }
    }

    public class Usuario
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }
        public string Login { get; set; }
    }    
}
```

Pronto, com apenas esse código fizemos uma function que recebe dados à partir de uma requisição http e salva o mesmo em um banco NoSql, não precisa ser feito mais nada. Apesar de ser só um exemplo de demonstração, podemos ver como é muito simples trabalharmos com as Azure Functions. Vamos analisar o código:

`[FunctionName("UsuarioSalvar")]` - Com esse annotation declaramos o nome da função que será usado pelo Azure.
`[return: Table("Usuario")]` - Esse annotation é um binding de saída de dados, estamos utilizando o binding do Azure Storage Table e dizendo que iremos salvar na tabela Usuario.
`public Usuario UsuarioSalvar([HttpTrigger("POST")] dynamic request)` - Note que aqui estamos retornando a classe Usuario o que irá ser feito o binding de saída e também temos declarado a nossa trigger HttpTrigger com o verbo POST recebendo um objeto dynamic.
E por fim retornarmos o objeto Usuario contendo o Login que foi passado via requisição http e as duas propriedades obrigatórias do Azure Storage Table que são o PartitionKey e o RowKey. A PartitionKey serve para criarmos separações entre os documentos presentes na tabela e o RowKey é um identificador único para cada documento.

Execute a aplicação e veja que no console foi disponibilizado um endpoint devido termos usado uma function http trigger, agora é só utilizar o endpoint que iremos ver a requisição sendo salva no banco. No caso aqui eu uso o aplicativo Postman para fazer a chamada do endpoint e o aplicativo Microsoft Azure Storage Explorer para visualizar os dados no banco.
![Dado persistido no banco](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkprd8fsqwp9j8rt63wm.PNG)

Sua function agora está pronta para ser publicada na Azure. Após terminar os testes não se esqueça de excluir o Resource Group utilizado no portal da Azure.

Referência:
[Serverless computing pros and cons: 5 benefits and 3 drawbacks](https://www.techrepublic.com/article/serverless-computing-pros-and-cons-5-benefits-and-3-drawbacks/)