浏览器发送请求后,为什么会触发两次请求的建立,两次 handler的添加 -- 引流 Netty


/**
 * 浏览器发送请求后
 * 运行结果:
 * [nioEventLoopGroup-3-1] 添加 handler了
 * [nioEventLoopGroup-3-2] 添加 handler了
 * [nioEventLoopGroup-3-1] 移除 handler了
 * [nioEventLoopGroup-3-2] 移除 handler了
 * [nioEventLoopGroup-3-1] channel已和远程节点建立连接
 * [nioEventLoopGroup-3-2] channel已和远程节点建立连接
 * [nioEventLoopGroup-3-1] 读取数据触发
 * [nioEventLoopGroup-3-1] 数据已读取完毕
 * [nioEventLoopGroup-3-1] 读取数据触发
 * [nioEventLoopGroup-3-1] 数据已读取完毕
 */
@Slf4j
public class HttpServer {
    public static void main(String[] args) {
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        new ServerBootstrap()
                .group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {

                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HttpServerCodec());
                        ch.pipeline().addLast(new SimpleChannelInboundHandler<HttpRequest>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
                                System.out.println(msg.uri() + "*********" + msg.headers());
                                log.debug("读取数据触发");
                                // 响应请求
                                DefaultFullHttpResponse response = new DefaultFullHttpResponse(msg.protocolVersion(), HttpResponseStatus.OK);
                                byte[] res = "<h1>the road is still long</h1>".getBytes();
                                // 请求头中需要去设置请求体长度 - 不然浏览器会空转等待
                                response.headers().set(CONTENT_LENGTH, res.length);
                                response.content().writeBytes(res);
                                ctx.writeAndFlush(response);

                            }

                            @Override
                            public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
                                log.debug("数据已读取完毕");
                                super.channelReadComplete(ctx);
                            }

                            @Override
                            public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
                                log.debug("channel注销");
                                super.channelUnregistered(ctx);
                            }

                            @Override
                            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                log.debug("channel已和远程节点建立连接");
                                super.channelActive(ctx);
                            }

                            @Override
                            public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                                log.debug("channel已和远程节点断开连接");
                                super.channelInactive(ctx);
                            }
                        });
                    }

                    @Override
                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                        log.debug("捕获到异常了");
                        super.exceptionCaught(ctx, cause);
                    }

                    @Override
                    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
                        log.debug("添加 handler了");
                        super.handlerAdded(ctx);
                    }

                    @Override
                    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
                        log.debug("移除 handler了");
                        super.handlerRemoved(ctx);
                    }
                }).bind(8080);
    }
}

一开始我认为两次发送数据,是因为 Http请求,对应两次数据的发送,第一次是请求行和请求头,第二次是请求体,那为什么这里会有两个连接?不应该是只有一次连接吗?

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 以帮助更多的人 ^-^