3

For the last week I read documentation about vertx. What i don't get it's how vertx handlers are work? For example

public class Client extends AbstractVerticle{

    @Override
    public void start() throws Exception {
       final HttpClient httpClient = this.vertx.createHttpClient();
       this.vertx.setPeriodic(1000, handler->{
           httpClient.getNow(8080, "localhost", "/", responseHandler -> {
                System.out.println("response");
            });
       });
    }

}

And server is:

public class JdbcVertx extends AbstractVerticle{

    @Override
    public void start() throws Exception {
        JDBCClient client = JDBCClient.createNonShared(this.vertx, new JsonObject()
                                .put("url", "jdbc:postgresql://localhost:5432/test")
                                .put("user", "user")
                                .put("password", "password")
                                .put("driver_class", "org.postgresql.Driver")
                                .put("max_pool_size", 30));
        this.vertx.createHttpServer()
                .requestHandler(r -> {
                    client.getConnection(handler -> {                     
                        final SQLConnection connection = handler.result();
                        connection.execute(execute(), hndlr -> {
                                connection.close(closehndlr -> {                                 
                                        r.response().putHeader("content-type", "text/html").end("Response");
                                });                                   
                        });
                    });
                }).listen(8080);
    }

    private String execute(){
            return "insert into rubish (name) values ('test')";      
    }
}

(P.S i know that i firstly should to check if handler is succeded and then make some action but i remove this checking to simplify code and also from official docs if there is no any response during 30 sec there will be an exception in handler)

From the code above, client send request each second and doesn't wait for response , but it has a handler that will be executed when response was comming.

'JdbcVertx' listen on port 8080 , get request, make insertion to db with sleep for example 3 s (i put 1_000_000 rows to db and create index to slow down insertion time) and then send response, therefore each request is non blocking.

As i know , vertx has only one thread named EventLoop event loop from jdbcVertx get reqests but doesn't return response immediately , instead it put a handler that will be executed when db insertion was succeed. How event loop know when IO action is done. I think that it use somthing like this

if(Thread.currentThread().getState != 'blocked' && sec != 30){
    this.object.getHandler().execute();
} else if(sec == 30){
 Thread.currentThread.inerrupt();
  } else{
    sec++;
  }

But we have only one thread, and when we have blocking call it doesn't has a thread, only handler.

The problem is , how event loop know when blocking operation is ended and it's time to execute handler

Almas Abdrazak
  • 3,209
  • 5
  • 36
  • 80

2 Answers2

4

But we have only one thread, and when we have blocking call it doesn't has a thread, only handler. How it work , and why do we need to use Worker Verticle if we can use handlers instead?

The handlers are just actions triggered upon receipt of an eventbus message or an http call. They are not designed to handle scalability for you. If you only use handlers and if your actions starts to take a long time or if you have any increase in the number of requests, you will block the eventloop of your verticle and will have a lot of Thread xxxx has been blocked warns.

To answer on how handler works and why the event loop doesn't wait the end of a handler to start another, according to this : https://vertx.io/docs/vertx-core/java/#_reactor_and_multi_reactor

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.

This means a single Vertx process can scale across your server, unlike Node.js.

We call this pattern the Multi-Reactor Pattern to distinguish it from the single threaded reactor pattern.

But that's not enough to handle all scalability and thread blocking problematics for you in my opinion, you schould read this too : https://vertx.io/docs/vertx-core/java/#golden_rule

There are many ways to design verticles but you have to stay as non-blocking as possible. In my opinion, using vert.x with a traditional blocking approach (like blocking restfull endpoints for example) is not relevant.

Personally I'd design my verticles as follows :

  • verticle A : which expose a restfull endpoint and take a callback url (whatever the action GET/POST/PUT/PATCH/DELETE). The verticle always respond a 202 Accepted immediatly without result and send a message in the eventbus to a verticle B.

  • verticle B : get the message, do the action (eventually invoke other verticles asynchronously with the eventbus and waiting the replies) and reply invoking the callback url.

I'd avoid to use worker verticle or the executeBlocking method or even creating a pool of thread. I'd privilege multiplying the instances of my verticles B (in seperate pids) that listen to the same eventbus cluster (and eventually verticle A with a http reverse proxy). We can even imagine having a variable number of verticle B instances (in seperate pids) depending on the number of requests in real time.

P.S : sometimes I use a more powerfull message broker tool like Apache Kafka instead of the native eventbus (when I need to respect a sort of message, or when I need to replay some messages).

Community
  • 1
  • 1
Idriss Neumann
  • 3,760
  • 2
  • 23
  • 32
  • Thank but how it relate to my question about handlers? – Almas Abdrazak Apr 10 '18 at 07:42
  • @AlmasAbdrazak I think using only http handlers is not enough to handle scalability and thread blocking problematic, that's it. And I answer your question about `why do we need worker verticle`. I've updated my answer to clarify a little bit more ;) – Idriss Neumann Apr 10 '18 at 07:53
  • It's just an example , i want to show that event loop doesn't wait each request to be done , instead it use handlers, how do they work, this is the question, not how to design my app with vertx – Almas Abdrazak Apr 10 '18 at 07:58
  • More over, using send method of event bus you can initialize handler for reply action – Almas Abdrazak Apr 10 '18 at 07:59
  • @AlmasAbdrazak I've updated my answer to give more give more explanations about the vert.x multi-reactor pattern (your question was not very clear and you seems to ask why you should do other stuffs like using vert.x worker instead of using only http handlers and I've answered to that). To summarize, I really think you need to not counting only on handlers to handle scalability and thread blocking problematics as you seems to say in your first message. That's the purpose of my answer! And I think that's relevant ;) – Idriss Neumann Apr 10 '18 at 08:34
0

Answering the question:

how event loop know when blocking operation is ended and it's time to execute handler?

According to the non-blocking model, the event-loop upon the call

connection.execute( execute(), hndlr )

spawns a new thread, executes your blocking piece of code and upon it's completion (something like Thread.join()) invokes the hndlr callback in the event-loop thread. Thus the main loop doesn't get blocked although the blocking code can be executed.

injecteer
  • 20,038
  • 4
  • 45
  • 89
  • Thank you, accroding to your answer 'spawns a new thread' , it mean that all blocking operations spawn a new thread that will wait until operation will be done, and then event loop thread check the state of newly spawned thread after each iteration,Am i right? – Almas Abdrazak Apr 10 '18 at 08:35
  • roughly yes. Event-loop doesn't care about the threads it spawns, it just receives the "completion signals" from them to execute the handlers. – injecteer Apr 10 '18 at 08:41
  • Thank you a lot, but i don't see something similar in official docs, i want to know how many threads event loop can create, does these threads are coming from pool or not, where i can find such information? – Almas Abdrazak Apr 10 '18 at 08:51
  • @AlmasAbdrazak you just could read the multireactor section of the official documentation (as I said before) ;) https://vertx.io/docs/vertx-core/java/#_reactor_and_multi_reactor – Idriss Neumann Apr 10 '18 at 08:54
  • @injecteer I think it's better to present the golden rule before presenting how to circumvent it (I'm talking about the `executeBlocking` method which is useless with a good non-blocking design). – Idriss Neumann Apr 10 '18 at 09:01