2
votes

I understand that in vert.x default Verticle will run in same event loop every time we don't need to write thread-safety in our handler.

For example if I'm having a Verticle running HttpServer -

public class HttpServerVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
    vertx.createHttpServer().requestHandler(req -> {
        req.response().putHeader("content-type", "text/html").end(" 
    <html><body><h1>Hello from vert.x!</h1></body></html>");
    }).listen(8080);
}

}

It's guaranteed that at no point in time, my request handler will be called twice (for 2 different requests) on 2 event loops. Therefore I don't have to take care of thread safety in my request handler.

Now if I'm running multiple instances of my HttpServer verticle -

DeploymentOptions deploymentOptions = new 
        DeploymentOptions().setWorker(false).setInstances(10);

vertx.deployVerticle("com.....HttpServerVerticle", deploymentOptions);

Do I need to take care of thread safety? It's possible that multiple request handler (max = 10) will be running in parallel?

2

2 Answers

5
votes

In this case what you get is 10 verticles, and HTTP requests will be dispatched in a round-robin fashion among these 10 verticles. Each verticle will be assigned to an event-loop, you keep the same thread-safety guarantees.

0
votes

From https://vertx.io/docs/4.2.0/vertx-core/java/#_specifying_number_of_verticle_instances:

When deploying a verticle using a verticle name, you can specify the number of verticle instances that you want to deploy. This is useful for scaling easily across multiple cores. For example you might have a web-server verticle to deploy and multiple cores on your machine, so you want to deploy multiple instances to utilise all the cores.

I confirmed this through experiments: For multi instance deployment of a verticle, the deployment ID of all instances is the same. All instances are indeed thread safe.

DEMO code:

public class Server extends AbstractVerticle {

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

  private int counter = 0;

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    vertx.createHttpServer().requestHandler(request -> {
      LOGGER.info("Request #{} from {}, verticleId: {}, hashcode: {}", ++counter, request.remoteAddress().host(), vertx.getOrCreateContext().deploymentID(), this.hashCode());
      request.response().end("Hello!");
    }).listen(8090).onComplete(server -> {
      if (server.succeeded()){
        startPromise.complete();
      }else {
        startPromise.fail(server.cause());
      }
    });
  }

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(Server.class, new DeploymentOptions().setInstances(4));
  }
}

public class Client {

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    WebClient webClient = WebClient.create(vertx);
    for (int i = 0; i < 100; i++) {
      webClient.getAbs("http://localhost:8090").send().onSuccess(response -> System.out.println(response.bodyAsString())).onFailure(Throwable::printStackTrace);
    }
  }
}

However, this does not mean that you can deploy multiple instances of any verticle. Because multi instance deployment means that multiple verticle objects are generated. If your verticle is stateful, the states of multiple instance objects are independent of each other. In other words, if you need to maintain a consistent and shared state(like counter in DEMO) in verticle during multi instance deployment, you can't multi instance deployment. Alternatively, you can use the shared data provided by vertx to solve this problem.