when I use netty ctx.writeAndFlush(),the client does not receive a response

Viewed 27

Java development, using netty's channel When writeandflush is executed in a new thread, the client does not receive a response; It can be received when executed in the normal method

private READER_ERR initReader() {

    //not receive
    new Thread(new Runnable() {
        @Override
        public void run() {
            Channel channel = NettyChannelMap.get(clientId);
            if (channel != null) {
                ChatDto returnDto = new ChatDto();
                returnDto.setClientId(clientId).setMsgType("READ").setMsg("返回数据");
                channel.writeAndFlush(JSON.toJSONString(returnDto));
            }
        }
    }).start();

    //receive
    Channel channel = NettyChannelMap.get(clientId);
    if (channel != null) {
        ChatDto returnDto = new ChatDto();
        returnDto.setClientId(clientId).setMsgType("READ").setMsg("返回数据");
        channel.writeAndFlush(JSON.toJSONString(returnDto));
    }
}

The interrupt point debugs the netty source code and finds that it enters the AbstractChannelHandlerContext class

if (executor.inEventLoop()) {
    if (flush) {
        next.invokeWriteAndFlush(m, promise);
    } else {
        next.invokeWrite(m, promise);
    }
} else {
    AbstractChannelHandlerContext.WriteTask task = AbstractChannelHandlerContext.WriteTask.newInstance(next, m, promise, flush);
    if (!safeExecute(executor, task, promise, m, !flush)) {
        task.cancel();
    }
}

We can see

public boolean inEventLoop(Thread thread) {
    return thread == this.thread;
}

false is returned, it indicates that the thread has been started, and the thread does not belong to EventLoop. It is a thread created by the user. Therefore, netty creates a task internally and puts it into the queue for execution. The problem is that this queue has not been executed, and there is no place to forcibly find the task for execution.

Add a point: if the client receives the message normally, entering ineventloop() will return true, indicating that if the current thread belongs to EventLoop, it can be executed immediately.

Now you need to send messages to the client multiple times in a callback method, so how can the server actively send messages to the client in the new thread?

I tried again and found that if the last message was sent by the ineventloop worker thread, those messages that were not sent before will also be sent along with the messages of the last worker thread according to the insertion time sequence. For example, when the program runs, the order of messages added is 1, 2, 3, and the "end" sent by a worker thread is added, then the order of messages received by the client is: end, 1, 2, 3

0 Answers
Related