Saltar a contenido

Relación de Entidades entre Microservicios

mmd

Introducción

En el contexto de la ingeniería de software y la arquitectura de microservicios, la forma en que las entidades se relacionan entre sí es crucial para garantizar la integridad y la eficiencia del sistema. Este documento aborda cómo gestionar las relaciones entre microservicios que utilizan bases de datos separadas, además de discutir el uso de una única base de datos para múltiples microservicios y la replicación de datos a través de eventos de dominio.

1. Relación de Entidades entre Microservicios

1.1. Identificación por ID Externo

En un escenario donde los microservicios tienen sus propias bases de datos, uno de los desafíos es la necesidad de relacionar entidades que pertenecen a servicios distintos. La práctica recomendada es utilizar IDs externos. Esto significa que, en lugar de mantener una referencia directa a otra entidad (por ejemplo, una llave foránea), un microservicio almacenará el ID de la entidad de otro microservicio.

Ejemplo:

  • Servicio A: Gestiona Usuarios
  • Servicio B: Gestiona Órdenes

En la base de datos del Servicio B, en lugar de tener una llave foránea que haga referencia directa a un Usuario del Servicio A, el Servicio B almacena solo el userId del Usuario. Esto crea un desacoplamiento entre los servicios y permite que cada uno sea escalable e independiente.

1.2. Ventajas

  • Desacoplamiento: Los microservicios pueden ser modificados o escalados de forma independiente.
  • Resiliencia: Si un microservicio está fuera de servicio, el otro aún puede funcionar, siempre que tenga la lógica para manejar la ausencia de datos.
  • Facilidad de mantenimiento: Los cambios en un microservicio no impactan directamente al otro.

2. Microservicios con la Misma Base de Datos

2.1. Uso Compartido de una Base de Datos

En algunos casos, puede ser deseable que múltiples microservicios accedan a la misma base de datos. Esto se puede hacer cuando los microservicios están fuertemente acoplados o cuando hay un alto costo de mantenimiento al dividir la base de datos.

Remapeo del Dominio como Subdominio

Cuando dos o más microservicios usan la misma base de datos, se puede considerar la implementación de un subdominio. El subdominio es una parte de la lógica de negocio que se agrupa según un contexto específico. Por ejemplo:

  • Servicio A puede ser responsable de gestionar Usuarios
  • Servicio B puede ser responsable de gestionar Autenticación

Ambos servicios acceden a la misma base de datos, pero cada uno se enfoca en un aspecto diferente del dominio.

2.2. Ventajas

  • Consistencia de datos: Fácil gestión de datos que necesitan ser accedidos por múltiples servicios.
  • Simplicidad: Reduce la complejidad de la arquitectura al evitar la necesidad de comunicación entre servicios para operaciones simples.

3. Replicación de Datos en Subdominios

3.1. Mapeo de Entidades en Subdominios

Cuando tenemos la misma entidad mapeada en diferentes subdominios, la replicación de datos es una cuestión importante. Para garantizar que la información sea consistente entre los subdominios, podemos utilizar el concepto de eventos de dominio.

Ejemplo de Replicación:

  • Servicio A: Gestiona Usuarios
  • Servicio B: Gestiona Notificaciones, que también necesita información sobre Usuarios.

Cuando un Usuario es creado o actualizado en el Servicio A, este puede publicar un evento de dominio, como UserCreated o UserUpdated. El Servicio B puede escuchar estos eventos y actualizar su propia base de datos con la información necesaria.

3.2. Ventajas de la Replicación vía Eventos de Dominio

  • Desacoplamiento: Los servicios no necesitan conocerse entre sí; solo escuchan eventos.
  • Escalabilidad: Cada servicio puede escalar de manera independiente.
  • Consistencia eventual: Los datos se mantienen actualizados sin necesidad de llamadas directas entre servicios.

Ejemplos

Escenario

  • Colaborador: Representa un usuario en el sistema.
  • Solicitud de Feedback: Una petición hecha por un colaborador para recibir feedback de otro colaborador.
  • Servicio A: Gestiona los colaboradores.
  • Servicio B: Gestiona las solicitudes de feedback.

1. Relación de Entidades entre Microservicios

1.1. Identificación por ID Externo

Entidad Colaborador (Servicio A)

@Entity
public class Colaborador {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nome;
    private String email;

    // Getters y Setters
}

Entidad Solicitud de Feedback (Servicio B)

@Entity
public class RequisicaoFeedback {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long colaboradorId; // ID del colaborador que hace la solicitud
    private Long colaboradorFeedbackId; // ID del colaborador que recibirá el feedback
    private String mensagem;

    // Getters y Setters
}

1.2. Ejemplo de Creación de Solicitud de Feedback

@RestController
@RequestMapping("/feedback")
public class RequisicaoFeedbackController {

    @Autowired
    private RequisicaoFeedbackService feedbackService;

    @PostMapping("/request")
    public ResponseEntity<RequisicaoFeedback> solicitarFeedback(@RequestBody RequisicaoFeedbackDTO dto) {
        RequisicaoFeedback feedback = feedbackService.solicitarFeedback(dto);
        return ResponseEntity.status(HttpStatus.CREATED).body(feedback);
    }
}

DTO para Solicitud de Feedback

public class RequisicaoFeedbackDTO {
    private Long colaboradorId;
    private Long colaboradorFeedbackId;
    private String mensagem;

    // Getters y Setters
}

2. Microservicios con la Misma Base de Datos

2.1. Uso Compartido de una Base de Datos

Entidad Colaborador (Servicio A y B)

@Entity
public class Colaborador {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nome;
    private String email;

    // Getters y Setters
}

Entidad Solicitud de Feedback (Servicio B)

@Entity
public class RequisicaoFeedback {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long colaboradorId; // ID del colaborador que hace la solicitud
    private Long colaboradorFeedbackId; // ID del colaborador que recibirá el feedback
    private String mensagem;

    // Getters y Setters
}

2.2. Ejemplo de Creación de Solicitud de Feedback

@RestController
@RequestMapping("/feedback")
public class RequisicaoFeedbackController {

    @Autowired
    private RequisicaoFeedbackService feedbackService;

    @PostMapping("/request")
    public ResponseEntity<RequisicaoFeedback> solicitarFeedback(@RequestBody RequisicaoFeedbackDTO dto) {
        RequisicaoFeedback feedback = feedbackService.solicitarFeedback(dto);
        return ResponseEntity.status(HttpStatus.CREATED).body(feedback);
    }
}

En este escenario, ambos servicios (Servicio A y Servicio B) acceden a la misma base de datos. Los colaboradores se gestionan en la misma base de datos, pero la lógica de feedback está aislada en el Servicio B.


3. Replicación de Datos en Subdominios

3.1. Mapeo de Entidades en Subdominios

Publicando Evento de Dominio al Crear Solicitud de Feedback

Cuando un colaborador solicita feedback, se publica un evento para informar a otros servicios.

public class RequisicaoFeedbackService {

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public RequisicaoFeedback solicitarFeedback(RequisicaoFeedbackDTO dto) {
        RequisicaoFeedback feedback = new RequisicaoFeedback();
        feedback.setColaboradorId(dto.getColaboradorId());
        feedback.setColaboradorFeedbackId(dto.getColaboradorFeedbackId());
        feedback.setMensagem(dto.getMensagem());

        // Guardar la solicitud en la base de datos
        // ...

        // Publicar evento
        eventPublisher.publishEvent(new FeedbackRequestedEvent(feedback));

        return feedback;
    }
}

Evento de Dominio

public class FeedbackRequestedEvent {
    private final RequisicaoFeedback feedback;

    public FeedbackRequestedEvent(RequisicaoFeedback feedback) {
        this.feedback = feedback;
    }

    public RequisicaoFeedback getFeedback() {
        return feedback;
    }
}

3.2. Consumiendo el Evento de Dominio

En el Servicio B, se puede implementar un listener para manejar el evento y actualizar la base de datos.

@Component
public class FeedbackRequestedListener {

    @Autowired
    private ColaboradorRepository colaboradorRepository;

    @EventListener
    public void handleFeedbackRequested(FeedbackRequestedEvent event) {
        RequisicaoFeedback feedback = event.getFeedback();
        // Lógica para actualizar o almacenar datos relacionados con el feedback
        // ...
    }
}