Leobreda.net

Web, .Net,
SQL, Cloud...

Criando função AWS Lambda utilizando .Net Core

Processe um console window sem a necessidade de provisionar uma instância EC2

Afinal de contas, o que é o AWS Lambda?

Em poucas palavras, é um console window que processa um volume de informações, dentro de um servidor qualquer. E só.

Dá pra fazer bastante coisa num console window: processamento batch, bulk insert no sql, disparo de e-mails em massa, etc.

Por ser "apenas" um console window, a parte de servidor é abstraída. Isso significa que você não precisa se preocupar em configurar o Sistema Operacional, atualizações de segurança, patches, etc. Basta realizar o upload do executável.

Tudo isso denominado serverless

Essa facilidade serverless pode trazer outros problemas: é 15% mais lento e até 8x mais caro que uma instância EC2.
Entretanto, a vantagem é que não se paga por 720h mensais, mas sim pelo tempo de cada execução.
Se a sua necessidade é construir uma ferramenta de disparo de e-mails 5x no mês e cada execução demora 5 minutos, não pense 2x em utilizá-lo! Sai bem mais barato que reservar uma instância EC2 para um processo tão simples.

Histórias a parte, vamos ao que interessa! Iremos construir uma função ASW Lambda em .Net Core :-)


1. Criando a função na AWS

Acesse o console AWS https://console.aws.amazon.com/ , Lambda, Funções.
Clique no botão Criar Função.

Selecione a opção Criar do Zero...

Nome da função: minhaFuncao
Tempo de execução: .NET Core 3.1

Em Permissões, marque a opção Criar uma função com permissões básicas do Lambda. Clique no botão Criar função.

Por fim a função é criada.


No Visual Studio, crie um Projeto vazio do tipo Console Window, na linguagem .Net Core 3.1.


Program.cs:

    using Amazon.Lambda.Core;
    using System;
    using System.Collections;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Configuration;
    using System.IO;
    using System.Net;
    
    namespace ConsoleLambda
    {
        public class Program
        {
            public static IConfigurationRoot Configuration;
    
            public static IConfiguration configuration { get; private set; }
    
            /// <summary>
            /// Este método só será executado durante o Debug.
            /// Não será invocado via execução AWS Lambda
            /// </summary>
            /// <param name="args"></param>
            static void Main(string[] args)
            {
                Console.WriteLine("Main!");
                Program instancia = new Program();
    
              
                LambdaContext lambda = new LambdaContext();
    
                instancia.Handler(lambda);
            }
    
            private void ConfigureSettings()
            {
                Configuration = new ConfigurationBuilder()
                .SetBasePath(System.IO.Directory
                    .GetParent(AppContext.BaseDirectory).FullName)
                 .AddJsonFile("appsettings.json", optional: true)
                 .Build();
    
                // Não esqueça de habilitar a opção 
                // "Copiar diretório de saída" para o arquivo appsettings.json,
                // caso contrário, Configuration sempre será NULL
            }
    
            public async Task Handler(ILambdaContext context)
            {
                this.ConfigureSettings();
    
                StringBuilder sb = new StringBuilder();
    
                sb.AppendLine("Hello World! My name is Lambda ;-)");
                sb.AppendLine("");
                sb.AppendLine("Variaveis de ambiente:");
    
                foreach (DictionaryEntry de in Environment.
                    GetEnvironmentVariables())
                    sb.AppendLine(de.Key + " = " + de.Value);
    
                sb.AppendLine("========================");
                sb.AppendLine("ILambdaContext:");
                sb.AppendLine("FunctionName: " + context.FunctionName);
                sb.AppendLine("RemainingTime: " + context.RemainingTime);
                sb.AppendLine("AwsRequestId: " + context.AwsRequestId);
                sb.AppendLine("FunctionVersion: " + context.FunctionVersion);
                sb.AppendLine("InvokedFunctionArn: " + context.InvokedFunctionArn);
                sb.AppendLine("LogGroupName: " + context.LogGroupName);
                sb.AppendLine("LogStreamName: " + context.LogStreamName);
                sb.AppendLine("MemoryLimitInMB: " + context.MemoryLimitInMB);
                sb.AppendLine("null: " + null);
    
                sb.AppendLine("========================");
                sb.AppendLine("appsettings:");
                sb.AppendLine("Versao: " + Configuration["versao"].ToString());
                sb.AppendLine("Autor: " + Configuration["autor"].ToString());
    
                Console.WriteLine(sb.ToString());
    
                // Testando requisições internet (teste de firewall)
                var requisicaoWeb = WebRequest.CreateHttp("https://www.leobreda.net/");
                requisicaoWeb.Method = "GET";
                using (var resposta = requisicaoWeb.GetResponse())
                {
                    var streamDados = resposta.GetResponseStream();
                    StreamReader reader = new StreamReader(streamDados);
                    object objResponse = reader.ReadToEnd();
                    Console.WriteLine(objResponse.ToString());
                    Console.ReadLine();
                    streamDados.Close();
                    resposta.Close();
                }
            }
        }
    }  

LambdaContext.cs (necessário para executar localmente o console window):

    using Amazon.Lambda.Core;
    using System;
    
    namespace ConsoleLambda
    {
        public class LambdaContext : ILambdaContext
        {
            public string AwsRequestId => null;
            public IClientContext ClientContext => null;
            public string FunctionName => null;
            public string FunctionVersion => null;
            public ICognitoIdentity Identity => null;
            public string InvokedFunctionArn => null;
            public ILambdaLogger Logger => null;
            public string LogGroupName => null;
            public string LogStreamName => null;
            public int MemoryLimitInMB => 0;
            public TimeSpan RemainingTime => new DateTime().TimeOfDay;
        }
    }

appsettings.json (arquivo de configuração do console window):

{
    "versao": "2020.10.20.a",
    "autor": "Leonardo Breda"
}

NuGet:

Amazon.Lambda.Core
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.FileExtensions
Microsoft.Extensions.Configuration.Json

Execute o console em debug para verificar se rodou com sucesso.


Faça a publicação do projeto...


Configuração: Release
Estrutura de destino: netcoreapp3.1
Tempo de execução de destino: linux-x64

Clique em publicar.


Vá até o diretório de destino e compacte todos os arquivos num único ZIP.


Volte até a função Lambda no console AWS. Em código da função, faça o upload do arquivo ZIP.


Na aba Permissões, Papel de execução, clique em Editar.


No campo manipulador, adote a seguinte nomenclatura:
Assembly::Namespace.Classe::Metodo

Clique em salvar.


Clique no botão Testar. Caso não tenha um teste associado, crie conforme a figura abaixo.


Clique novamente no botão Testar, onde deverá processar a função com sucesso .


No quadro resumo, é possível identificar o tempo de execução e memória RAM consumida.


No CloudWatch, é possível ver toda a saída produzida pelo console window.

E assim concluímos um aprendizado básico do AWS Lambda.




Acessar todos os artigos »