Reactor Netty HTTP Server接收Connect请求的逻辑

1. 创建 EventLoopGroup

设置 parentGroupchildGroup 共用一个 EventLoopGroup ,创建的是 NioEventLoopGroup 实例,包含 8 个 NioEventLoop 实例。

reactor.netty.tcp.TcpServerRunOn#configure(io.netty.bootstrap.ServerBootstrap, boolean, reactor.netty.resources.LoopResources)

static void configure(ServerBootstrap b,
			boolean preferNative,
			LoopResources resources) {
	SslProvider sslProvider =  SslProvider.findSslSupport(b);

	boolean useNative = preferNative &&
			(sslProvider == null || !(sslProvider.sslContext instanceof JdkSslContext));
	// parent and children use the sam EventLoopGroup
	EventLoopGroup selectorGroup = resources.onServerSelect(useNative);
	EventLoopGroup elg = resources.onServer(useNative);

	b.group(selectorGroup, elg)
	 .channel(resources.onServerChannel(elg));
}

2. 创建并初始化 NioServerSocketChannel

reactor.netty.tcp.TcpServerBind#bind 方法中会调用 ServerBootStrap.bind() 方法,该方法执行时会创建 NioServerSocketChannel 实例并进行初始化,在初始化 NioServerSocketChannel 时,会添加加 ServerBootstrapAcceptor ChannelHandler。

io.netty.bootstrap.AbstractBootstrap#initAndRegister

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
    	// create NioServerSocketChannel
        channel = channelFactory.newChannel();
        // 初始化NioServerSocketChannel
        init(channel);
    } catch (Throwable t) {
        // 略
    }

    ChannelFuture regFuture = config().group().register(channel);
    if (regFuture.cause() != null) {
        if (channel.isRegistered()) {
            channel.close();
        } else {
            channel.unsafe().closeForcibly();
        }
    }
    // 略
    return regFuture;
}

3. 将 NioServerSocketChannel 注册到 NioEventLoop

NioEventLoopGroup 中获取 NioEventLoop ,将 NioServerSocketChannelNioEventLoop 绑定。如果当前 NioEventLoop 尚未开始运行,则启动线程运行 NioEventLoop.run()

启动线程的逻辑 io.netty.util.concurrent.SingleThreadEventExecutor#doStartThread

NioEventLoop的run方法 io.netty.channel.nio.NioEventLoop#run

@Override
protected void run() {
    for (;;) {
        try {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                case SelectStrategy.CONTINUE:
                    continue;
                case SelectStrategy.BUSY_WAIT:
                    // fall-through to SELECT since the busy-wait is not supported with NIO
                case SelectStrategy.SELECT:
                    select(wakenUp.getAndSet(false));
					// 略注释
                    if (wakenUp.get()) {
                        selector.wakeup();
                    }
                default:
                }
            } catch (IOException e) {
                rebuildSelector0();
                handleLoopException(e);
                continue;
            }

            cancelledKeys = 0;
            needsToSelectAgain = false;
            final int ioRatio = this.ioRatio;
            if (ioRatio == 100) {
                try {
                    processSelectedKeys();
                } finally {
                    // Ensure we always run tasks.
                    runAllTasks();
                }
            } else {
                final long ioStartTime = System.nanoTime();
                try {
                    processSelectedKeys();
                } finally {
                    // Ensure we always run tasks.
                    final long ioTime = System.nanoTime() - ioStartTime;
                    runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                }
            }
        } catch (Throwable t) {
            handleLoopException(t);
        }
        // Always handle shutdown even if the loop processing threw an exception.
        try {
            if (isShuttingDown()) {
                closeAll();
                if (confirmShutdown()) {
                    return;
                }
            }
        } catch (Throwable t) {
            handleLoopException(t);
        }
    }
} 

4. 接收连接请求并处理

连接请求发送到 Netty Http Server 后,NioEventLoop 检测到 NioServerSocketChannel 状态发生变化后 (TODO: 如何监控?) 读取 java.nio.channels.SocketChannel 信息,并将其封装成 io.netty.channel.socket.nio.NioSocketChannel 对象。

信息读取完毕后触发 io.netty.channel.ChannelPipeline#fireChannelRead 方法,最终触发 ServerBootstrapAcceptor ChannelHandler 处理连接请求。

io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor#channelRead
该方法会对 NioSocketChannel 进行设置并将其注册到 child NioEventLoopGroup

@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;

    child.pipeline().addLast(childHandler);

	// 设置channel的操作
    setChannelOptions(child, childOptions, logger);

    for (Entry<AttributeKey<?>, Object> e: childAttrs) {
        child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
    }

    try {
        childGroup.register(child).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()) {
                    forceClose(child, future.cause());
                }
            }
        });
    } catch (Throwable t) {
        forceClose(child, t);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值