ManagedServiceBuilder vs. EndpointServerBuilder
ManagedServiceBuilder
is in QBit admin. EndpointServerBuilder
is in QBit core.ManagedServiceBuilder
provides integration with statsD, consul, swagger.ManagedServiceBuilder
is the glue to work well in Heroku-like environments, Swagger support, StatsD support, local stats support, health end point support, health system support, admin endpoint support, etc. EndpointServerBuilder
builds a single endpoint.ManagedServiceBuilder
builds a standard microservice app with health checks, metrics, and more to provide a batteries-included microservices architecture. There is some overlap with Vertx. But the plan is to build bridges from QBit health system over to Vertx health system, and from QBit metrics, stats, KPI over to Vertx stats system. (You just have to implement an interface and delegate some method calls to vertx for both QBit health system and QBit stats system).
Read all three rounds here if you missed the first two.
If you want to use QBit without statsD, consul, health checks, admin, managed shutdown and swagger support, then you just use
EndpointServerBuilder
. If you want statsD, consul, health checks, admin, or swagger then you use QBit Spring support or theManagedServiceBuilder
. The Spring support is for another document page.ManagedServiceBuilder
allows you to inject a custom health system, a custom service discovery, a custom stats system. It is an nice integration point to delegate to Vertx services.
Let's cover this in example that is like the REST example above but uses
ManagedServiceBuilder
instead of EndpointServerBuilder
.You have a service like before
@RequestMapping("/hello")
public class MyRestService {
@RequestMapping(value = "/world", method = RequestMethod.POST)
public String hello(String body) {
return body;
}
}
Note this is a simple example. QBit can do much more than this. To get a bit of an idea, please check out: QBit microservice tutorials. And be sure to check out QBit Reactive Programming.
The verticle now uses ManagedServiceBuilder instead of EndpointServerBuilder direct
public class MyVerticle extends AbstractVerticle {
private final int port;
/** The systemManager can cleanly shut down anything started by the
* QBit ManagedServiceBuilder.
*/
private QBitSystemManager systemManager;
public MyVerticle(int port) {
this.port = port;
}
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();
systemManager = managedServiceBuilder.getSystemManager();
/*
* Create a new service endpointServer.
*/
final ServiceEndpointServer endpointServer = managedServiceBuilder
.getEndpointServerBuilder().setUri("/")
.addService(new MyRestService())
.setHttpServer(httpServer).build();
endpointServer.startServer();
/*
* Associate the router as a request handler for the vertxHttpServer.
*/
vertxHttpServer.requestHandler(router::accept).listen(port);
}catch (Exception ex) {
ex.printStackTrace();
throw new IllegalStateException(ex);
}
}
public void stop() {
if (systemManager!=null) {
systemManager.shutDown();
}
}
}
The important bits to see are that we are now using the
ManagedServiceBuilder
in the verticle start methodManagedServiceBuilder
/** Use a managed service builder. */
final ManagedServiceBuilder managedServiceBuilder =
ManagedServiceBuilder.managedServiceBuilder();
systemManager = managedServiceBuilder.getSystemManager();
And that we are now using the
EndpointServerBuilder
that is managed by theManagedServiceBuilder
(managedServiceBuilder.getEndpointServerBuilder
).ManagedServiceBuilder.getEndpointServerBuilder
/*
* Create a new service endpointServer.
*/
final ServiceEndpointServer endpointServer = managedServiceBuilder
.getEndpointServerBuilder().setUri("/")
.addService(new MyRestService())
.setHttpServer(httpServer).build();
Note that the QBit systemManager ensures that all services that QBit started will get properly shutdown.
Proper shutdown
public void stop() {
if (systemManager!=null) {
systemManager.shutDown();
}
}
This example is one of the unit tests for the admin package.
Complete example showing how to use ManagedServiceBuilder with Vertx to build microservices
package io.advantageous.qbit.vertx;
import io.advantageous.qbit.admin.ManagedServiceBuilder;
import io.advantageous.qbit.annotation.RequestMapping;
import io.advantageous.qbit.annotation.RequestMethod;
import io.advantageous.qbit.http.client.HttpClient;
import io.advantageous.qbit.http.client.HttpClientBuilder;
import io.advantageous.qbit.http.request.HttpTextResponse;
import io.advantageous.qbit.http.server.HttpServer;
import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.system.QBitSystemManager;
import io.advantageous.qbit.util.PortUtils;
import io.advantageous.qbit.vertx.http.VertxHttpServerBuilder;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
public class VertxManagedServiceBuilderIntegrationTest {
private Vertx vertx;
private TestVerticle testVerticle;
private int port;
@RequestMapping("/hello")
public static class TestRestService {
@RequestMapping(value = "/world", method = RequestMethod.POST)
public String hello(String body) {
return body;
}
}
public static class TestVerticle extends AbstractVerticle {
private final int port;
private QBitSystemManager systemManager;
public TestVerticle(int port) {
this.port = port;
}
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();
systemManager = managedServiceBuilder.getSystemManager();
/*
* Create a new service endpointServer.
*/
final ServiceEndpointServer endpointServer = managedServiceBuilder
.getEndpointServerBuilder().setUri("/")
.addService(new TestRestService())
.setHttpServer(httpServer).build();
endpointServer.startServer();
/*
* Associate the router as a request handler for the vertxHttpServer.
*/
vertxHttpServer.requestHandler(router::accept).listen(port);
}catch (Exception ex) {
ex.printStackTrace();
throw new IllegalStateException(ex);
}
}
public void stop() {
if (systemManager!=null) {
systemManager.shutDown();
}
}
}
@Before
public void setup() throws Exception{
final CountDownLatch latch = new CountDownLatch(1);
port = PortUtils.findOpenPortStartAt(9000);
testVerticle = new TestVerticle(port);
vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(5));
vertx.deployVerticle(testVerticle, res -> {
if (res.succeeded()) {
System.out.println("Deployment id is: " + res.result());
} else {
System.out.println("Deployment failed!");
res.cause().printStackTrace();
}
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
@Test
public void test() {
final HttpClient client = HttpClientBuilder.httpClientBuilder().setHost("localhost").setPort(port).buildAndStart();
final HttpTextResponse response = client.postJson("/svr/rout1/", "\"hi\"");
assertEquals(202, response.code());
assertEquals("route1", response.body());
final HttpTextResponse response2 = client.postJson("/hello/world", "\"hi\"");
assertEquals(200, response2.code());
assertEquals("\"hi\"", response2.body());
}
@After
public void tearDown() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
vertx.close(res -> {
if (res.succeeded()) {
System.out.println("Vertx is closed? " + res.result());
} else {
System.out.println("Vertx failed closing");
}
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
vertx = null;
testVerticle = null;
}
}
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
No comments:
Post a Comment