Netty源码分析(二):客户端操作之EventLoopGroup、group()、option()

EventLoopGroup

顾名思义,为事件循环组,可以理解为线程组,类似Filter、Intercept,都是循环链路
先看看类图:
在这里插入图片描述

可以看到最上层为Executor,接下层为ExecutorService,即线程池,印证了Event是通过线程来分发的,本质就是线程池

切入点中,new了一个NioEventLoopGroup,咱们来说道说道,直接看最深层的构造方法:

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    if (executor == null) {
        //初始化线程池
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
	//1. 创建一个大小为nThreads的SingleThreadEventExecutor数组
    children = new EventExecutor[nThreads];
	//2.初始化数组,每次循环都是new一个NioEventLoop
    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            children[i] = newChild(executor, args);
            success = true;
        } 。。。
    }
	//3.根据nThreads的大小,创建不同的Chooser。
    //即如果nThreads是2的幂,则使用PowerOfTwoEventExecutorChooser
    //反之使用GenericEventExecutorChooser
    //两者功能一致,都是从children数组中选择一个合适的EventExecutor实例
    chooser = chooserFactory.newChooser(children);

    final FutureListener<Object> terminationListener = new FutureListener<Object>() {
        @Override
        public void operationComplete(Future<Object> future) throws Exception {
            if (terminatedChildren.incrementAndGet() == children.length) {
                terminationFuture.setSuccess(null);
            }
        }
    };

    for (EventExecutor e: children) {
        e.terminationFuture().addListener(terminationListener);
    }

    Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
    Collections.addAll(childrenSet, children);
    readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

不断深入super的过程中出现的有:
SelectStrategyFactory:用来管理Nio中的Selector

DEFAULT_EVENT_LOOP_THREADS:默认事件循环数,涉及一个算法:

//Runtime.getRuntime().availableProcessors()获取运行时电脑有多少个cpu,即几核
//此处将线程池初始化为cpu的两倍
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
    "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));

EventLoopGroup初始化过程总结:
在这里插入图片描述

group方法:

public B group(EventLoopGroup group) {
    this.group = group;
    return (B) this;
}

非常简单,就是将初始化后的EventLoopGroup放入Bootstrap中

option方法:

public <T> B option(ChannelOption<T> option, T value) {
    if (value == null) 
        synchronized (options) 
            options.remove(option);
    else 
        synchronized (options) 
            options.put(option, value);
    return (B) this;
}

也非常简单,就是根据value是否为null,来选择是否加入options

handler方法

将需要的处理器、编码解码器等放入pipeline中,即真正的业务处理

我们实现了ChannelInitializer#InitChannel,那么这个方法是在哪里调用呢?是在ChannelInitializer#channelRegistered#initChannel中

public final void channelRegistered(ChannelHandlerContext ctx) throws Exception {
    if (initChannel(ctx)) //模板模式
        ctx.pipeline().fireChannelRegistered();
     else 
        ctx.fireChannelRegistered();
}
private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
    initChannel((C) ctx.channel());//使用者重写的就是此方法
    remove(ctx);
}

重写了之后,会调用fireChannelRegistered:

public final ChannelPipeline fireChannelRegistered() {
    AbstractChannelHandlerContext.invokeChannelRegistered(head);
    return this;
}
//此处代码很有美感
static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        next.invokeChannelRegistered();
    } else {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelRegistered();
            }
        });
    }
}

回到initChannel中,看看remove方法,此方法通过finally来保证执行,是一种设计技巧:

private void remove(ChannelHandlerContext ctx) {
    try {
        ChannelPipeline pipeline = ctx.pipeline();
        if (pipeline.context(this) != null) {
            pipeline.remove(this);
        }
    } finally {
        initMap.remove(ctx);
    }
}

remove自己,即ChannelInitializer,因为它只是作为一个配置的模板,执行的时候不需要它的逻辑,删掉可以增加性能,这是一种很巧妙的设计技巧

看看流程图:
在这里插入图片描述
最后一个管道,即执行完handler方法后,pipeline的状态

猜你喜欢

转载自blog.csdn.net/qq_41594698/article/details/89840737