Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vert.x multi-thread web-socket

Tags:

java

vert.x

I have simple vert.x app:

public class Main {
public static void main(String[] args) {
    Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40));
    Router router = Router.router(vertx);
    long main_pid = Thread.currentThread().getId();
    Handler<ServerWebSocket> wsHandler = serverWebSocket -> {
        if(!serverWebSocket.path().equalsIgnoreCase("/ws")){
            serverWebSocket.reject();
        } else {
            long socket_pid = Thread.currentThread().getId();
            serverWebSocket.handler(buffer -> {
                String str = buffer.getString(0, buffer.length());
                long handler_pid = Thread.currentThread().getId();
                log.info("Got ws msg: " + str);
                String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                serverWebSocket.writeFinalTextFrame(res);
            });
        }
    };
    vertx
        .createHttpServer()
        .websocketHandler(wsHandler)
        .listen(8080);
}
}

When I connect this server with multiple clients I see that it works in one thread. But I want to handle each client connection parallelly. How I should change this code to do it?

like image 581
Ivan Zelenskyy Avatar asked Sep 04 '26 12:09

Ivan Zelenskyy


2 Answers

This:

new VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40)

looks like you're trying to create your own HTTP connection pool, which is likely not what you really want.

The idea of Vert.x and other non-blocking event-loop based frameworks, is that we don't attempt the 1 thread -> 1 connection affinity, rather, when a request, currently being served by the event loop thread is waiting for IO - EG the response from a DB - that event-loop thread is freed to service another connection. This then allows a single event loop thread to service multiple connections in a concurrent-like fashion.

If you want to fully utilise all core on your machine, and you're only going to be running a single verticle, then set the number of instances to the number of cores when your deploy your verticle.

IE

Vertx.vertx().deployVerticle("MyVerticle", new DeploymentOptions().setInstances(Runtime.getRuntime().availableProcessors()));
like image 62
Will Avatar answered Sep 06 '26 01:09

Will


Vert.x is a reactive framework, which means that it uses a single thread model to handle all your application load. This model is known to scale better than the threaded model.

The key point to know is that all code you put in a handler must never block (like your Thread.sleep) since it will block the main thread. If you have blocking code (say for example a JDBC call) you should wrap your blocking code in a executingBlocking handler, e.g.:

serverWebSocket.handler(buffer -> {
  String str = buffer.getString(0, buffer.length());
  long handler_pid = Thread.currentThread().getId();
  log.info("Got ws msg: " + str);
  String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid);
  vertx.executeBlocking(future -> {
    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    serverWebSocket.writeFinalTextFrame(res);
    future.complete();
  });
});

Now all the blocking code will be run on a thread from the thread pool that you can configure as already shown in other replies.

If you would like to avoid writing all these execute blocking handlers and you know that you need to do several blocking calls then you should consider using a worker verticle, since these will scale at the event bus level.

A final note for multi threading is that if you use multiple threads your server will not be as efficient as a single thread, for example it won't be able to handle 10 million websockets since 10 million threads event on a modern machine (we're in 2016) will bring your OS scheduler to its knees.

like image 26
Paulo Lopes Avatar answered Sep 06 '26 03:09

Paulo Lopes