Creación de microservicios idempotentes basados en eventos

Creación de microservicios idempotentes basados en eventos

Creación de un microservicio para usar en el ejemplo

Utilizaremos un microservicio basado en la plataforma Devprime

  • Utilice una cuenta activa en Devprime y habilite la CLI de Devprime.
  • Inicie los contenedores desde docker (MongoDB, RabbitMQ y Redis)
  • Cree la cola orderevents y paymentevents en RabbitMQ.
  • Crea un nuevo microservicio siguiendo el ejemplo de “payment” presentado.
  • Este microservicio escuchará la cola/tema “orderevents”

Iniciando la configuración de idempotencia

Ajuste de la idempotencia en el interruptor “Devprime_App”
Cambie la configuración de Idempotencia a “Habilitado” a “verdadero” y el “Flujo” a “frontend”. Cambiamos la “clave” por “mi-clave-de-idempotencia”. Con esta configuración, la API requerirá la clave de idempotencia en Headar.
code .\src\app\appsettings.json

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "auto"
    }

Incluir una segunda persistencia en la tecla “Devprime_State”
En este ejemplo, usaremos un Redis local con una contraseña predeterminada
code .\src\app\appsettings.json

1
2
3
4
5
6
7
8
9
{
  "enable": "true",
  "alias": "State2",
  "dbtype": "redis",
  "connection": "127.0.0.1:6379,password=LltF8Nx*yo",
  "timeout": "5",
  "retry": "2",
  "durationofbreak": "45"
}

Para este escenario, agregaremos el evento directamente a RabbitMQ para simular un evento duplicado.

Ejecute el microservicio dp-stream e inicie sesión en el portal de Rabbitmq en
http://localhost:15672 con el usuario invitado/invitado. Localice el menú Colas > orderevents y localice el elemento “Publicar mensaje”

Localice el campo de carga útil y pegue el json a continuación y luego vaya a “Publicar mensaje” para poner en cola ese evento.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
   "Headers":{
      "uber-trace-id":"126e838875d34dd3:5644a477603d0a55:bc20635b06c79bc2:1"
   },
   "Id":"36dbd9d0-7b8b-41fb-bdaf-2ff6a0672bd4",
   "CorrelationId":"18c71a48-0253-4247-9c8b-d576c4f8394e",
   "AppId":"21cef89c-229e-4291-8d6a-1ccf5c401484",
   "AppName":"ms-idempotency",
   "TenantID":"",
   "TenantUserID":"",
   "Version":1,
   "Name":"OrderCreated",
   "CreationDate":"2022-03-13T11:14:01.0284863-03:00",
   "Payload":{
      "ID":"ccfc8248-2ab5-4423-92fc-b16c4555add2",
      "CustomerName":"Bill",
      "CustomerTaxID":"string",
      "Total":100
   }
}

El microservicio está escuchando esta cola y reaccionará al evento y lo procesará correctamente.

Flujo de idempotencia de las capacidades de Devprime

Ahora vuelve a RabbitMQ y vuelve a enviar el mismo evento y notarás que cuando llega al microservicio se rechaza automáticamente.

Flujo de idempotencia de las capacidades de Devprime

Para repetir la prueba, cambie un valor de la carga json colocando otro GUID en el identificador, por ejemplo.

Inicio de la idempotencia manual

Devprime le permite ingresar manualmente un método específico que admitirá idempotencia. El primer paso es cambiar la configuración principal y luego ir directamente al método para agregar la configuración.

Cambiar la tecla “Acción” a “Manual”

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "manual"
    }

En el modo manual, al realizar una prueba enviando eventos duplicados, notará que serán aceptados. Debe visitar cada método deseado y agregar “Dp.Idempotency.Enable = true;” para habilitar el control de idempotencia.

** Modificando la transmisión para “idempotencia” **
Abra el centro de eventos y busque la suscripción del evento deseado, que en este contexto es “OrderCreated” y agregue “Dp.Idempotency.Enable = true;”.
code src\Adapters\Stream\EventStream.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
namespace Devprime.Stream;
public class EventStream : EventStreamBase, IEventStream
{
    public override void StreamEvents()
    {
        Subscribe<IPaymentService>("Stream1", "OrderCreated", (payload, paymentService, Dp) =>
        {
            Dp.Idempotency.Enable = true;

            var dto = System.Text.Json.JsonSerializer.Deserialize<OrderCreatedEventDTO>(payload);
            var command = new Payment()
            {
                CustomerName = dto.CustomerName,
                OrderID = dto.OrderID,
                Value = dto.Value
            };
            paymentService.Add(command);
        });
    }
}

Cuando intente volver a ejecutar eventos duplicados, notará que vuelve a funcionar.

Más artículos sobre idempotencia

Idempotencia en microservicios y APIs REST
Creación de microservicios idempotentes basados en eventos

Última modificación January 10, 2024 (967dcac3)