Arquitectura de aplicaciones de Azure

La nube está cambiando la forma en que se diseñan las aplicaciones. En lugar de monolitos, las aplicaciones se descomponen en servicios descentralizados más pequeños. Estos servicios se comunican a través de API o mediante eventos o mensajería asíncrona. Las aplicaciones escalan horizontalmente, agregando nuevas instancias, según lo requiera la demanda.

Estas tendencias traen nuevos desafíos. El estado de la aplicación se distribuye. Las operaciones se realizan en paralelo y asíncronamente. El sistema como un todo debe ser resiliente cuando ocurren fallas. Las implementaciones deben ser automatizadas y predecibles. El monitoreo y la telemetría son fundamentales para obtener información sobre el sistema. La Guía de arquitectura de aplicaciones de Azure está diseñada para ayudarlo a navegar estos cambios.

Los párrafos anteriores están tomados de aquí , y es un buen lugar para diseñar una solución en la nube. Pero me costó mucho dibujar una imagen en mi mente mientras los leía. El mayor desafío fue: ¿por dónde empezar? y ¿cómo sentirse cómodo con Azure Architecture Center?

En esta publicación, demuestro cómo trabajar con varios servicios de Azure que se usan comúnmente en aplicaciones empresariales. Todo el objetivo de este ejercicio es aprender siguiendo el servicio de Azure y diseñar una solución empresarial de alto nivel.

  • función azul
  • Aplicación de función
  • Autobús de servicio
  • Aplicación lógica
  • Servicio de Guardamuebles (mesa)

Guión:

  • La aplicación de consola publica un evento en el tema evento de política de Autobús de servicio.
  • Desencadenar la función de Azure PolicyTopicReaderPolicyTopicReader cuando un suscriptor recibe un mensaje.
  • PolicyTopicReaderPolicyTopicReader llamar Lógica de la aplicación para comenzar a procesar este mensaje.
  • Escriba el Riesgo Creado para Almacenamiento de Azure (tabla) y publique el evento nuevamente en Service Bus.

1.png

  1. PolicyTopicReaderPolicyTopicReader – Código para enviar Mensaje a Tema:
using Microsoft.Azure.ServiceBus;
using System;
using System.Text;
using System.Threading.Tasks;
namespace WriteToTopic
{
    class Program
    {
        const string ServiceBusConnectionString = "Endpoint=sb://neuron.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=mLQjdI6B4U83mG9EFLDhw9t1COULHHLkkyyghZ1/PJg=";
        const string TopicName = "policyevent";
        static ITopicClient topicClient;

        static void Main(string[] args)
        {
            MainAsync().GetAwaiter().GetResult();

            Console.ReadKey();
        }

        static async Task MainAsync()
        {
            const int numberOfMessages = 10;
            topicClient = new TopicClient(ServiceBusConnectionString, TopicName);

            // Send messages.
            await SendMessagesAsync(numberOfMessages);
            await topicClient.CloseAsync();
        }

        static async Task SendMessagesAsync(int numberOfMessagesToSend)
        {
            try
            {
                // Create a new message to send to the topic
                string messageBody = @"{
                                        ""loanKey"": ""beb05058-8b0e-e811-80c7-0025b500b0db"",
                                        ""globalPropertyId"": 151042454,
                                        ""evaluationPeriod"": 
                                            {
                                            ""startDate"": ""2017-08-25"",
                                            ""endDate"": ""9999-12-31""
                                            }
                                        }";
                var message = new Message(Encoding.UTF8.GetBytes(messageBody));

                // Write the body of the message to the console
                Console.WriteLine($"Sending message: {messageBody}");

                // Send the message to the topic
                await topicClient.SendAsync(message);
            }
            catch (Exception exception)
            {
                Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
            }
        }
    }
}

Una vez que se envía el mensaje, se escribe al suscriptor de políticaevento Tema y se puede navegar de la siguiente manera:

2.png

3.png

Al recibir un mensaje de este suscriptor, se desencadena PolicyTopicReaderPolicyTopicReader función.

4.png

5.png

using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text;

private static string logicAppUri = \@"https://prod-25.centralus.logic.azure.com:443/workflows/571ed60873ff46cfa119cabaf2fc818c/triggers/manual/paths/invoke?api-version=2016-10-01\&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=bcU8napBOwEM78XGh-MkdypXcZCcRLPwismZGOIPRxQ";

public static void Run(string mySbMsg, ILogger log)
{
  log.LogInformation(\$"C\# ServiceBus topic trigger function processed message:{mySbMsg}");
  using (var client = new HttpClient())
  {
    var response = client.PostAsync(logicAppUri, new StringContent(mySbMsg,	Encoding.UTF8, "application/json")).Result;
  }
}

Un punto importante a tener en cuenta aquí es que CORS está configurado para permitir que todos

.  Esto se encuentra en la función Plataforma de la aplicación de funciones.

6.png

Esto llama a la aplicación lógica para procesar el mensaje de evento.

7.png

8.png

9.png

Obtener Período de Evaluación:

10.png

11.png

12.png

\#r "Newtonsoft.Json"

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

public static async Task\<IActionResult\> Run(HttpRequest req, ILogger log)
{
  if (req == null) throw new ArgumentNullException(nameof(req));
  if (req.Body == null) throw new ArgumentNullException(nameof(req));
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

  if (string.IsNullOrEmpty(requestBody)) throw new ArgumentNullException(nameof(requestBody));

  var evaluationRequest = JsonConvert.DeserializeObject\<EvaluationRequest\>(requestBody);

  if (evaluationRequest == null) throw new ArgumentNullException(nameof(evaluationRequest));

  if (evaluationRequest.EvaluationPeriod == null) throw new ArgumentNullException(nameof(evaluationRequest.EvaluationPeriod));

  // Add clamp logic to evaluation period

  evaluationRequest.EvaluationPeriod.StartDate = evaluationRequest.EvaluationPeriod.StartDate \< DateTime.Parse("02/10/2018")
  ? DateTime.Parse("02/10/2018")
  : evaluationRequest.EvaluationPeriod.StartDate;
  return (ActionResult)new OkObjectResult(evaluationRequest);
}

public class EvaluationRequest
{
  public Guid LoanKey { get; set; }
  public int GlobalPropertyId { get; set; }
  public EvaluationPeriod EvaluationPeriod { get; set; }
}

public class EvaluationPeriod
{
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

13.png

ObtenerPeríodoRequerido:

14.png

15.png

16.png

\#r "Newtonsoft.Json"

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;

public static async Task\<IActionResult\> Run(HttpRequest req, ILogger log)
{
  if (req == null) throw new ArgumentNullException(nameof(req));
  if (req.Body == null) throw new ArgumentNullException(nameof(req));
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

  if (string.IsNullOrEmpty(requestBody)) throw new ArgumentNullException(nameof(requestBody));
  var evaluationRequest = JsonConvert.DeserializeObject\<EvaluationRequest\>(requestBody);
  if (evaluationRequest == null) throw new ArgumentNullException(nameof(evaluationRequest));
  if (evaluationRequest.EvaluationPeriod == null) throw new ArgumentNullException(nameof(evaluationRequest.EvaluationPeriod));

  return (ActionResult)new OkObjectResult(GetRequiredPeriods(evaluationRequest));
}

public static IEnumerable\<RequiredPeriod\> GetRequiredPeriods(EvaluationRequest evaluation)
  {
  return new RequiredPeriod[]
  {
    new RequiredPeriod(){ StartDate = evaluation.EvaluationPeriod.StartDate, EndDate = evaluation.EvaluationPeriod.EndDate, CvgType = CvgType.WI, Peril= Peril.Fire, RiskType = RiskType.Lapse},
    new RequiredPeriod(){ StartDate = evaluation.EvaluationPeriod.StartDate, EndDate = evaluation.EvaluationPeriod.EndDate, CvgType = CvgType.WI, Peril= Peril.Fire, RiskType = RiskType.Gap},
    new RequiredPeriod(){ StartDate = evaluation.EvaluationPeriod.StartDate, EndDate = evaluation.EvaluationPeriod.EndDate, CvgType = CvgType.SO, Peril= Peril.Fire, RiskType = RiskType.Lapse},
    new RequiredPeriod(){ StartDate = evaluation.EvaluationPeriod.StartDate, EndDate = evaluation.EvaluationPeriod.EndDate, CvgType = CvgType.SO, Peril= Peril.Fire, RiskType = RiskType.Gap},
  };
}

public class EvaluationRequest
{
  public Guid LoanKey { get; set; }
  public int GlobalPropertyId { get; set; }
  public EvaluationPeriod EvaluationPeriod { get; set; }
}

public class EvaluationPeriod
{
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public class RequiredPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public enum Peril
{
  Fire = 1,
  Flood = 2,
  Wind = 3,
  Hurricane = 5
}

public enum RiskType
{
  Lapse = 1,
  Gap = 2
}

public enum CvgType
{
  WI = 1,
  SO = 2,
  ES = 3
}

17.png

Obtener período de elegibilidad:

18.png

19.png

20.png

\#r "Newtonsoft.Json"

using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task\<IActionResult\> Run(HttpRequest req, ILogger log)
{
  if (req == null) throw new ArgumentNullException(nameof(req));
  if (req.Body == null) throw new ArgumentNullException(nameof(req));
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

  if (string.IsNullOrEmpty(requestBody)) throw new ArgumentNullException(nameof(requestBody));
  var requiredPeriods = JsonConvert.DeserializeObject\<IEnumerable\<RequiredPeriod\>\>(requestBody);
  if (requiredPeriods == null) throw new	ArgumentNullException(nameof(requiredPeriods));
  return (ActionResult)new OkObjectResult(GetEligibilityPeriods(requiredPeriods));
}

public static IEnumerable\<EligibilityPeriod\> GetEligibilityPeriods(IEnumerable\<RequiredPeriod\> requiredPeriods)
{
  return requiredPeriods
  .Select(req =\> new EligibilityPeriod(){ StartDate = DateTime.Now, EndDate =
    DateTime.MaxValue, CvgType = CvgType.WI, Peril= Peril.Fire, RiskType =
    RiskType.Lapse})
  .ToList();
}

public class EvaluationRequest
{
  public Guid LoanKey { get; set; }
  public int GlobalPropertyId { get; set; }
  public EvaluationPeriod EvaluationPeriod { get; set; }
}

public class EvaluationPeriod
{
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public class RequiredPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public class EligibilityPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public enum Peril
{
  Fire = 1,
  Flood = 2,
  Wind = 3,
  Hurricane = 5
}

public enum RiskType
{
  Lapse = 1,
  Gap = 2
}

public enum CvgType
{
  WI = 1,
  SO = 2,
  ES = 3
}

21.png

IdentificarRiesgo:

22.png

23.png

24.png

\#r "Newtonsoft.Json"

using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task\<IActionResult\> Run(HttpRequest req, ILogger log)
{
  if (req == null) throw new ArgumentNullException(nameof(req));
  if (req.Body == null) throw new ArgumentNullException(nameof(req));
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
  if (string.IsNullOrEmpty(requestBody)) throw new ArgumentNullException(nameof(requestBody));
  var eligibilityPeriods = JsonConvert.DeserializeObject\<IEnumerable\<EligibilityPeriod\>\>(requestBody);
  if (eligibilityPeriods == null) throw new	ArgumentNullException(nameof(eligibilityPeriods));
  return (ActionResult)new OkObjectResult(GetLrps(eligibilityPeriods));
}

public static IEnumerable\<LenderRiskPeriod\> GetLrps(IEnumerable\<EligibilityPeriod\> eligibilityPeriods)
{
  return eligibilityPeriods
  .Select(e => new LenderRiskPeriod()
  {
    StartDate = e.StartDate,
    EndDate = e.EndDate,
    CvgType = e.CvgType,
    Peril = e.Peril,
    RiskType = e.RiskType,
    Amount = 100
  })
  .ToList();
}

public class LenderRiskPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
  public int Amount { get; set; }
}

public class EligibilityPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

public enum Peril
{
  Fire = 1,
  Flood = 2,
  Wind = 3,
  Hurricane = 5
}

public enum RiskType
{
  Lapse = 1,
  Gap = 2
}

public enum CvgType
{
  WI = 1,
  SO = 2,
  ES = 3
}

25.png

Guardar y publicar:

26.png

27.png

28.png

\#r "Newtonsoft.Json"

using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task\<IActionResult\> Run(HttpRequest req,ICollector\<LoanProperty\> tableBinding, ICollector\<string\> queueCollector, ILogger log)
{
  if (req == null) throw new ArgumentNullException(nameof(req));
  if (req.Body == null) throw new ArgumentNullException(nameof(req));
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
  if (string.IsNullOrEmpty(requestBody)) throw new ArgumentNullException(nameof(requestBody));

  var lrps = JsonConvert.DeserializeObject\<IEnumerable\<LenderRiskPeriod\>\>(requestBody);
  if (lrps == null) throw new ArgumentNullException(nameof(lrps));
  log.LogInformation(\$"Adding LenderRiskPeriod");
  var riskProfile = JsonConvert.SerializeObject(lrps).ToString();
  tableBinding.Add(
    new LoanProperty() {
      PartitionKey = Guid.NewGuid().ToString(),
      RowKey = Guid.NewGuid().ToString(),
      ClientPortfolioId = 1,
      LoanKey = Guid.NewGuid().ToString(),
      GlobalPropertyId = 1,
      LenderRiskPeriod = riskProfile
    }
  );

  queueCollector.Add(riskProfile);
  return (ActionResult)new OkObjectResult(null);
}

public class LoanProperty
{
  public string PartitionKey { get; set; }
  public string RowKey { get; set; }
  public string LoanKey { get; set; }
  public int ClientPortfolioId { get; set; }
  public long GlobalPropertyId { get; set; }
  public string LenderRiskPeriod { get; set; }
}

public class LenderRiskPeriod
{
  public Peril Peril { get; set; }
  public CvgType CvgType { get; set; }
  public RiskType RiskType { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
  public int Amount { get; set; }
}

public enum Peril
{
  Fire = 1,
  Flood = 2,
  Wind = 3,
  Hurricane = 5
}

public enum RiskType
{
  Lapse = 1,
  Gap = 2
}

public enum CvgType
{
  WI = 1,
  SO = 2,
  ES = 3
}

29.png

Respuesta:

30.png

31.png

Verifique el resultado en la tabla de Azure Storage

32.png

33.png

Verificar el resultado en Service Bus

34.png

  1. Notas adicionales

El siguiente ejemplo muestra cómo puede construir una variable y asignarle valores.

  1. 35.png

    Jerarquía de abstracción de servicios de Azure:

  2. IaaS > Azure Service Fabric > App Service > Aplicación lógica y funciones de Azure

Similar Posts

Leave a Reply

Your email address will not be published.