fbpx
Azure Functions + Containers (Parte 1/2)
Publicado em: domingo, 21 de jun de 2020

Certa vez rolou uma discussão sobre Function as a Service (FaaS) e Containers questionando se um suplantaria o outro, ou se seríamos capazes de ignorar um em função do outro. Minha resposta curta e objetiva é: Não! Functions e Containers se complementam.

Sempre que olharmos para Function as a Service, o Lock-in bate à sua porta.

Lock-in é um problema?

Sim! Pode ser, da mesma forma como não! Pode simplesmente não significar absolutamente nada.

Lock-In é um problema quando estar preso a um vendor, não fizer parte do seu planejamento de risco.

Ou você aceitou estar preso ao vendor, e essa decisão foi deliberada (para esse cenário ou previamente com outras decisões anteriores), ou alguém ignorou a questão e ficou no limbo. Nesse último caso estamos falando de falha e as implicações de negligenciar riscos e trade-offs.

Functions

As soluções de FaaS exercem o papel de hospedar nossas funções, em geral escrevemos em uma entre várias tecnologias e conectamos nossas funções à plataforma. Uma vez publicada nossa função, definimos quem são os estímulos que passarão os dados para nossa função.

Esses runtimes são preparados para hospedar nosso código e lidar com escala dessas funções, evitando que tenhamos a necessidade de pensar sobre os aspectos de hospedagem desse código. Ele simplesmente está lá disponível 24/7 e executa o que precisa ser executado.

Containers

Em outra direção containers trazem a abstração clara de processos e um modelo de empacotamento incrível, oferecendo portabilidade. Portabilidade se traduz naturalmente em eliminar reduzir ou até eliminar o lock-in. Containers docker rodam da mesma forma em qualquer cloud provider, da mesma forma que em qualquer IaaS, incluindo VPS’s baratas ao redor do mundo, da mesmíssima forma como roda também no bare metal. Esse poder nunca foi tão popular.

Function vs Containers

Ainda há quem defenda a concorrência entre as duas estratégias e ache redundante pensar na soma das duas.

Ainda há quem considere que entender de containers é coisa de infra, de DevOps.

Cagando regra…

Container é um assunto de todos os técnicos. Incluindo e principalmente o DEV, especialmente se ele trabalhar com Backend . Independente de ser fullstack ou não, é no backend que falamos de containers docker, no entanto até quando disponibilizamos SPA’s ou caches varnish, quem está no front-end tem a chance de passar a lidar com esse tipo de tecnologia, dada a arquitetura e estratégia.

Function ❤️ Containers

Uma das minhas defesas contra o lock-in é o uso de standards e containers.

Nesse caso design patterns + containers são fundamentais para reduzir o acoplamento entre seus serviços e a lógica específica de um projeto de functions.

Mas o que é necessário para evitar Lock-in?

Na prática dificilmente vamos zerar o esforço de fazer funções agnósticas, mas podemos reduzir substancialmente o escopo do esforço na hora de portar ou mesmo migrá-las.

Agnostic Services

Um dos padrões que mais gosto é o Agnostic Services. A versatilidade com que esse padrão pode ser aplicado a qualquer cenário em que há demandas específicas da tecnologia de hospedagem é absurda. Ele oferece um isolamento absoluto que blinda seu core code de ser poluído com código específico para lidar com a hospedagem A, B ou C.

Nesses casos um serviço feito sob os preceitos de Agnostic Services, facilmente pode ser usado em SignalR, WCF, Web API, gRPC, e até AMQP RPC ou protocolos futuros não inventados ainda. Vai depender apenas das demandas de serialização das mensagens.

E naturalmente um serviço Agnóstico pode ser usado por uma function em qualquer cloud provider que suporte sua tecnologia.

Proxy

Com Agnostic Service, o código específico de uma Azure Function por exemplo, tem o papel de ser um proxy tecnológico para nosso core.

E aqui vai o spoiler: ter um core independente da tecnologia é o que nos dá esse poder.

A anatomia de uma Function

Abaixo temos a anatomia de uma function:

public static class HttpExample
{
    [FunctionName("HttpExample")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        
        string name = req.Query["name"]; 

//--------------- CORE - INICIO

        name = name ?? data?.name;

        string responseMessage = string.IsNullOrEmpty(name)
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
            : $"Hello, {name}. This HTTP triggered function executed successfully.";

//--------------- CORE - FIM

        return new OkObjectResult(responseMessage);
    }
}

 

Entre as linhas 16 e 24 temos a implementação do que seria o corpo da função.

O que acontece antes da linha 16 é meramente desserialização e obtenção de parâmetros: Algo específico da tecnologia em questão.

O que acontece após a linha 16, também é pertinente exclusivamente à tecnologia de hospedagem da função.

Embora o exemplo seja simples demais até para nosso exemplo, vale o exercício.

A nova versão seria algo assim:

public static class HttpExample
{
    [FunctionName("HttpExample")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        
        string name = req.Query["name"]; 

//--------------- CORE - INICIO

        string responseMessage = new ExampleA.ServiceB.FunctionC(name);

//--------------- CORE - FIM

        return new OkObjectResult(responseMessage);
    }
}

 

O código relevante, com as regras de negócio estão em ExampleA.ServiceB.FunctionC, um assembly, empacotado como um pacote nuget.

Esse pacote pode ser reaproveitado em qualquer lugar, principalmente nos testes unitários, mas também por outros proxies de outras tecnologias.

Esse isolamento proporciona que esse código possa ser usado em:

  • Azure Functions (ou qualquer outro Function as a Service que suporte .NET)
  • SignalR
  • RabbitMQ RPC
  • WCF
  • gRPC
  • Web API
  • Embarcado como uma dependência

E que diferença faz ter Docker ou não?

Aí entra o caráter agnóstico não só do código, mas também da hospedagem. Ganhamos aqui a capacidade de lidar com dependências complexas.

Imagine que essa function seja um OCR, Tesseract talvez, que tal? Como vimos no post Tesseract OCR + ASP.NET Core (Dockerfile), lembra?

O controle e o poder do Docker entram aqui, viabilizando instalações complexas das mais variadas naturezas.

Nós vimos algo semelhante no youtube downloader, com as demandas do python necessário pra rodar o youtube-dl.

Próximo passo

Fique de olho que mais tarde eu publico um tutorial sobre Azure Functions 3 com Containers, tem umas complicações com Azure Functions 3 e precisamos mostrar como resolver isso.

Quer saber mais sobre Azure Functions?

Te indico o material do Renato Groffe no Medium.

Se precisa de um treinamento sobre Serverless + Azure Functions, o Renato, o Milton e o Ericson encabeçam o Azure na Prática que pode te ajudar nessa direção.

Aliás, um passarinho me contou que vai rolar o Azure na Prática #13 – Serverless + Azure Functions #03, e está em pré-venda. Vale lembrar que em pré-venda, são R$ 400 reais de desconto.

Azure na Prática – Serverless + Azure Functions

Vai rolar no dia 29/08/2020 (sábado), com foco em Serverless + Azure Functions e englobando o uso de tecnologias como:
Azure Logic Apps, RabbitMQ, Apache Kafka, SQL Server, MongoDB, Redis, Application Insights, Azure Cosmos DB e GitHub Actions.

Acesse então o link a seguir para efetuar sua inscrição com o desconto especial de pré-venda (apenas R$ 200,00).
Sim, é isso mesmo! De R$ 600 por R$ 200!!!!

Quer saber mais sobre Docker & .NET + Open Source?

No mais, se quiser saber mais sobre Docker e .NET, principalmente Open Source e .NET vem comigo que também tenho muita coisa legal!

0 comentários

Enviar um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

[docker de a a z]

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.