Volver al inicio

Orquestación descentralizada en RabbitMQ

El artículo describe una biblioteca para orquestación descentralizada en RabbitMQ como reemplazo de Apache Camel. En detalle: entidades, modos de ejecución, migración. Ventajas: recuperación de estado, escalado.

Orquestación RabbitMQ: abandonando Camel en microservicios
Advertisement 728x90

Orquestación de Procesos Descentralizada con RabbitMQ: Una Alternativa a Apache Camel

Un sistema para procesar grandes volúmenes de datos desde archivos FTP y flujos de Kafka/RabbitMQ utiliza una arquitectura de microservicios con más de 40 servicios. Anteriormente, las cadenas de procesamiento se implementaban con Apache Camel mediante DSL en Java con llamadas REST desde un servicio central. Los problemas incluían pérdida de estado durante reinicios, limitaciones de escalabilidad debido a flujos paralelos y riesgos durante las implementaciones.

Una nueva biblioteca de RabbitMQ con colas de quórum permite una gestión descentralizada. El estado se conserva en el broker, y los procesos se reanudan automáticamente. El servicio de inicialización escala horizontalmente.

Entidades Principales de la Biblioteca

La biblioteca incluye clases e interfaces para pasos, rutas y ejecutores:

Google AdInline article slot
  • RouteStepInfo: Identifica un paso en una ruta.
public class RouteStepInfo {
    private final String routeName;
    private final String stepId;

    public RouteStepInfo(String routeName, String stepId) {
        this.routeName = routeName;
        this.stepId = stepId;
    }
}
  • StepExecutor: Interfaz para ejecución asíncrona/síncrona/desacoplada.
public interface StepExecutor {
    String getStepName();
    void runAsync(RouteStepInfo routeStepInfo, Long objectId);
    void runSync(RouteStepInfo routeStepInfo, Long objectId);
    void runDetached(RouteStepInfo routeStepInfo, Long objectId);
    void appendListener(StepExecutionFinishedListener listener);
}
  • StepExecutionFinishedListener: Callback para la finalización de un paso.
public interface StepExecutionFinishedListener {
    void onStepExecutionFinished(RouteStepInfo routeStepInfo, Long objectId);
}
  • RouteStep: Paso con modos ASYNC, SYNC, DETACHED.
public interface RouteStep {
    String getRouteName();
    String getStepId();
    String getStepName();
    ExecutionMode getExecutionMode();
    void run(Long objectId);
    void appendListener(StepExecutionFinishedListener listener);

    enum ExecutionMode {
        ASYNC,
        SYNC,
        DETACHED
    }
}
  • ExecutionRoute: Ruta como una lista de pasos con índices.
@Slf4j
public class ExecutionRoute {
    @Getter
    private final String routeName;
    private final List<RouteStep> routeSteps;
    private final Map<String, Integer> stepsIndex;

    public ExecutionRoute(String routeName, List<RouteStep> routeSteps) {
        this.routeName = routeName;
        this.routeSteps = routeSteps;
        this.stepsIndex = new HashMap<>();
        for (int i = 0; i < routeSteps.size(); i++) {
            stepsIndex.put(routeSteps.get(i).getStepId(), i);
        }
    }
}

Además: RoutesConfigBuilder para configuración, RouterConfigProvider para rutas, ProcessRouter como listener y ejecutor.

Modos de Ejecución de Pasos

La biblioteca admite tres modos:

  • ASYNC: Lanzamiento secuencial en segundo plano, pasando al siguiente paso tras la finalización.
  • SYNC: Llamada bloqueante, que retorna después de toda la cadena.
  • DETACHED: Lanzamiento sin esperar, avanzando inmediatamente.

Las combinaciones permiten ramificación y paralelismo:

Google AdInline article slot
  • Ruta 1: Pasos SYNC 1→2→3.
  • Ruta 2: Pasos ASYNC 1→2→3, retornando inmediatamente.
  • Ruta 3: ASYNC con paso DETACHED 2.
  • Ruta 5: Subruta paralela Ruta 4.

Implementación y Migración

Las pruebas de carga confirmaron la funcionalidad. La migración es por fases: reemplazando partes de Camel con conmutación A/B. Las dependencias existentes se mantienen para revertir.

Puntos clave:

  • El estado en RabbitMQ garantiza la reanudación tras reinicios.
  • Escalabilidad horizontal del inicializador.
  • Configuración transparente mediante builder.
  • Soporte para ramificación y paralelismo sin un servicio centralizado.

Este enfoque es adecuado para sistemas con altos requisitos de fiabilidad y escalabilidad.

Google AdInline article slot

— Editorial Team

Advertisement 728x90

Leer después