Reputation: 13471
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
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