1.netty源码阅读-管理端Server启动

0 阅读4分钟

管理端Server

初始化MultiThreadIoEventLoopGroup

1.根据传入的线程数初始化事件执行器

MultithreadEventExecutorGroup构造器

// 初始化时间线程数
children = new EventExecutor[nThreads];

// 遍历生成
for (int i = 0; i < nThreads; i++) {
    boolean success = false;
    try {
        // 根据传入的类型来确认 执行器的类型
        children[i] = newChild(executor, args);
        success = true;
    } catch (Exception e) {
        ...
    } finally {
        // 不成功优雅关闭
        if (!success) {
            ...
        }
    }
    
}

// 所有 EventLoop 创建完成后,再创建选择器。
// 当有新任务/新连接到来时,chooser 决定把它分配给哪一个 EventLoop。
chooser = chooserFactory.newChooser(children);

...
readonlyChildren = Collections.unmodifiableSet(childrenSet);

MultiThreadIoEventLoopGroup的newChild()方法

protected IoEventLoop newChild(Executor executor, IoHandlerFactory ioHandlerFactory,
                               @SuppressWarnings("unused") Object... args) {
    return new SingleThreadIoEventLoop(this, executor, ioHandlerFactory);
}

public SingleThreadIoEventLoop(IoEventLoopGroup parent, Executor executor, IoHandlerFactory ioHandlerFactory) {
    super(parent, executor, false,
            ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported());
    this.maxTaskProcessingQuantumNs = DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS;
    // io 处理层,EventLoop "怎么去等待 I/O 事件,以及事件来了之后发给谁"。
    this.ioHandler = ioHandlerFactory.newHandler(this);
}

看一下SingleThreadIoEventLoop的构造器

/**
 * parent	线程组归属
 * executor	线程的启动方式
 * addTaskWakesUp	入队唤醒策略
 * supportSuspension	状态机是否含"暂停"状态
 * maxPendingTasks	队列容量上限(背压)
 * rejectedHandler	队列满时的兜底策略
 */
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                    boolean addTaskWakesUp, boolean supportSuspension,
                                    int maxPendingTasks, RejectedExecutionHandler rejectedHandler) {
    super(parent);
    this.addTaskWakesUp = addTaskWakesUp;
    this.supportSuspension = supportSuspension;
    this.maxPendingTasks = Math.max(16, maxPendingTasks);
    this.executor = ThreadExecutorMap.apply(executor, this);
    taskQueue = newTaskQueue(this.maxPendingTasks);
    rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    lastActivityTimeNanos = ticker().nanoTime();
}


初始化ServerBootstrap

ServerBootstrap b = new ServerBootstrap();
// 简化写法:同一个 EventLoopGroup 同时承担 boss 和 worker 的职责
b.group(group)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG, 100)
        .handler(new LoggingHandler(LogLevel.INFO))
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                if (sslCtx != null) {
                    p.addLast(sslCtx.newHandler(ch.alloc()));
                }
                //p.addLast(new LoggingHandler(LogLevel.INFO));
                p.addLast(serverHandler);
            }
        });


// group 初始化处理线程组。b.group(group) 会把同一个 group 同时赋给 boss 和 worker。
// 这是简化用法:一个线程池既接受连接,也处理子连接上的 I/O。
// 生产环境中更常见的是显式拆分 bossGroup 和 workerGroup。
// EventLoopGroup bossGroup = new NioEventLoopGroup(1);    // ① boss 线程池:只接受连接(通常 1~2 个线程)
// EventLoopGroup workerGroup = new NioEventLoopGroup();   // ② worker 线程池:处理每个连接上的 I/O(默认 CPU 核数*2)
// ServerBootstrap b = new ServerBootstrap();
// 显式指定两个线程池:第一个是 boss,第二个是 worker
// b.group(bossGroup, workerGroup)     // ← parentGroup=bossGroup, childGroup=workerGroup

// channel 初始化创建channel的类型,使用工厂设计模式
// option 作用于 ServerChannel(NioServerSocketChannel),也就是监听端口、接受连接的那个 Channel。
// 整个服务通常只有 1 个 ServerChannel。
// handler 作用于 ServerChannel 的 Pipeline,只创建 1 次,贯穿整个服务器生命周期。

// childHandler 作用于每个接入的客户端 SocketChannel。
// 每个新连接都有自己的 SocketChannel 和 Pipeline,都会执行一次 childHandler 初始化。


启动服务

// 同步启动
ChannelFuture f = b.bind(PORT).sync();

// bind 绑定本地端口号,启动相关任务

主要逻辑我们需要看AbstractBootstrap.doBind

private ChannelFuture doBind(final SocketAddress localAddress) {
    // 初始化服务端 ServerChannel,并将它注册到 parent/boss EventLoopGroup
    final ChannelFuture regFuture = initAndRegister();
    ...
    if (regFuture.isDone()) {
        // 此时我们知道注册已经完成并且成功了。
        ChannelPromise promise = channel.newPromise();
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        ...
        // 异常处理
        return promise;
    }
}


我们看一下initAndRegister方法

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        // 1.创建 Channel 对象(此时还没注册到 EventLoop)
        channel = channelFactory.newChannel();

        // 2.调用 init() 方法
        init(channel);
    } catch (Throwable t) {
        ...  // 异常处理
    }

    // 3.注册到 EventLoopGroup —— 对 ServerBootstrap 来说,这里注册的是 ServerChannel 到 parent/boss group
    final ChannelFuture regFuture = config().group().register(channel);
    ...

    return regFuture;
}

ServerBootstrap.init方法

void init(Channel channel) throws Throwable {
        // 配置 ChannelOption,影响底层 Channel 行为,例如 SO_BACKLOG、SO_REUSEADDR 等
        setChannelOptions(channel, newOptionsArray(), logger);
        // 存储用户自定义属性,可以通过 AttributeKey 在 Channel 上保存上下文数据
        setAttributes(channel, newAttributesArray());

        // 得到pipeline,pipeline的初始化是在创建 Channel 时完成
        ChannelPipeline p = channel.pipeline();

        // 保存子通道配置的引用(避免后续被修改)
        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions = newOptionsArray(childOptions);
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs = newAttributesArray(childAttrs);
        // 加载拓展插件
        final Collection<ChannelInitializerExtension> extensions = getInitializerExtensions();

        // 给 ServerChannel 添加初始化器。这里初始化的是 ServerChannel 的 Pipeline。
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                final ChannelPipeline pipeline = ch.pipeline();
                // 添加用户配置的处理器(如果存在)
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                // 这里的 ch 是 ServerChannel,所以任务提交到 boss/parent EventLoop 执行。
                // 这样可以保证 ServerBootstrapAcceptor 在 handlerAdded 之后再加入 Pipeline。
                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        // ServerBootstrapAcceptor 是 ServerChannel Pipeline 中的入站处理器。
                        // 它在接收到 accepted SocketChannel 后:
                        // 1. 给子 Channel 添加 childHandler;
                        // 2. 设置 childOptions 和 childAttrs;
                        // 3. 执行扩展点;
                        // 4. 将子 Channel 注册到 childGroup,也就是 worker EventLoopGroup。
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs,
                                extensions));
                    }
                });
            }
        });
        ...
    }




关于AbstractChannel的注册流程

public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    ObjectUtil.checkNotNull(eventLoop, "eventLoop");
    // 检查
    ...

    // 设置关联的 EventLoop
    AbstractChannel.this.eventLoop = eventLoop;

    // 将通道里面的执行器设置为空
    AbstractChannelHandlerContext context = pipeline.tail;
    do {
        context.contextExecutor = null;
        context = context.prev;
    } while (context != null);

    // 如果当前线程就是 EventLoop 线程,直接注册;否则提交任务到 EventLoop 执行
    ...
        register0(promise);
    ...
}

private void register0(ChannelPromise promise) {
    ...
    // 创建内部注册 Promise,用于监听底层注册结果
    ChannelPromise registerPromise = newPromise();
    boolean firstRegistration = neverRegistered;
    // 添加监听器,处理注册成功后的回调
    registerPromise.addListener(future -> {
        if (future.isSuccess()) {
            // 更新注册状态
            neverRegistered = false;
            registered = true;

            // 确保在通知 promise 之前调用 handlerAdded,防止用户在监听器中触发事件时 Handler 还未添加
            pipeline.invokeHandlerAddedIfNeeded();

            // 通知 register() 的调用者成功了
            safeSetSuccess(promise);
            // 触发注册事件,Pipeline 传播
            pipeline.fireChannelRegistered();

            // 仅在首次注册且 Channel 活跃时触发 channelActive
            if (isActive()) {
                if (firstRegistration) {
                    // 通知我已经准备好了可以进行通信了
                    pipeline.fireChannelActive();
                } else if (config().isAutoRead()) {
                    // 重新注册且 autoRead 开启时,需要重新开始读取数据
                    beginRead();
                }
            }
        } else {
            // 注册失败,关闭 Channel 避免资源泄漏
            ...
        }
    });
    // 底层 I/O 注册。以 NIO 为例,这里会把 Channel 注册到 Selector,
    // 并完成 Channel 与当前 EventLoop 的绑定。
    doRegister(registerPromise);
}