Introducción a Dapr .NET SDK (1/N) y «Service-to-service invocation»


Estas últimas semanas he comenzando a aventurarme con Dapr. El propósito es comenzar a usarlo en proyectos para nuevos clientes. Aunque ya lo conocía desde un punto de vista teórico he de decir que me está sorprendiendo para bien. Tanto en este post como en otros que vendrán voy a tratar de ir escribiendo mis experiencias con el fin de ir conocíendolo. Me centraré principalmetne en usar el SDK de .NET. No obstante, podrás comprobar que es simplemente cuestión de gustos. Uno de los principios de Darps es precisamente ser independiente del lenguaje.

En mi github iré dejando todos y cada unos de los ejemplos/pruebas/demos.

A continuación, el listado completo de posts relacionados sobre los que iré trabajando y publicando:

Introducción

Antes de nada indicar, que la documentación más valiosa hasta el momento la podemos encontrar en https://docs.dapr.io, y es la que estoy usando como referencia principalmente.

Dapr significa Distributed Application Runtime. Y, lo definiría como una capa de abstracción independiente del lenguaje y agnostico a la infraestructura/plataforma, que permite el desarrollo y ejecución de aplicaciones elásticas, orientadas a eventos y distribuidas. Ayuda a los desarrolladores a centrarse en la lógica de la aplicación y conseguir un código sencillo y portable.

Con la siguiente imagen profundizamos en la definición de Dapr categorizando sus objetivos y/o principios.

Building blocks

Uno de los principios se centra en el desarrollo basado en la construcción haciendo uso de «Building Block«. Y, un Building Block, no es ni mas ni menos que un API HTTP o gRPC que puede ser llamada desde código y usar a su vez uno o más componentes Dapr. De igual forma, existen algunos SDKs que permiten hacer uso de Dapr de una forma mucho más sencilla:

Elige un SDK y un Framework y podrás gobernar cualquier Infraestructura (gracias a los componentes)

El listado de Building Blocks es el siguiente:

Podemos encontrar más detalle aquí: https://docs.dapr.io/concepts/building-blocks-concept/

Componentes

Otro de los pilares fundamentales de Dapr, son los componentes (o Components), que podemos definir como la unidad funcional en la que se apoyan los Building Blocks que sigue un diseño modular, tiene una definición de interfaz y, que por tanto puede ser intercambiado por otro componente que mantenga la misma interfaz.

Desde un punto de vista de arquitectura, ahora si que Dapr va a facilitarnos la respueta a los «por si acaso» del tipo: ¿Y si usamos Azure y despues migramos a AWS?, ¿Y si en lugar de Azure Service Bus usamos RabbitMQ? y si, …

Actualmente exite un repositorio Git, donde se contribuye para la creación de más y más componentes que permiten así extender y ampliar la capacidad de Dapr. La siguiente imagen muestra numerosos componentes para los distintos tipos de Building Blocks:

Mas detalle aquí: https://docs.dapr.io/concepts/components-concept/

Arquitectura Sidecar

sidecar pattern

Finalmente, concluimos esta introducción y conceptos con este otro pilar, la Arquitectura o Patrón Sidecar, de manera que cada una de las APIs HTTP y gRPC son expuestas como contenedor o como proceso independiente que no requiere que el código de la aplicación incluya ningún runtime de ejecucíon para Dapr. Lo que facilita la integración con otros runtimes así como la separación de la lógica de la aplicación para mejorar la compatibilidad. Es decir, desarrollamos la aplicación y de la ejecución ya se encarga Dapr.

Entorno de desarrollo

Instalar Dapr CLI

Inicializar Darp en el entorno local. Dicha inicialización de manera predeterminada e implicita incluye la ejecución de los contenedores:

  • Redis para el almacenamiuento de estados,
  • Zipkin para observabilidad,
  • Componentes predeterminados, situados en la carpeta de usuario: «%USERPROFILE%.dapr\» y,
  • Dapr placement para el soporte local de Actores.
dapr init

Aunque es posible inicializar Dapr en un entorno sin Docker, por el momento nos centraremos en trabajar con Docker como dependencia, por lo que necesitaremos tener Docker instalado.

Service-to-service invocation

Veremos a continuación un ejemplo de «Service-to-service invocation» (o invocación entre servicios) con dos opciones posibles.

El ejemplo se basa en dos API Rest desarrolladas en ASP.NET 5.0. Concretamente creadas a partir de la plantilla básica «webapi». Una de ellas actua como backend (o api invocada) y la otra como proxy (o api invocadora).

Una vez creadas ambas apis, continuar como sigue, para el proyecto/api de tipo «proxy»:

Añadir el paquete nuget: «Dapr.AspNetCore»

Opción 1: Uso de Dapr HttpClient

Crear la clase «WeatherForecastClient.cs«, que será la encargada de mostrar el uso de HttpClient para llamar al API Rest que actua como backend. Como se puede observar, es el mismo uso que hacemos habitualmente en nuestros proyectos.

public class WeatherForecastClient : IWeatherForecastClient
{
    private readonly HttpClient _backendHttpClient;
    public WeatherForecastClient(HttpClient backendHttpClient)
    {
        _backendHttpClient = backendHttpClient;
    }
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecast(int count)
    {
        var weatherForecasts =
            await _backendHttpClient.GetFromJsonAsync<List<WeatherForecast>>("weatherforecast");
        return weatherForecasts?.Take(count);
    }

Opción 2: Uso de DaprClient

De la misma fora, crear la clase «WeatherForecastInvokeClient.cs«, donde aquí ya vemos algunos cambios destacables.

public class WeatherForecastInvokeClient : IWeatherForecastClient
{
    private readonly DaprClient _daprClient;
    private readonly ILogger _logger;
    public WeatherForecastInvokeClient(DaprClient daprClient,
        ILogger<WeatherForecastInvokeClient> logger)
    {
        _daprClient = daprClient;
        _logger = logger;
    }
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecast(int count)
    {
        _logger.LogInformation($"Using DaprClient to invoke/call Service (Backend) !");
        var weatherForecasts =
            await _daprClient.InvokeMethodAsync<List<WeatherForecast>>(
                HttpMethod.Get, "backend", "weatherforecast");
        return weatherForecasts?.Take(count);
    }
}

Incluir en el «Startup.cs», el siguiente código tal y como muestra la imagen:

Injección de HttpClient y DaprClient en ASP.NET Core / 5.x

Nota: En el appSetgings.json podemos cambiar el valor de la propiedad UseDaprInvoke, y probar así las opciones 1 y 2 respectivamente.

Hasta aquí es todo lo que necesitamos desarrollar. Seguidamente veremos como el runtime de Dapr se encarga del resto. Para ello, ejecutar las dos instrucciones siguienes en dos terminales de windows diferentes:

dapr.exe run --app-id proxy --app-port 5001 --dapr-http-port 3501 --app-ssl dotnet run -- --urls=https://localhost:5001/ -p WeatherForecastProxyService/WeatherForecastProxyService.csproj
dapr.exe run --app-id backend --app-port 5000 --dapr-http-port 3500 --app-ssl dotnet run -- --urls=https://localhost:5000/ -p WeatherForecastService/WeatherForecastService.csproj

Para simplificar, podemos ejecutar el script «start.ps1» desde una termina de PowerShell: «.\start.ps1«, lo que nos abrirá y ejecutará ambas aplicaciones simultaneamente en dos terminales «Windows Terminal«.

$ProxyDapr = 'dapr.exe run --app-id proxy --app-port 5001 --dapr-http-port 3501 --app-ssl dotnet run -- --urls=https://localhost:5001/ -p WeatherForecastProxyService/WeatherForecastProxyService.csproj'
$Proxy = '--title "Proxy" -- pwsh.exe -Interactive -NoExit -Command ' + "$ProxyDapr"
$BackendDapr = 'dapr.exe run --app-id backend --app-port 5000 --dapr-http-port 3500 --app-ssl dotnet run -- --urls=https://localhost:5000/ -p WeatherForecastService/WeatherForecastService.csproj'
$Backend = '--title "Backend" -- pwsh.exe -Interactive -NoExit -Command ' + "$BackendDapr"
$cmd = '-M -w -1 nt -d . ' + $Proxy + '; split-pane -d . ' + $Backend
Start-Process wt $cmd

Importante: el parámetro «–app-id» (backend), tiene que coincidir con el indicado anteriormente en el código de la aplicación para que el discovery pueda realizarse con éxito:

  • DaprClient.createInvokeHttpClient(«backend») y
  • _daprClient.InvokeMethodAsync<List<WeatherForecast>>(HttpMethod.Get, «backend«, «weatherforecast») .

El código completo de este ejemplo se encuentra aquí, en github

En siguientes post sobre Dapr, veremos también como depurar y continuaremos conociendo mucho mas de Dapr. ¡Espero que sea de utilida!

Happy #Dapr coding !!

Referencias:

PS: Thanks @laurentKempe to make me easy the way to learn Dapr !

Anuncio publicitario

14 comentarios sobre “Introducción a Dapr .NET SDK (1/N) y «Service-to-service invocation»

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.