Skip to content

Microservicios reactivos con Vert.x

Hola a todos! En este articulo vamos a hablar sobre mi tema mas favorito – microservicios reactivos con Vert.x. Vert.x es un framework para el desarrollo de aplicaci贸n orientada sa eventos que se ejecuta en JVM. Y, que es importante, Vert.x es un “polyglot”. En este articulo usamos solamente Java, sin embargo las aplicaciones pueden ser escritas tambi茅n en Scala, JS, Python, Ruby, Kotlin, Groovy.

Qu茅 significa “microservicio”?

Microservicos es un estilo de arquitectura de software. En este caso, una applicaci贸n consta de una colecci贸n de componentes aut贸nomos y peque帽os (se llaman “microservicios”). Estos componentes son independientes entre s铆 y cada uno debe implementar una funcionalidad de negocio individual. Una arquitectura de microservicios es opuesta a la arquitectura mas tradicional de monolith. Vean en este gr谩fico:

Arquitectura monol铆tica vs. Arquitectura microservicios (Apiservice.cl)

En comparaci贸n con las aplicaciones monol铆ticas, los microservicios son m谩s f谩ciles para dise帽ar, probar, implementar y actualizar. La arquitectura usa “servicios” como componentes l贸gicos. Este enfoque tiene algunas ventajas:

  • Microservicios est谩n acoplados de forma flexible. Son peque帽os y tiene un enfoque claro. Y por eso mas comodos para dise帽ar y implementar.
  • El servicio es un c贸digo base independiente. Entonces podemos usar lenguajes de programaci贸n y herramientas que son mas adequadas para cada situaci贸n.
  • Los servicios se comunican entre s铆 mediante API. Es importante, definir el mismo API para communicar.
  • Los servicios tienen un mejor “Return on Investment”. Necesitamos un hardware mas barato para ejecutar servicos, que para ejecturar aplicaciones monolithes.

En otras palabras, esta arquitectura es un intento de desplegar servicios independentes con un contexto definido.

Y por que son reactivos?

La palabra “reactivo” significa otro concepte muy importante de arquitectura de software. Unas sistemas reactivos, en general, son m谩s flexibles, con bajo acoplamiento y escalables. Estas sistemas tienen siguientes caracteristicas (seg煤n al Manifiesto de Sistemas Reactivos):

  1. Son responsivas: unas sistemas se enfocan en proveer tiempos de respuesta r谩pidos y consistentes, estableciendo l铆mites superiores confiables para as铆 proporcionar una calidad de servicio consistente
  2. Son resilientes: unas sistemas permanecen responsivo frente a fallos
  3. Son el谩sticos: unas sistemas pueden reaccionar a cambios en la frecuencia de peticiones incrementando o reduciendo los recursos asignados para servir dichas peticiones
  4. Son orientados a mensajes: unas sistemas comunican con mensajes. El uso del intercambio de mensajes expl铆cito posibilita la gesti贸n de la carga, la elasticidad, y el control de flujo, gracias al modelado y monitorizaci贸n de las colas de mensajes en el sistema, y la aplicaci贸n de back-pressure cuando sea necesario

Empezamos con Vert.x

Vert.x es una soluci贸n obvia para implementar las conceptos antedichos. Vert.x, comparar con Java frameworks cl谩sicos, esta orientada de una arquitectura de microservicios reactivos. La realizaci贸n de esta arquitectura no es dific铆l – Vert.x Core nos propociona todos los componentes necesarios: Verticles, EventBus y messaging. Adicionalmente, a帽adimos Vert.x Web porque necesitamos Router para implementar HTTP server routing. Podemos usar Vert.x Starter para generar un nuevo proyecto:

Necesitamos creer 2 components: Endpoint y Service. Estan conectado con Event Bus que puede transmitir mensajes en una manera reactiva. Este arquitectura de software se llama Endpoint-Service-Repository.

Endpoint

Endpoint es un componente que conecta una aplicaci贸n con el otro mundo 馃檪 Normalmente, consiste en Router y AuthManager para asegurar unas rutas (pero no concentramos en una seguridad en este articulo).

private EventBus bus;
private AuthProvider authProvider;
@Override
public void start(Future<Void> startFuture) throws Exception {
    super.start(startFuture);
    Future<Void> initSteps = initAuthProvider().compose(s->initServer());
    initSteps.setHandler(startFuture.completer());
}
private Future<Void> initServer(){
    Future<Void> future = Future.future();
    //inicializamos un serveridor y un router
    HttpServer server = vertx.createHttpServer();
    Router router = Router.router(vertx);
    //obtenemos una referencia de EventBus
    this.bus = vertx.eventBus();
    //assignamos hanlderers en rutas
    router.get("/chat/:id").handler(this::getChats);
    //assignamos un serveridor
    server.requestHandler(router).listen(4567, res->{
        if (res.succeeded()){
            System.out.println("Created a server on port 4567");
        } else {
            System.out.println(res.cause().getLocalizedMessage());
            future.fail(res.cause());
        }
    });
    return future;
}


private void getChats(RoutingContext ctx){
    String chatId = ctx.pathParam("id");
    JsonObject request = new JsonObject();
    request.put("chatId", chatId);
    //enviar request a consumidor
    bus.send("consumer.service.messages.getchat", request, res->{
        if (res.succeeded()){
           ctx.response()
.setStatusCode(200)
.end(Json.encode(res.result().body()));
        } else {
            System.out.println(res.cause().getLocalizedMessage());
            ctx.response().setStatusCode(404).end();
        }
    });
}

Este codigo hace siguientes acciones:

  1. Obtiene el Id desde un parametro de la ruta
  2. Crea un Request. B谩sicamente eso es un JsonOnject con datos, en nuestro ejemplo – userId
  3. Envia un mensaje a EventBus. Especificamos un destino (address), payload y handler (esto es opcional) para negociar con una respuesta
  4. Envia los datos al usario.

Service

El segundo componente de nuesta arquitectura se llama Service. Service se extiende un AbstractVerticle tambi茅n. En el metodo start() creamos un consumidor de mensajes con una direcci贸n consumer.service.messages.getchat:

@Override 
public void start() throws Exception { 
    super.start();
    EventBus bus = vertx.eventBus();
    bus.consumer("consumer.service.messages.getchat").handler(msg->{
        JsonObject request = JsonObject.mapFrom(msg.body());
        Chat result = chatDao.find(request.getString("chatId"));
        msg.reply(Json.mapFrom(result));
    });
 }

La conclusi贸n

En este articulo, hemos hablado sobre unos microservicios reactivos y como implementar esta arquitectura de software con Vert.x. Por supuesto, Vert.x es una soluci贸n obvia para implementar las conceptos antedichos. Vert.x, comparar con Java frameworks cl谩sicos, esta orientada de una arquitectura de microservicios reactivos.

La bibliograf铆a

  • Cecilio 脕lvarez Caules. Introducci贸n a Vertx (2016) Arquitectura Java. Leer aqui
  • Estilo de arquitectura de microservicios (2018) Microsoft. Leer aqui
  • Jose Hern谩ndez. Vert.x (2017) Leer aqui