paul
paul

Reputation: 13471

Vertx run multiple event loops

I have a situation where I need to scale up vertically, so I end up with a Virtual machine with 20 cores and 5GB.

The problem is that when I make a very big load of data, I cannot see the CPU used more than just one core. And what I would expect is see running the 20 cores in parallel.

I've tried to create my Vertx with a Worker of 100 threads.

VertxOptions options = new VertxOptions().setWorkerPoolSize(100);
this.asyncFlowVertx = Vertx.vertx(options);

But still my service is not using all cores.

What else can I configure to allow my server run more request in parallel?

Having this code how can I deploy multiple Verticle without bindaddress exceptions

@Override
public void start(Promise<Void> startPromise) {
    logger.info("Preparing Async Flow Http proxy server....");
    Router router = Router.router(asyncFlowVertx);
    router.route().handler(BodyHandler.create());
    router.route(GET, "/ready").respond(ctx -> Future.succeededFuture());
    router.route(GET, "/health").respond(ctx -> Future.succeededFuture());
    router.route(POST, "/request").respond(this::processRequest);
    router.route(POST, "/response").respond(this::processResponse);

    server = asyncFlowVertx.createHttpServer();
    server.requestHandler(router).listen(port, http -> {
        if (http.succeeded()) {
            logger.info("Async-flow-http-proxy running......");
            startPromise.complete();
        } else {
            startPromise.fail(http.cause());
        }
    });
}

If I try

DeploymentOptions options = new DeploymentOptions().setInstances(20);
vertx.deployVerticle("com.bla.MyVerticle", options);

I get bind address exception

SOLUTION

I manage to deploy multiple verticles, but even deploying 20, I can only see in my logs run two event loops threads

var vertx = Vertx.vertx();
Router router = Router.router(vertx);
IntStream.range(0,20).forEach(i -> {
    logger.info("Creating Vertx Verticle {}", i);
    vertx.deployVerticle(new AsyncFlowHttpProxy(router));
});

My Verticle need some dependencies in the constructor, and If I try to create multiple Verticle like this

VertxOptions options = new VertxOptions();
    options.setWorkerPoolSize(100);
    var vertx = Vertx.vertx(options);
    Router router = Router.router(vertx);
    DeploymentOptions deploymentOptions = new DeploymentOptions().setInstances(20);
    vertx.deployVerticle(new AsyncFlowHttpProxy(port, nextServicePort, nextServiceName, router), deploymentOptions);

I got this error

java.lang.IllegalArgumentException: Can't specify > 1 instances for already created verticle

Any idea why?

Regards

Upvotes: 3

Views: 863

Answers (1)

kartikone
kartikone

Reputation: 41

An instance of a verticle defaults to having an event loop pool with number of threads = 2 * number of cores on the machine. For argument's sake, let us assume that there are x physical cores with hyperthreading; this means that there are 2x virtual cores.

This does not mean that a single instance of the verticle will immediately create the maximum number of threads, that will correspondingly utilize all of the virtual cores, which with hyperthreading would cause all x physical cores to be utilized (this is managed by the OS). This would be closer to multithreading behaviour as opposed to reactive, event-driven behaviour of a framework like Vert.x.

In Vert.x, the number of threads actually created are dynamically managed by the framework. Here is a nice analysis of the same. Adherence to the design principles of Vert.x such as writing non-blocking code, utilizing worker pools would be the way to optimize performance. Specifically for number of instances, I found this that suggests starting with one instance per physical core and scaling up to test.

Here is the complete code I used to test your example, where I was able to deploy the verticle with multiple instances.

public class TestVerticle extends AbstractVerticle {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestVerticle.class);

    private static Vertx vertx;

    public static void main(String[] args) {
        VertxOptions options = new VertxOptions().setWorkerPoolSize(100);
        DeploymentOptions deploymentOptions = new DeploymentOptions().setInstances(20);
        vertx = Vertx.vertx(options);
        vertx.deployVerticle(TestVerticle.class, deploymentOptions);
    }

    @Override
    public void start(Promise<Void> startPromise) {
        LOGGER.info("Preparing Async Flow Http proxy server....");
        Router router = Router.router(vertx);
        router.route().handler(BodyHandler.create());
        router.route(GET, "/ready").respond(ctx -> Future.succeededFuture());
        router.route(GET, "/health").respond(ctx -> Future.succeededFuture());
        router.route(GET, "/request").respond(ctx -> Future.succeededFuture(new JsonObject().put("hello", "world")));

        HttpServer server = vertx.createHttpServer();
        server.requestHandler(router).listen(8080, http -> {
            if (http.succeeded()) {
                LOGGER.info("Async-flow-http-proxy running......");
                startPromise.complete();
            } else {
                startPromise.fail(http.cause());
            }
        });
    }
}

Upvotes: 2

Related Questions