environment : spring-boot-starter-webflux + netty embedded

code: in my rest controller, code is

    @GetMapping(path = "/flux")
    public Flux<List<User>> getAllRecord() {
        Flux<List<User>> stream = Flux.range(0, 1)
                .publishOn(s)
                .map(i -> {
                        System.out.println(Thread.currentThread().getName());
                        return userService.getAllUser();
                    }
                );
        return stream;
    }

problem: according to reactor design pattern and netty's principle, network IO need be executed on one thread associated with eventloop. but i found that when using webflux with api "publishOn(ExecutorService)", the netty method ChannelHandlerContext.write(ByteBuf) is invoked by custom thread pool, not by nio-event-loop thread.

is it reasonable? or webflux need change codes to do read/write IO using nio eventloop thread according to reactor pattern or netty's principle?

Comment From: bclozel

Is this a problem in theory only for now or do you have a concrete use case that shows this is a problem?

If the handler code intends to dispatch the processing on a different executor (probably for a good reason given the task at hand), maybe scheduling that back to the netty event loop after that is counter productive performance wise? Given that the body can be written as a stream or in batches, paying twice the cost of rescheduling work on a different executor might be a problem.

Also, I’m not sure we can reschedule that work on the IO event loop and not introduce a performance penalty for all the other cases which didn’t use the publishOn operator.

Comment From: ghost

hi @bclozel i dig into the netty source code, and found that, it will eventually use eventloop thread to IO even you invoke ctx.write(ByteBuf) at a custom thread

the source code shows at below. the netty ChannelHandlerContext write method will check if the current thread is eventloop thread, if not, it will schedule the write task to the eventloop thread which is named as executor as a variable

Spring spring webflux IO  is not executed  by  eventloop thread when using publishOn?

Comment From: bclozel

So is this a problem in theory only for now or do you have a concrete use case that shows this is a problem?

We're interested in the current behavior and how/why it's not the best choice or the expected one. It seems that this case is covered by Netty itself in AbstractChannelHandlerContext, so it doesn't seem against Netty's principle? Do you have elements showing that this has performance or functional drawbacks?

Comment From: ghost

as far as i know, netty does this for avoiding lock aquire conflicts for concurrent read/write. All read from or write to one socket handled by one eventloop thread , so you won't encounter lock competition.

in netty, each channel has a channelpipeline which contains a list of channelhandlers. Since all channel 's events are handled by one specific eventloop thread, these channelhandlers can share states without needs to think about thread-safe problems

Comment From: bclozel

Since there are no strong concerns here, and that we're not doing something forbidden by Netty's design, I'm closing this issue.

If this behavior has to change, then Reactor Netty might enforce writing from the event loop (which is not the case right now). Thanks!