What are Vert.x verticle "instances", and what is their relation to threads?

2.5k views Asked by At

When deploying a verticle in a Vert.x application, the documentation appears to be painstakingly unclear about what a verticle "instance" actually is, and how it relates to threads and thread pools. In fact, it's rather unclear about anything relating to the actual threading model...

From the documentation;

Vert.x works differently here. Instead of a single event loop, each Vertx instance maintains several event loops. By default we choose the number based on the number of available cores on the machine, but this can be overridden.

Also from the documentation;

The number of instances of the verticle to instantiate in the Vert.x server. Each verticle instance is strictly single threaded so to scale your application across available cores you might want to deploy more than one instance. If omitted a single instance will be deployed. We'll talk more about scaling later on in this user manual.

Let's assume I want to deploy a simple REST API that is written as a single Verticle, and I would like to have it scale efficiently across available CPU cores. What should I do?

  • Do I deploy one instance of the verticle per CPU core?
  • Do I deploy a single instance of the verticle, as according to at least one part of documentation a single verticle instance will alread maintain several event loops (as I assume 1 event loop = 1 thread)?
  • If I deploy 4 instances of a verticle, what threads and/or thread pools will actually be created/used?
2

There are 2 answers

0
Evan On

The Vert.x documentation has this paragraph:

Verticles are chunks of code that get deployed and run by Vert.x. A Vert.x instance maintains N event loop threads (where N by default is core*2) by default.

If you wanted to utilize all of your cores, you would deploy 2 verticles per core.

Standard verticles are assigned an event loop thread when they are created and the start method is called with that event loop. When you call any other methods that takes a handler on a core API from an event loop then Vert.x will guarantee that those handlers, when called, will be executed on the same event loop.

This means we can guarantee that all the code in your verticle instance is always executed on the same event loop (as long as you don’t create your own threads and call it!).

When you deploy a verticle, it gets assigned an event loop thread. That means that the execution of any code written inside a verticle will always be executed on the same event loop that the verticle was deployed on. This allows you to scale nicely across the available threads.

0
Tomek Samcik On

You are right about the clarity of documentation, I posted a related question here

Here's what documentation says -

Vert.x works differently here. Instead of a single event loop, each Vertx instance maintains several event loops. By default we choose the number based on the number of available cores on the machine, but this can be overridden.

Even though a Vertx instance maintains multiple event loops, any particular handler will never be executed concurrently, and in most cases (with the exception of worker verticles) will always be called using the exact same event loop.

And here's how I get it -

  • Each Vert.x instance will run a number of event loops that equals the number of available cores.

  • On a single Vert.x instance you can deploy multiple Veriticles that includes deploying multiple instances of the same Verticle that can run concurrently on different threads.

  • Although documentation says that a particular handler only ever gets executed on a single event loop, I think what they mean by a "particular handler" is an object instance of a given Verticle, which doesn't mean that another object instance of this same Verticle can't run on another event loop on the same Vert.x.

  • Even if this same Verticle runs concurrently on many event loops on the same Vert.x, instances are not sharing any state so are thread-safe.

If you deploy 4 instances of a Verticle on Vert.x running on a 2-cpu machine you will end up with 2 event loops running 2 instances each and each instance will host its own state if I get it right.