vert-x3 / issues

Apache License 2.0
36 stars 7 forks source link

EventLoop strange phenomenon #544

Closed PrintTree closed 3 years ago

PrintTree commented 3 years ago

I‘m new to Vert.x,and write some code like simple example,and I find a strange phenomenon of EventLoop thread.

public final class Bootstrap {

    private static final int CORE_NUMBER;

    private static final VertxOptions VERTX_OPTIONS;
    private static final Vertx VERTX;

    private static final DeploymentOptions HTTP_SERVER_DEPLOYMENT_OPTIONS;

    static {

        CORE_NUMBER = VertxOptions.DEFAULT_EVENT_LOOP_POOL_SIZE;

        VERTX_OPTIONS = new VertxOptions();
        VERTX_OPTIONS.setEventLoopPoolSize(CORE_NUMBER);
        System.out.println(VERTX_OPTIONS.getEventLoopPoolSize());

        VERTX = Vertx.vertx(VERTX_OPTIONS);

        HTTP_SERVER_DEPLOYMENT_OPTIONS = new DeploymentOptions();
        HTTP_SERVER_DEPLOYMENT_OPTIONS.setInstances(CORE_NUMBER);
        HTTP_SERVER_DEPLOYMENT_OPTIONS.setWorkerPoolName("http-server-worker");
        HTTP_SERVER_DEPLOYMENT_OPTIONS.setWorkerPoolSize(4);
    }

    public static void main(String[] args) {

        VERTX.deployVerticle("org.x.HttpServer", HTTP_SERVER_DEPLOYMENT_OPTIONS, ar -> {
            System.out.println("???"); //this never print
        });

    }
}
public class HttpServer extends AbstractVerticle {

    @Override
    public void start(Promise<Void> startPromise) throws Exception {

        Router router = Router.router(vertx);
        String content = "I'm " + this + " thread: " + Thread.currentThread() + " router: " + router;

        router.get("/").handler(context -> {
            context.response().end(content);
        });

        vertx.createHttpServer().requestHandler(router).listen(80, ar -> {
            if(ar.succeeded()) {
                System.out.println("server start " + this);
            } else {
                ar.cause().printStackTrace();
            }
        });
    }
}

When I start application,the console print the core number as 12,and 12 server start messages printed as I expected.

12 server start org.x.HttpServer@4637a165 server start org.xHttpServer@15838c55 server start org.x.HttpServer@2c4a18da server start org.x.HttpServer@50cda176 server start org.x.HttpServer@53ea4d2e server start org.x.HttpServer@2dc648b9 server start org.x.HttpServer@4d454184 server start org.x.HttpServer@74e7f992 server start org.x.HttpServer@53f43fb6 server start org.x.HttpServer@e76b6b1 server start org.x.HttpServer@5645ce63 server start org.x.HttpServer@5219cd4c

Then I ran Java visualVM to see thread,and something strange happened,there are only 6 vert.x-enevtloop-thread ! What's even more strange is that when I ran jmeter to send concurrent requests, there are only 4 thread handle request! The other 2 are missing!And when I use postman to send request one by one,there is only one thread handle my request......

Maybe this isn't an issue,but who can tell me if I did something wrong?

PrintTree commented 3 years ago

Well,one thing I known is that my jmeter thread group has 4 thread,and there are only 4 thread handle request.When I set jmeter thread number to 6,there are 6 thread handle request! But I'm still wondering why only six event loop threads have been created?

PrintTree commented 3 years ago

From more test,I found that EventLoop thread number is determined by setEventLoopPoolSize and setInstances method.Most importantly, setting odd and even numbers makes a big difference.First I setInstances(24) and remain unchanged.Then I setEventLoopPoolSize(20),setEventLoopPoolSize(21),setEventLoopPoolSize(27).These settings create different numbers of threads 10,21,24.

PrintTree commented 3 years ago

And my Maven GAV is

    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-web</artifactId>
        <version>3.9.2</version>
    </dependency>

    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-jdbc-client</artifactId>
        <version>3.9.2</version>
    </dependency>
parit commented 3 years ago

I think you need to call startPromise.complete() in if(ar.succeeded()) { ... } block to indicate the tool-chain above that the verticle is deployed.

PrintTree commented 3 years ago

I think you need to call startPromise.complete() in if(ar.succeeded()) { ... } block to indicate the tool-chain above that the verticle is deployed.

Thanks,I call that method and then it works. But EventLoopThread problem still there. I think it has something to do with netty's thread creation mechanism,and I'm looking at netty's source code to find out why. In any case, this is very strange, because I set the size of the thread pool, but the number of threads in it is not the same as what I specified.

tsegismont commented 3 years ago

There are 4 threads handling requests because, even if you deploy 6 instances of your worker verticle, you've configured the worker pool size to 4.

I would recommend to read the intro to Vert.x for Java devs: https://vertx.io/docs/guide-for-java-devs/

Then for questions such as this one, it's better to send them to the user forum (see https://vertx.io/community) because not everyone in the community is subscribed to GH issues.

Happy hacking!

PrintTree commented 3 years ago

There are 4 threads handling requests because, even if you deploy 6 instances of your worker verticle, you've configured the worker pool size to 4.

I would recommend to read the intro to Vert.x for Java devs: https://vertx.io/docs/guide-for-java-devs/

Then for questions such as this one, it's better to send them to the user forum (see https://vertx.io/community) because not everyone in the community is subscribed to GH issues.

Happy hacking!

Unfortunately, I think the request handling is in EventLoopThread because the response show that. The response like this: I'm org.x.HttpServer@fc79dd9 thread: Thread[vert.x-eventloop-thread-12,5,main] router: RouterImpl@16806481{vertx=io.vertx.core.impl.VertxImpl@4444fe7c, state=RouterState{routes=null, orderSequence=0, errorHandlers=null, modifiedHandler=null}} It shows that the current thread is EventLoopThread,right?Did I miss something?

I've read the documentation you mentioned, but I haven't found much explanation for the threading problem.BTW,even if I set the workPoolSize to 1,the request handle thread number is also the same as jmeter thread,so this is actually a useless setup,because the HttpServer I written is called Standard Verticle?

tsegismont commented 3 years ago

Sorry for the confusion. Indeed it's not a worker verticle but a standard verticle.

So because you deploy 6 instances of the verticle, Vert.x assigns a different event loop to each of them. This is why you see 6 event loop threads handling requests even if the maximum is 12.

Then if you see only 4 of them handling requests while running JMeter, it may be because it creates 4 long lived HTTP connections. Indeed, Vert.x load balances connections between verticle instances, not requests.

PrintTree commented 3 years ago

Sorry for the confusion. Indeed it's not a worker verticle but a standard verticle.

So because you deploy 6 instances of the verticle, Vert.x assigns a different event loop to each of them. This is why you see 6 event loop threads handling requests even if the maximum is 12.

Then if you see only 4 of them handling requests while running JMeter, it may be because it creates 4 long lived HTTP connections. Indeed, Vert.x load balances connections between verticle instances, not requests.

I post a question on stackoverflow https://stackoverflow.com/questions/63466734/how-does-vertx-create-eventloop-thread Firstly,I want to know how vertx create threads(It creates the wrong number of threads).Thanks for your help!

PrintTree commented 3 years ago

I read source code and maybe find an answer: https://stackoverflow.com/questions/63466734/how-does-vertx-create-eventloop-thread/63473649 I will create a new issue.