Skip to content

Wiring in Vertx and QBit to work together with health and stats

Richard Hightower edited this page Jun 23, 2016 · 2 revisions

I am basing this on the first example to mix/match QBit and Vert.x. QBit health system and stats is part of the ManagedServiceBuilder. The ManagedServiceBuilder will automatically wire in health and stats, but it also wires in the end points. We have to map the end point services exposed in QBit to Vertx and we do that with a route.

Map in service

    /* Route everything under /hello to QBit http server. */
final Route qbitRoute = router.route().path("/hello/*");


    /* Vertx HTTP Server. */
final io.vertx.core.http.HttpServer vertxHttpServer =
        this.getVertx().createHttpServer();

    /*
     * Use the VertxHttpServerBuilder which is a special builder for Vertx/Qbit integration.
     */
final HttpServer httpServer = VertxHttpServerBuilder.vertxHttpServerBuilder()
        .setRoute(qbitRoute)
        .setHttpServer(vertxHttpServer)
        .setVertx(getVertx())
        .build();

We then pass that route to our integration lib VertxHttpServerBuilder.

But as you know. This will only route built in services and health and metrics are not part of the normal service end point flow (perhaps they should have been).

First lets get the EndpointBuilder which manages wiring in the health and stats systems.

EndpointServerBuilder

final EndpointServerBuilder endpointServerBuilder = managedServiceBuilder
        .getEndpointServerBuilder().setUri("/")
        .addService(new HelloWorldService())
        .setHttpServer(httpServer);

To map in the health end point and the metrics end point (there are many ways), you could use additional routes from vertx as follows:

healthRoute

    /* Route everything under /__health to QBit health system. */
final Route healthRoute = router.route().path("/__health");

final HealthServiceAsync healthService = endpointServerBuilder.getHealthService();
healthRoute.handler(event -> healthService.ok(aBoolean -> event.response().end(aBoolean.toString())));

It is actually fairly simple. Three lines of code.

To map in built-in metrics you would do this:

statsRoute, globalStats, statsCollection

    /* Route everything under /__stats/instance to QBit stats system. */
final Route statsRoute = router.route().path("/__stats/instance");
final Route globalStats = router.route().path("/__stats");
final StatCollection statsCollection = endpointServerBuilder.getStatsCollection();
statsRoute.handler(event -> statsCollection.collect(stats -> {

    String json = JsonFactory.toJson(stats);
    event.response().end(json);
}));
globalStats.handler(event -> {
    event.response().end("{\"version\":1}");
});

Here is the full example:

package io.advantageous.qbit.example.vertx;

import io.advantageous.boon.json.JsonFactory;
import io.advantageous.qbit.admin.ManagedServiceBuilder;
import io.advantageous.qbit.http.server.HttpServer;
import io.advantageous.qbit.server.EndpointServerBuilder;
import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.service.health.HealthServiceAsync;
import io.advantageous.qbit.service.stats.StatCollection;
import io.advantageous.qbit.system.QBitSystemManager;
import io.advantageous.qbit.vertx.http.VertxHttpServerBuilder;
import io.vertx.core.*;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class HelloWorldVerticle extends AbstractVerticle {
    private final int port;

    private QBitSystemManager systemManager;

    public HelloWorldVerticle(int port) {
        this.port = port;
    }

    public static void main(final String... args) throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        final HelloWorldVerticle helloWorldVerticle = new HelloWorldVerticle(8080);
        final AtomicReference<AsyncResult> asyncResultRef = new AtomicReference<>();
        Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(5));
        vertx.deployVerticle(helloWorldVerticle, result -> {
            if (result.succeeded()) {
                System.out.println("Deployment id is: " + result.result());
                asyncResultRef.set(result);
            } else {
                System.out.println("Deployment failed!");
                result.cause().printStackTrace();
            }
            latch.countDown();
        });
        latch.await(5, TimeUnit.SECONDS);

        if (asyncResultRef.get().succeeded()) {

            System.out.println("Server started");
        }
    }

    public void start() {

        try {


                /* Route one call to a vertx handler. */
            final Router router = Router.router(vertx); //Vertx router
            router.route("/svr/rout1/").handler(routingContext -> {
                HttpServerResponse response = routingContext.response();
                response.setStatusCode(202);
                response.end("route1");
            });

                /* Route everything under /hello to QBit http server. */
            final Route qbitRoute = router.route().path("/hello/*");


                /* Vertx HTTP Server. */
            final io.vertx.core.http.HttpServer vertxHttpServer =
                    this.getVertx().createHttpServer();

                /*
                 * Use the VertxHttpServerBuilder which is a special builder for Vertx/Qbit integration.
                 */
            final HttpServer httpServer = VertxHttpServerBuilder.vertxHttpServerBuilder()
                    .setRoute(qbitRoute)
                    .setHttpServer(vertxHttpServer)
                    .setVertx(getVertx())
                    .build();


            /** Use a managed service builder. */
            final ManagedServiceBuilder managedServiceBuilder = ManagedServiceBuilder.managedServiceBuilder();



            final EndpointServerBuilder endpointServerBuilder = managedServiceBuilder
                    .getEndpointServerBuilder().setUri("/")
                    .addService(new HelloWorldService())
                    .setHttpServer(httpServer);


                /* Route everything under /__health to QBit health system. */
            final Route healthRoute = router.route().path("/__health");

            final HealthServiceAsync healthService = endpointServerBuilder.getHealthService();
            healthRoute.handler(event -> healthService.ok(aBoolean -> event.response().end(aBoolean.toString())));



                /* Route everything under /__stats/instance to QBit stats system. */
            final Route statsRoute = router.route().path("/__stats/instance");
            final Route globalStats = router.route().path("/__stats");
            final StatCollection statsCollection = endpointServerBuilder.getStatsCollection();
            statsRoute.handler(event -> statsCollection.collect(stats -> {

                String json = JsonFactory.toJson(stats);
                event.response().end(json);
            }));
            globalStats.handler(event -> {
                event.response().end("{\"version\":1}");
            });




                /*
                 * Create a new service endpointServer.
                 */
            final ServiceEndpointServer endpointServer = endpointServerBuilder.build();


            endpointServer.startServer();


            systemManager = managedServiceBuilder.getSystemManager();



                /*
                 * Associate the router as a request handler for the vertxHttpServer.
                 */
            vertxHttpServer.requestHandler(router::accept).listen(port);
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    public void stop() {

        if (systemManager != null) {
            systemManager.shutDown();
        }
    }


}


package io.advantageous.qbit.example.vertx;

import io.advantageous.qbit.annotation.RequestMapping;
import io.advantageous.qbit.annotation.RequestMethod;

@RequestMapping("/hello")
public class HelloWorldService {


    @RequestMapping(value = "/world", method = RequestMethod.POST)
    public String hello(String body) {
            return "hello " + body;
    }


    @RequestMapping(value = "/hi/", method = RequestMethod.GET)
    public String hi() {
        return "hi ";
    }

}

curl

$ curl http://localhost:8080/__stats/instance
{"MetricsKV":{"HelloWorldService":1},"MetricsMS":{},"MetricsC":{"HelloWorldService.startBatchCount":5,"HelloWorldService.receiveCount":5},"version":1}

$ curl http://localhost:8080/__stats
{"version":1}

$ curl http://localhost:8080/__health
true

Tutorials

__

Docs

Getting Started

Basics

Concepts

REST

Callbacks and Reactor

Event Bus

Advanced

Integration

QBit case studies

QBit 2 Roadmap

-- Related Projects

Kafka training, Kafka consulting, Cassandra training, Cassandra consulting, Spark training, Spark consulting

Clone this wiki locally