较真儿学源码系列-Netty核心流程源码分析

安稳与你 提交于 2020-10-12 07:09:05

目录

1 简介

1.1 线程模型

1.2 ChannelHandler & ChannelPipeline

1.3 直接内存

2 NioEventLoopGroup

3 ServerBootstrap & Bootstrap

3.1 构造器

3.2 group方法

3.3 channel方法

3.4 option方法

3.5 childHandler & handler方法

3.6 bind & connect方法

4 sync方法

5 writeAndFlush方法

6 心跳检测机制

6.1 构造器

6.2 channelActive方法

6.3 channelRead方法


Netty版本:4.1.51.Final。


1 简介

因为NIO的类库和API比较繁琐,使用起来比较麻烦,开发的工作量和难度都非常大,例如客户端面临断连重连、网络闪断、心跳处理、半包读写、网络拥塞和异常流的处理等等。所以Netty对Java自带的NIO API进行了良好的封装,解决了上述问题。且Netty拥有高性能、吞吐量更高、延迟更低、减少资源消耗,零拷贝直接内存等优点。所以Netty可以很方便地实现出一个网络通信系统,比如聊天服务器或弹幕系统(我曾经使用Netty实现过一个简易聊天室的demo,感兴趣的可以查看《Netty实现简易聊天室的功能》),同时在分布式框架中,像阿里的Dubbo和RocketMQ,底层使用的就是Netty来作为基础通信组件。

需要注意的是:Netty曾经有Netty 5这个版本,但是后来被废弃掉了,现在使用的都是Netty 4的版本。之所以被废弃,最主要的原因是Netty 5中使用了ForkJoinPool,增加了代码的复杂性却没有很明显的性能提升,同时增加了没有必要的多版本分支的维护工作(Norman Maurer(《Netty IN ACTION》作者,同时他现在也在领导着Netty项目)的原话在此https://github.com/netty/netty/issues/4466)。

值得一提的是:在2016年Norman Maurer曾经对Netty做过一次演讲,详细介绍了4.x版本相对于3.x版本所做的改进之处。讲解的非常好,感兴趣的可以查看《Netty - One Framework to rule them all....》(中文字幕版)。

1.1 线程模型

Netty使用的是NIO的模型(我之前写过一篇讲解BIO、NIO和AIO的文章,感兴趣的可以查看《BIO & NIO & AIO》),但是对于NIO模型来说,我当时示例代码的服务端是只用了一个线程来处理。那么假如此时有十万多个客户端需要和服务端IO交互,而其中某一个客户端和服务端的IO交互花费时间很长,剩下的十万个IO请求就都会被阻塞住。即使服务端使用的是线程池,服务端也不可能开十万个线程,多余的线程也会被放在阻塞队列中进行阻塞。所以在Netty中又进一步优化了原有NIO的模型:

上面就是Netty的线程模型图,其中客户端我没有细画是因为其执行逻辑和服务端大致都是类似的,只不过客户端只有一组线程组(WorkerGroup),而不是服务端的两组(BossGroup和WorkerGroup)。

在服务端中BossGroup只负责接收客户端的连接(一般只需要一个线程就可以了,如果需要监听多个端口才需要开多个NioEventLoop);而WorkerGroup专门负责网络的读写,是真正干活的线程,WorkerGroup做成多个NioEventLoop的话就会有多个selector来处理客户端的IO请求。Netty通过这种方式来实现对连接IO操作和读写IO操作的分离,让两者之间不会受干扰,不会出现一个读写IO非常慢从而导致后面的连接IO被阻塞的情况。同时如果连接IO出现问题的话,往往是网络出现异常;而读写IO出现问题可能是业务代码逻辑上有问题。这样就可以通过职责分离,快速定位出问题所在(分治的思想通常是实现任何可扩展性目标的最佳方法)。

每个NioEventLoop(可以把NioEventLoop理解为一个线程,而NioEventLoopGroup就相当于线程池)都会循环做三件事:

  1. select:BossGroup中的select方法是用来处理accept事件,WorkerGroup中的select方法是用来处理read或write事件,而客户端的select方法是用来处理connect、read或write事件;
  2. processSelectedKeys:BossGroup中的processSelectedKeys方法是用来注册客户端的NioSocketChannel到workerGroup的一个selector上,WorkerGroup中的processSelectedKeys方法是用来处理客户端的I/O事件(在pipeline上遍历处理),而客户端的processSelectedKeys方法是用来处理服务端的I/O事件;
  3. runAllTasks:用来处理任务队列taskQueue和定时任务队列scheduledTaskQueue中的任务。

其实这里Netty的线程模型源自于Doug Lea大神写过的一篇文章《Scalable IO in Java》中的Multiple Reactors模型:

1.2 ChannelHandler & ChannelPipeline

ChannelHandler是处理服务端和客户端入站(站在客户端的角度来说,服务端往客户端发送数据;或者站在服务端的角度来说,客户端往服务端发送数据叫做入站)出站(站在客户端的角度来说,客户端往服务端发送数据;或者站在服务端的角度来说,服务端往客户端发送数据叫做出站)的逻辑容器,具体可分为ChannelInboundHandler和ChannelOutboundHandler。ChannelInboundHandler是用来处理入站逻辑的,而ChannelOutboundHandler是用来处理出站逻辑的。比方说我现在写了一个自定义编解码的逻辑,那么ChannelInboundHandler就是写解码逻辑的,而ChannelOutboundHandler是写编码逻辑的。当然Netty中也内置了一些ChannelHandler,比如说对String的编解码逻辑StringEncoder和StringDecoder,对象的编解码逻辑ObjectEncoder和ObjectDecoder等。

如上面的Netty线程模型图所示,在处理实际业务时用到的就是ChannelHandler。但是上面的图画的只是一个大概,完整的服务端和客户端ChannelHandler的交互示意图如下所示:

如果有多个ChannelHandler,那么它们之间是通过ChannelPipeline的方式来组合使用的,也就是说通过pipeline可以将所有的ChannelInboundHandler和ChannelOutboundHandler组合成一个处理链,但是并不是一次会把所有的ChannelHandler都执行。如上图所示:在入站的时候,只会从pipeline的head向tail方向执行处理链上所有的ChannelInboundHandler,遇到ChannelOutboundHandler的时候会跳过;而在出站的时候,只会从pipeline的tail向head方向执行处理链上所有的ChannelOutboundHandler,遇到ChannelInboundHandler的时候会跳过。

有一点需要注意的是:在一条处理链中所有出站的handler,它们之间的顺序不是随便写的。比如说我现在有一个发送数据的handler和一个编码的handler。因为出站的顺序是从pipeline的tail到head,所以发送数据的handler一定要放在编码handler的后面,也就是必须要先发送数据再编码。如果这个顺序反了,就变成了先编码再发送数据,那么就不会发送成功数据,逻辑就有问题了。同时对于所有入站的handler也是一样的道理。因为入站的顺序是从pipeline的head到tail,所以接收数据的handler也是一定要放在解码handler的后面,也就是必须要先解码再接收数据。

1.3 直接内存

直接内存是相对于堆内存来说的,它并不是JVM运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。某些情况下直接内存也会被频繁地使用,而且也有可能会导致OOM的出现。元空间对应的内存可以叫作直接内存,同时在NIO编程中用DirectByteBuffer也可以分配一块直接内存,它们对应的都是机器的物理内存。

但是在NIO编程中直接内存的API非常难用,稍不留意就会写出bug。所以在Netty中已经帮我们封装为了ByteBuf类,使用起来更加方便。ByteBuf的大致数据结构如下:

每调用一次writeByte方法,writerIndex指针就+1;每调用一次readByte方法,readerIndex指针就+1;而getByte方法是不会造成指针移动的。所以就可以依据这两个指针划分为三个区间:

  • [0, readerIndex):代表已经读取过的区域;
  • [readerIndex, writerIndex):代表可以读取但还没读取的区域;
  • [writerIndex, capacity):代表可以写的区域。

值得一提的是:直接内存虽然执行速度更快,但是其创建和销毁是很耗时间的(起码比堆内存慢)。所以在Netty中,对ByteBuf使用了内存池的缓冲区重用机制,提前放进去了一些ByteBuf。


2 NioEventLoopGroup

在上面的Netty线程模型图中,bossGroup和workerGroup就是NioEventLoopGroup,也就是Netty自己封装的线程池。

/**
 * NioEventLoopGroup:
 * 无参构造器
 */
public NioEventLoopGroup() {
    //这里nThreads会赋值为0
    this(0);
}

/**
 * 有参构造器
 */
public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

public NioEventLoopGroup(int nThreads, Executor executor) {
    this(nThreads, executor, SelectorProvider.provider());
}

public NioEventLoopGroup(
        int nThreads, Executor executor, final SelectorProvider selectorProvider) {
    this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}

public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                         final SelectStrategyFactory selectStrategyFactory) {
    super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}

/**
 * MultithreadEventLoopGroup:
 */
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
    /*
    从这里可以看到,如果是无参构造器,传进来的nThreads就是0,那么就会为DEFAULT_EVENT_LOOP_THREADS
    而DEFAULT_EVENT_LOOP_THREADS值的初始化过程在下面,默认为当前JVM最大可用线程数*2
     */
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}

public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup {
    //...

    private static final int DEFAULT_EVENT_LOOP_THREADS;

    static {
        /*
        如果用户没有设置“io.netty.eventLoopThreads”和“io.netty.availableProcessors”这两个参数,
        DEFAULT_EVENT_LOOP_THREADS的值就默认为当前JVM最大可用线程数*2(至少要为1)
         */
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

        if (logger.isDebugEnabled()) {
            logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
        }
    }

    //...
}

/**
 * MultithreadEventExecutorGroup:
 * 第39行代码处:
 */
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
    this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    if (nThreads <= 0) {
        throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
    }

    /*
    不管是有参构造器还是无参构造器,传进来的executor都是null,所以在此进行初始化的工作,
    赋值为一个Netty封装过的executor
     */
    if (executor == null) {
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

    //EventExecutor也是Netty封装过的线程池接口,这里的children就相当于一个线程池
    children = new EventExecutor[nThreads];

    for (int i = 0; i < nThreads; i++) {
        boolean success = false;
        try {
            /*
            这里默认会调用NioEventLoopGroup的newChild方法从而new出一个NioEventLoop,相当于一个Netty封装过的线程
            (实际上是相当于线程池,只不过这个线程池里只会有一个线程)。现在再来看一下之前的Netty线程模型图:children就
            相当于bossGroup或workerGroup,而其中的每一个元素就是NioEventLoop
             */
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
            throw new IllegalStateException("failed to create a child event loop", e);
        } finally {
            if (!success) {
                for (int j = 0; j < i; j++) {
                    children[j].shutdownGracefully();
                }

                for (int j = 0; j < i; j++) {
                    EventExecutor e = children[j];
                    try {
                        while (!e.isTerminated()) {
                            e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                        }
                    } catch (InterruptedException interrupted) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }

    //这里会调用DefaultEventExecutorChooserFactory的newChooser方法
    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);
    }

    //根据children构建不可修改readonlyChildren
    Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
    Collections.addAll(childrenSet, children);
    readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

/**
 * NioEventLoopGroup:
 * 第96行代码处:
 */
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);
}

/**
 * NioEventLoop:
 */
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
             SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,
             EventLoopTaskQueueFactory queueFactory) {
    super(parent, executor, false, newTaskQueue(queueFactory), newTaskQueue(queueFactory),
            rejectedExecutionHandler);
    this.provider = ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");
    this.selectStrategy = ObjectUtil.checkNotNull(strategy, "selectStrategy");
    //该方法里面会完成NIO的selectedKeys的初始化
    final NioEventLoop.SelectorTuple selectorTuple = openSelector();
    //这里进行对NIO的selector的初始化,也就是在上面Netty线程模型图中,每一个NioEventLoop都有一个selector的体现
    this.selector = selectorTuple.selector;
    this.unwrappedSelector = selectorTuple.unwrappedSelector;
}

/**
 * SingleThreadEventLoop:
 * 第160行代码处:
 */
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                boolean addTaskWakesUp, Queue<Runnable> taskQueue, Queue<Runnable> tailTaskQueue,
                                RejectedExecutionHandler rejectedExecutionHandler) {
    super(parent, executor, addTaskWakesUp, taskQueue, rejectedExecutionHandler);
    tailTasks = ObjectUtil.checkNotNull(tailTaskQueue, "tailTaskQueue");
}

/**
 * SingleThreadEventExecutor:
 * 第178行代码处:
 */
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                    boolean addTaskWakesUp, Queue<Runnable> taskQueue,
                                    RejectedExecutionHandler rejectedHandler) {
    super(parent);
    this.addTaskWakesUp = addTaskWakesUp;
    this.maxPendingTasks = DEFAULT_MAX_PENDING_EXECUTOR_TASKS;
    //这里进行对executor的初始化
    this.executor = ThreadExecutorMap.apply(executor, this);
    //这里进行对taskQueue的初始化
    this.taskQueue = ObjectUtil.checkNotNull(taskQueue, "taskQueue");
    this.rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}

/**
 * DefaultEventExecutorChooserFactory:
 * 第122行代码处:
 */
@SuppressWarnings("unchecked")
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
    /*
    这里会根据executors的长度是否是2的幂来选择调用PowerOfTwoEventExecutorChooser
    或GenericEventExecutorChooser。之所以有这个区别是因为后续会调用到next方法,
    而next方法会通过取余的方式来找到下一个EventExecutor。而如果长度为2的幂的话,会有
    优化的写法而不是使用默认的“%”取余符号,后续会详细讲解
     */
    if (isPowerOfTwo(executors.length)) {
        return new PowerOfTwoEventExecutorChooser(executors);
    } else {
        return new GenericEventExecutorChooser(executors);
    }
}

/**
 * 第212行代码处:
 * 该方法是用来判断val是否是2的幂。一个数的负数和原数的二进制形式的区别是取反再+1
 * 所以只有val是2的幂的时候,这个数和它取负数的数在最后val.length个位数长度上的
 * 数是完全一样的。所以两者按位与的结果就是这个数,以此就可以判断出来是否是2的幂了
 * 举个例子:假如说val是3,二进制是11。而-3的二进制是1111 1111 1111 1111 1111 1111 1111 1101
 * 两者在最后两位分别是11和01,是不一样的,所以按位与的结果肯定不是11,也就是十进制的3;
 * 那么假如说val是4,二进制是100;而-4的二进制是1111 1111 1111 1111 1111 1111 1111 1100
 * 两者在最后三位都是100,所以按位与的结果就是100,也就是十进制的4,也就是判断是相等的
 */
private static boolean isPowerOfTwo(int val) {
    return (val & -val) == val;
}

/**
 * 第213行代码处:
 */
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
    //这里将children赋值进PowerOfTwoEventExecutorChooser的executors
    this.executors = executors;
}

/**
 * 第215行代码处:
 */
GenericEventExecutorChooser(EventExecutor[] executors) {
    //这里将children赋值进GenericEventExecutorChooser的executors
    this.executors = executors;
}

3 ServerBootstrap & Bootstrap

Bootstrap在Netty中是启动的辅助类,可以在其中加上一些配置项。具体可分为服务端的ServerBootstrap和客户端的Bootstrap。

3.1 构造器

/**
 * ServerBootstrap:
 */
public ServerBootstrap() {
    //这里虽然是空实现,但在ServerBootstrap类中会完成如下所示的初始化工作
}

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
    //...

    private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> childAttrs = new ConcurrentHashMap<AttributeKey<?>, Object>();
    private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);

    //...
}

/**
 * ServerBootstrapConfig:
 * 第13行代码处:
 */
ServerBootstrapConfig(ServerBootstrap bootstrap) {
    super(bootstrap);
}

/**
 * AbstractBootstrapConfig:
 */
protected AbstractBootstrapConfig(B bootstrap) {
    //这里会将ServerBootstrap赋值给this.bootstrap
    this.bootstrap = ObjectUtil.checkNotNull(bootstrap, "bootstrap");
}

/**
 * Bootstrap:
 */
public Bootstrap() {
    //这里虽然是空实现,但在Bootstrap类中会完成如下所示的初始化工作
}

public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
    //...

    private final BootstrapConfig config = new BootstrapConfig(this);

    //...
}

/**
 * BootstrapConfig:
 * 第44行代码处:
 */
BootstrapConfig(Bootstrap bootstrap) {
    //这里会一样调用AbstractBootstrapConfig的构造器,将Bootstrap赋值给AbstractBootstrapConfig.bootstrap
    super(bootstrap);
}

3.2 group方法

/**
 * ServerBootstrap:
 * ServerBootstrap中的bossGroup会赋值给AbstractBootstrap的group;
 * 而workerGroup会赋值给ServerBootstrap的childGroup
 */
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
    //会调用到AbstractBootstrap的group方法
    super.group(parentGroup);
    if (this.childGroup != null) {
        throw new IllegalStateException("childGroup set already");
    }
    this.childGroup = ObjectUtil.checkNotNull(childGroup, "childGroup");
    return this;
}

/**
 * AbstractBootstrap:
 * 第8行代码处、以及Bootstrap调用group方法处:
 * Bootstrap中的workerGroup会赋值给AbstractBootstrap的group
 */
public B group(EventLoopGroup group) {
    ObjectUtil.checkNotNull(group, "group");
    if (this.group != null) {
        throw new IllegalStateException("group set already");
    }
    this.group = group;
    return self();
}

@SuppressWarnings("unchecked")
private B self() {
    return (B) this;
}

3.3 channel方法

/**
 * AbstractBootstrap:
 */
public B channel(Class<? extends C> channelClass) {
    //这里传进来的是NioServerSocketChannel(服务端)或NioSocketChannel(客户端)
    return channelFactory(new ReflectiveChannelFactory<C>(
            ObjectUtil.checkNotNull(channelClass, "channelClass")
    ));
}

/**
 * ReflectiveChannelFactory:
 */
public ReflectiveChannelFactory(Class<? extends T> clazz) {
    ObjectUtil.checkNotNull(clazz, "clazz");
    try {
        /*
        把NioServerSocketChannel或NioSocketChannel的空参数构造器赋值进constructor,
        后续会通过反射的方式进行调用
         */
        this.constructor = clazz.getConstructor();
    } catch (NoSuchMethodException e) {
        throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                " does not have a public non-arg constructor", e);
    }
}

/**
 * AbstractBootstrap:
 * 第6行代码处:
 */
public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) {
    return channelFactory((io.netty.bootstrap.ChannelFactory<C>) channelFactory);
}

@Deprecated
public B channelFactory(io.netty.bootstrap.ChannelFactory<? extends C> channelFactory) {
    ObjectUtil.checkNotNull(channelFactory, "channelFactory");
    if (this.channelFactory != null) {
        throw new IllegalStateException("channelFactory set already");
    }

    //把ReflectiveChannelFactory赋值给channelFactory
    this.channelFactory = channelFactory;
    return self();
}

3.4 option方法

/**
 * AbstractBootstrap:
 */
public <T> B option(ChannelOption<T> option, T value) {
    ObjectUtil.checkNotNull(option, "option");
    //options是一个LinkedHashMap,里面存放着存进来的TCP定制化参数
    synchronized (options) {
        if (value == null) {
            options.remove(option);
        } else {
            options.put(option, value);
        }
    }
    return self();
}

3.5 childHandler & handler方法

/**
 * ServerBootstrap:
 */
public ServerBootstrap childHandler(ChannelHandler childHandler) {
    /*
    这里就是把传进来的ChannelInitializer赋值给childHandler,而我们在其中实现的initChannel方法
    会在channel被注册时回调,ChannelInitializer实例会在initChannel方法执行完毕后被销毁
    后续会看到这一点
     */
    this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
    return this;
}

/**
 * AbstractBootstrap:
 */
public B handler(ChannelHandler handler) {
    /*
    这里就是把传进来的ChannelInitializer赋值给handler,而我们在其中实现的initChannel方法
    会在channel被注册时回调,ChannelInitializer实例会在initChannel方法执行完毕后被销毁
    后续会看到这一点
     */
    this.handler = ObjectUtil.checkNotNull(handler, "handler");
    return self();
}

3.6 bind & connect方法

bind方法看起来就是一个绑定端口的方法,实则完成服务端启动的全过程,流程不仅长而且还很复杂。而前面这些方法都只是在做一些配置而已。

而connect方法是客户端连接服务端的方法,其执行过程和bind方法大致类似,所以这里只挑出实现不一样的地方来进行分析。

/**
 * AbstractBootstrap:
 * 这里是服务端的bind方法
 */
public ChannelFuture bind(int inetPort) {
    return bind(new InetSocketAddress(inetPort));
}

public ChannelFuture bind(SocketAddress localAddress) {
    validate();
    return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}

private ChannelFuture doBind(final SocketAddress localAddress) {
    //完成channel的初始化和注册过程
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();
    if (regFuture.cause() != null) {
        return regFuture;
    }

    if (regFuture.isDone()) {
        ChannelPromise promise = channel.newPromise();
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
        regFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Throwable cause = future.cause();
                if (cause != null) {
                    promise.setFailure(cause);
                } else {
                    promise.registered();

                    doBind0(regFuture, channel, localAddress, promise);
                }
            }
        });
        return promise;
    }
}

/**
 * Bootstrap:
 * 这里是客户端的connect方法
 */
public ChannelFuture connect(String inetHost, int inetPort) {
    return connect(InetSocketAddress.createUnresolved(inetHost, inetPort));
}

public ChannelFuture connect(SocketAddress remoteAddress) {
    ObjectUtil.checkNotNull(remoteAddress, "remoteAddress");
    validate();
    return doResolveAndConnect(remoteAddress, config.localAddress());
}

private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
    //完成channel的初始化和注册过程
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();

    if (regFuture.isDone()) {
        if (!regFuture.isSuccess()) {
            return regFuture;
        }
        return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
    } else {
        final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
        regFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Throwable cause = future.cause();
                if (cause != null) {
                    promise.setFailure(cause);
                } else {
                    promise.registered();
                    doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
                }
            }
        });
        return promise;
    }
}

/**
 * 第16行和第61行代码处:
 * 可以看到服务端和客户端都调用了initAndRegister方法,那么下面就来看一下其实现
 */
final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        //这里会调用到我们之前在channel方法中创建的ReflectiveChannelFactory的newChannel方法
        channel = channelFactory.newChannel();
        init(channel);
    } catch (Throwable t) {
        if (channel != null) {
            channel.unsafe().closeForcibly();
            return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
        }
        return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
    }

    //这里的group方法拿到的就是bossGroup 这里也就是在对channel进行注册
    ChannelFuture regFuture = config().group().register(channel);
    if (regFuture.cause() != null) {
        if (channel.isRegistered()) {
            channel.close();
        } else {
            channel.unsafe().closeForcibly();
        }
    }

    return regFuture;
}

/**
 * ReflectiveChannelFactory:
 * 第95行代码处:
 */
@Override
public T newChannel() {
    try {
        /*
        之前constructor指向的是NioServerSocketChannel(服务端)或NioSocketChannel(客户端),
        所以在这里调用了其空参数构造器
         */
        return constructor.newInstance();
    } catch (Throwable t) {
        throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
    }
}

/**
 * NioServerSocketChannel:
 * 第129行代码处:
 */
public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

/**
 * 这里可以看到通过newSocket方法来生成了一个ServerSocketChannel。而本方法的返回值
 * ServerSocketChannel不就是NIO的ServerSocketChannel吗?所以这里就可以看出
 * NioServerSocketChannel就是对原生NIO的ServerSocketChannel的包装
 */
private static ServerSocketChannel newSocket(SelectorProvider provider) {
    try {
        return provider.openServerSocketChannel();
    } catch (IOException e) {
        throw new ChannelException(
                "Failed to open a server socket.", e);
    }
}

/**
 * 第140行代码处:
 */
public NioServerSocketChannel(ServerSocketChannel channel) {
    //这里的OP_ACCEPT正是在之前NIO编程中,对ServerSocketChannel注册OP_ACCEPT事件的相关代码
    super(null, channel, SelectionKey.OP_ACCEPT);
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

/**
 * AbstractNioMessageChannel:
 * 第162行代码处:
 */
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent, ch, readInterestOp);
}

/**
 * NioSocketChannel:
 * 第129行代码处:
 * 这里先不去查看AbstractNioMessageChannel的super方法,先来看一下客户端的NioSocketChannel的无参构造器
 */
public NioSocketChannel() {
    this(DEFAULT_SELECTOR_PROVIDER);
}

public NioSocketChannel(SelectorProvider provider) {
    this(newSocket(provider));
}

/**
 * 这里跟NioServerSocketChannel一样,NioSocketChannel就是对原生
 * NIO的SocketChannel的包装
 */
private static SocketChannel newSocket(SelectorProvider provider) {
    try {
        return provider.openSocketChannel();
    } catch (IOException e) {
        throw new ChannelException("Failed to open a socket.", e);
    }
}

/**
 * 第184行代码处:
 */
public NioSocketChannel(SocketChannel socket) {
    this(null, socket);
}

public NioSocketChannel(Channel parent, SocketChannel socket) {
    super(parent, socket);
    config = new NioSocketChannelConfig(this, socket.socket());
}

/**
 * AbstractNioByteChannel:
 * 第207行代码处:
 */
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
    /*
    同服务端,这里跟NIO编程一样,对SocketChannel注册OP_READ事件,
    同时也调用了AbstractNioMessageChannel的super方法
     */
    super(parent, ch, SelectionKey.OP_READ);
}

/**
 * AbstractNioChannel:
 * 第171行和第220行代码处:
 * NioServerSocketChannel和NioSocketChannel都会调用到此处
 */
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent);
    this.ch = ch;
    //把注册事件赋值给readInterestOp
    this.readInterestOp = readInterestOp;
    try {
        //下面这行代码在NIO编程也是一样的,将ServerSocketChannel或SocketChannel配置为非阻塞模式
        ch.configureBlocking(false);
    } catch (IOException e) {
        try {
            ch.close();
        } catch (IOException e2) {
            logger.warn(
                    "Failed to close a partially initialized socket.", e2);
        }

        throw new ChannelException("Failed to enter non-blocking mode.", e);
    }
}

/**
 * AbstractChannel:
 * 第229行代码处:
 */
protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId();
    unsafe = newUnsafe();
    /*
    这里就可以看到对pipeline进行了初始化操作。也就是说,每一个NioServerSocketChannel
    或NioSocketChannel都会带有一个pipeline
     */
    pipeline = newChannelPipeline();
}

protected DefaultChannelPipeline newChannelPipeline() {
    return new DefaultChannelPipeline(this);
}

/**
 * DefaultChannelPipeline:
 */
protected DefaultChannelPipeline(Channel channel) {
    this.channel = ObjectUtil.checkNotNull(channel, "channel");
    succeededFuture = new SucceededChannelFuture(channel, null);
    voidPromise = new VoidChannelPromise(channel, true);

    /*
    这里可以看到初始化了pipeline中的head和tail的handler(HeadContext和TailContext本身就是
    一个ChannelHandler),而之后如果要加ChannelHandler的话,会在tail之前加入
     */
    tail = new TailContext(this);
    head = new HeadContext(this);

    //head和tail指针互相指向
    head.next = tail;
    tail.prev = head;
}

/**
 * ServerBootstrap:
 * 第96行代码处:
 */
@Override
void init(Channel channel) {
    setChannelOptions(channel, newOptionsArray(), logger);
    setAttributes(channel, attrs0().entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY));

    //拿到之前在newChannelPipeline方法里面设置好的pipeline
    ChannelPipeline p = channel.pipeline();

    //拿到之前在group方法里面设置好的workerGroup
    final EventLoopGroup currentChildGroup = childGroup;
    //拿到之前在childHandler方法里面设置好的childHandler
    final ChannelHandler currentChildHandler = childHandler;
    final Map.Entry<ChannelOption<?>, Object>[] currentChildOptions;
    //我在之前没有演示,但是如果调用childOption方法,这里获取的就是childOptions
    synchronized (childOptions) {
        currentChildOptions = childOptions.entrySet().toArray(EMPTY_OPTION_ARRAY);
    }
    //我在之前没有演示,但是如果调用childAttr方法,这里获取的就是childAttrs
    final Map.Entry<AttributeKey<?>, Object>[] currentChildAttrs = childAttrs.entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY);

    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.eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    pipeline.addLast(new ServerBootstrapAcceptor(
                            ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                }
            });
        }
    });
}

/**
 * Bootstrap:
 * 第96行代码处:
 * (这里是客户端和服务端不一样的地方)
 */
@Override
@SuppressWarnings("unchecked")
void init(Channel channel) {
    ChannelPipeline p = channel.pipeline();
    p.addLast(config.handler());

    setChannelOptions(channel, newOptionsArray(), logger);
    setAttributes(channel, attrs0().entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY));
}

/**
 * DefaultChannelPipeline:
 * 第311行和第340行代码处:
 * 可以看到服务端和客户端都调用了addLast方法,那么下面就来看一下其实现(以服务端来举例)
 */
@Override
public final ChannelPipeline addLast(ChannelHandler... handlers) {
    return addLast(null, handlers);
}

@Override
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
    ObjectUtil.checkNotNull(handlers, "handlers");

    for (ChannelHandler h : handlers) {
        if (h == null) {
            break;
        }
        addLast(executor, null, h);
    }

    return this;
}

/**
 * 第364行代码处:
 */
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
    final AbstractChannelHandlerContext newCtx;
    synchronized (this) {
        checkMultiplicity(handler);

        //把传进来的ChannelInitializer(服务端)封装为一个ChannelHandlerContext
        newCtx = newContext(group, filterName(name, handler), handler);

        addLast0(newCtx);

        if (!registered) {
            newCtx.setAddPending();
            callHandlerCallbackLater(newCtx, true);
            return this;
        }

        EventExecutor executor = newCtx.executor();
        if (!executor.inEventLoop()) {
            callHandlerAddedInEventLoop(newCtx, executor);
            return this;
        }
    }
    callHandlerAdded0(newCtx);
    return this;
}

/**
 * 第380行代码处:
 */
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
    return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler);
}

/**
 * DefaultChannelHandlerContext:
 */
DefaultChannelHandlerContext(
        DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
    super(pipeline, executor, name, handler.getClass());
    //这里就会将服务端的ChannelInitializer赋值进handler中,后面会用到
    this.handler = handler;
}

/**
 * 第382行代码处:
 * 从本方法就可以看出:新添加的ChannelHandlerContext会放在tail之前
 */
private void addLast0(AbstractChannelHandlerContext newCtx) {
    AbstractChannelHandlerContext prev = tail.prev;
    newCtx.prev = prev;
    newCtx.next = tail;
    prev.next = newCtx;
    tail.prev = newCtx;
}

/**
 * ServerBootstrap:
 * 第106行代码处:
 */
@Override
public final ServerBootstrapConfig config() {
    /*
    这里直接返回了config,而config的赋值在一开始创建ServerBootstrap时就已经创建好了,
    之前在分析ServerBootstrap的构造器中已经分析了这一点
     */
    return config;
}

/**
 * Bootstrap:
 * 第106行代码处:
 * (这里是客户端和服务端不一样的地方)
 */
@Override
public final BootstrapConfig config() {
    /*
    这里直接返回了config,而config的赋值在一开始创建Bootstrap时就已经创建好了,
    之前在分析Bootstrap的构造器中已经分析了这一点
     */
    return config;
}

/**
 * AbstractBootstrapConfig:
 * 第106行代码处:
 */
@SuppressWarnings("deprecation")
public final EventLoopGroup group() {
    //这里返回的就是ServerBootstrap或Bootstrap中的group方法
    return bootstrap.group();
}

/**
 * AbstractBootstrap:
 */
@Deprecated
public final EventLoopGroup group() {
    /*
    这里面的group就是之前在group方法中赋值的group,即bossGroup(服务端)
    或者是workerGroup(客户端)
     */
    return group;
}

/**
 * MultithreadEventLoopGroup:
 * 第106行代码处:
 */
@Override
public ChannelFuture register(Channel channel) {
    /*
    每调用一次本方法,就会用EventLoopGroup的下一个EventLoop来进行注册
    如果看过下面我对“next().register(channel)”这行代码的分析后就可以明白:
    这里实际上只会有一个线程来执行pipeline上的所有handler的事件,期间不会
    进行线程的切换,避免了锁竞争。这里也就是Netty中无锁串行化的体现
     */
    return next().register(channel);
}

@Override
public EventLoop next() {
    return (EventLoop) super.next();
}

/**
 * MultithreadEventExecutorGroup:
 */
@Override
public EventExecutor next() {
    /*
    在之前NioEventLoopGroup的构造器中,会根据executors的长度是否是2的幂来选择调用
    PowerOfTwoEventExecutorChooser或GenericEventExecutorChooser,也就是这里
    的chooser。此处会调用其next方法
     */
    return chooser.next();
}

/**
 * PowerOfTwoEventExecutorChooser(DefaultEventExecutorChooserFactory):
 */
@Override
public EventExecutor next() {
    /*
    executors也就是之前在NioEventLoopGroup的构造器中赋值进去的children。这里就是在拿取
    executors数组中的下一个EventExecutor。因为其长度为2的幂,所以可以用按位与的优化写法
    来同样达到取余的效果(在HashMap和ConcurrentHashMap中也出现了同样的取余优化写法)
     */
    return executors[idx.getAndIncrement() & executors.length - 1];
}

/**
 * GenericEventExecutorChooser(DefaultEventExecutorChooserFactory):
 */
@Override
public EventExecutor next() {
    /*
    同上面的解释,这里就是当executors的长度不是2的幂的时候,使用常规的“%”取余符号来进行拿取下一个
    EventExecutor的方式。之所以这里会取绝对值是为了防止出现数据溢出的情况:当idx递增到一个特别大
    的数:2147483647,那么此时再+1就变成了-2147483648,就变成了一个负数。而数组的索引位置
    是不可能出现负数的(如果为负数就会抛出数组索引越界异常),所以在这里会做一次取绝对值的操作
     */
    return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}

/**
 * SingleThreadEventLoop:
 * 第490行代码处:
 */
@Override
public ChannelFuture register(Channel channel) {
    return register(new DefaultChannelPromise(channel, this));
}

@Override
public ChannelFuture register(final ChannelPromise promise) {
    ObjectUtil.checkNotNull(promise, "promise");
    promise.channel().unsafe().register(this, promise);
    return promise;
}

/**
 * AbstractChannel:
 */
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    ObjectUtil.checkNotNull(eventLoop, "eventLoop");
    if (isRegistered()) {
        promise.setFailure(new IllegalStateException("registered to an event loop already"));
        return;
    }
    if (!isCompatible(eventLoop)) {
        promise.setFailure(
                new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
        return;
    }

    //将SingleThreadEventLoop赋值给AbstractChannel.eventLoop
    AbstractChannel.this.eventLoop = eventLoop;

    if (eventLoop.inEventLoop()) {
        register0(promise);
    } else {
        try {
            eventLoop.execute(new Runnable() {
                @Override
                public void run() {
                    register0(promise);
                }
            });
        } catch (Throwable t) {
            logger.warn(
                    "Force-closing a channel whose registration task was not accepted by an event loop: {}",
                    AbstractChannel.this, t);
            closeForcibly();
            closeFuture.setClosed();
            safeSetFailure(promise, t);
        }
    }
}

/**
 * AbstractEventExecutor:
 * 第573行代码处:
 */
@Override
public boolean inEventLoop() {
    return inEventLoop(Thread.currentThread());
}

/**
 * SingleThreadEventExecutor:
 */
@Override
public boolean inEventLoop(Thread thread) {
    /*
    这里可以看到inEventLoop方法就是用来判断当前线程和SingleThreadEventExecutor中的线程是否是同一个
    而this.thread在此处还没有被赋值,为null,所以本方法返回false
     */
    return thread == this.thread;
}

/**
 * SingleThreadEventExecutor:
 * 第577行代码处:
 * 这里把register0方法的执行逻辑先放一放,先来看一下任务是如何被执行的
 */
@Override
public void execute(Runnable task) {
    ObjectUtil.checkNotNull(task, "task");
    execute(task, !(task instanceof LazyRunnable) && wakesUpForTask(task));
}

private void execute(Runnable task, boolean immediate) {
    //同上,inEventLoop方法此时返回false
    boolean inEventLoop = inEventLoop();
    addTask(task);
    if (!inEventLoop) {
        startThread();
        if (isShutdown()) {
            boolean reject = false;
            try {
                if (removeTask(task)) {
                    reject = true;
                }
            } catch (UnsupportedOperationException e) {
            }
            if (reject) {
                reject();
            }
        }
    }

    if (!addTaskWakesUp && immediate) {
        wakeup(inEventLoop);
    }
}

/**
 * 第629行代码处:
 */
protected void addTask(Runnable task) {
    ObjectUtil.checkNotNull(task, "task");
    if (!offerTask(task)) {
        reject(task);
    }
}

/**
 * 第656行代码处:
 */
final boolean offerTask(Runnable task) {
    if (isShutdown()) {
        reject();
    }
    //该处可以看到是把这个任务放到了任务队列(阻塞队列)中,在默认情况下容量为int的最大值。后续会执行它
    return taskQueue.offer(task);
}

/**
 * SingleThreadEventExecutor:
 * 第631行代码处:
 */
private void startThread() {
    if (state == ST_NOT_STARTED) {
        //CAS操作确保每一个NioEventLoop只会启动一个线程
        if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
            boolean success = false;
            try {
                doStartThread();
                success = true;
            } finally {
                if (!success) {
                    STATE_UPDATER.compareAndSet(this, ST_STARTED, ST_NOT_STARTED);
                }
            }
        }
    }
}

/**
 * 第682行代码处:
 */
private void doStartThread() {
    assert thread == null;
    executor.execute(new Runnable() {
        @Override
        public void run() {
            //这里将this.thread赋值为当前线程,之后再调用inEventLoop方法就返回为true了
            thread = Thread.currentThread();
            if (interrupted) {
                thread.interrupt();
            }

            boolean success = false;
            updateLastExecutionTime();
            try {
                SingleThreadEventExecutor.this.run();
                success = true;
            } catch (Throwable t) {
                logger.warn("Unexpected exception from an event executor: ", t);
            } finally {
                for (; ; ) {
                    int oldState = state;
                    if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                            SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                        break;
                    }
                }

                if (success && gracefulShutdownStartTime == 0) {
                    if (logger.isErrorEnabled()) {
                        logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
                                "be called before run() implementation terminates.");
                    }
                }

                try {
                    for (; ; ) {
                        if (confirmShutdown()) {
                            break;
                        }
                    }

                    for (; ; ) {
                        int oldState = state;
                        if (oldState >= ST_SHUTDOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTDOWN)) {
                            break;
                        }
                    }

                    confirmShutdown();
                } finally {
                    try {
                        cleanup();
                    } finally {
                        FastThreadLocal.removeAll();

                        STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                        threadLock.countDown();
                        int numUserTasks = drainTasks();
                        if (numUserTasks > 0 && logger.isWarnEnabled()) {
                            logger.warn("An event executor terminated with " +
                                    "non-empty task queue (" + numUserTasks + ')');
                        }
                        terminationFuture.setSuccess(null);
                    }
                }
            }
        }
    });
}

/**
 * NioEventLoop:
 * 第710行代码处:
 * (注:以下的代码应该算是Netty中比较核心的代码了。但可惜的是,该代码的可读性非常差,嵌套了
 * 大量的try-catch和if-else。我查阅了该处代码的初始几次提交者是Trustin Lee(Netty原作者)
 * 和Norman Maurer,那个时候的run方法就已经嵌套了很多的if-else了-_-我能想到这里需要考虑
 * 很多复杂的场景,但是应该会有一种更好的实现方式)
 */
@Override
protected void run() {
    int selectCnt = 0;
    //这里的死循环也就是在Netty线程模型图中,NioEventLoop画圈循环执行的含义
    for (; ; ) {
        try {
            int strategy;
            try {
                strategy = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());
                //下面的代码就可以理解为在NIO编程中处理各种事件的代码
                switch (strategy) {
                    case SelectStrategy.CONTINUE:
                        continue;

                    case SelectStrategy.BUSY_WAIT:

                    case SelectStrategy.SELECT:
                        long curDeadlineNanos = nextScheduledTaskDeadlineNanos();
                        if (curDeadlineNanos == -1L) {
                            curDeadlineNanos = NONE;
                        }
                        nextWakeupNanos.set(curDeadlineNanos);
                        try {
                            if (!hasTasks()) {
                                strategy = select(curDeadlineNanos);
                            }
                        } finally {
                            nextWakeupNanos.lazySet(AWAKE);
                        }
                    default:
                }
            } catch (IOException e) {
                rebuildSelector0();
                selectCnt = 0;
                handleLoopException(e);
                continue;
            }

            selectCnt++;
            cancelledKeys = 0;
            needsToSelectAgain = false;
            final int ioRatio = this.ioRatio;
            boolean ranTasks;
            if (ioRatio == 100) {
                try {
                    if (strategy > 0) {
                        processSelectedKeys();
                    }
                } finally {
                    ranTasks = runAllTasks();
                }
            } else if (strategy > 0) {
                final long ioStartTime = System.nanoTime();
                try {
                    processSelectedKeys();
                } finally {
                    final long ioTime = System.nanoTime() - ioStartTime;
                    ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                }
            } else {
                ranTasks = runAllTasks(0);
            }

            if (ranTasks || strategy > 0) {
                if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS && logger.isDebugEnabled()) {
                    logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",
                            selectCnt - 1, selector);
                }
                selectCnt = 0;
            } else if (unexpectedSelectorWakeup(selectCnt)) {
                selectCnt = 0;
            }
        } catch (CancelledKeyException e) {
            if (logger.isDebugEnabled()) {
                logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?",
                        selector, e);
            }
        } catch (Throwable t) {
            handleLoopException(t);
        }
        try {
            if (isShuttingDown()) {
                closeAll();
                if (confirmShutdown()) {
                    return;
                }
            }
        } catch (Throwable t) {
            handleLoopException(t);
        }
    }
}

/**
 * 第800行代码处:
 * 这里也就是在Netty线程模型图中NioEventLoop循环所做的第一件事:select
 */
private int select(long deadlineNanos) throws IOException {
    if (deadlineNanos == NONE) {
        /*
        可以看到这里就是在调用NIO编程中的select方法,如果没有客户端来的时候,本方法会一直阻塞在这里
        (从这里又可以再一次看出:Netty就是对NIO的一种复杂封装,但是使用起来会很简单)
         */
        return selector.select();
    }
    long timeoutMillis = deadlineToDelayNanos(deadlineNanos + 995000L) / 1000000L;
    //这里会调用NIO编程中有时间限制的select方法
    return timeoutMillis <= 0 ? selector.selectNow() : selector.select(timeoutMillis);
}

/**
 * 第822行和第830行代码处:
 * 这里也就是在Netty线程模型图中NioEventLoop循环所做的第二件事:processSelectedKeys
 * 跟NIO编程一样,如果有事件来临的时候,会把该事件放在selectedKeys集合中,也就会执行本方法
 * 如果没有事件来临,该方法不会被调用
 * (注:我建议processSelectedKey方法放在最后再看、等服务端走完所有的流程后再看比较好
 * 现在可以先过掉这个方法,直接去看第三件事:runAllTasks方法的实现。因为processSelectedKey
 * 方法本身就是服务端初始化完成后,客户端发起事件时才会调用的方法。如果现在就看下面的分析的话,
 * 可能有些东西会不理解(我下面对processSelectedKeys方法的分析也是建立在看完了服务端所有初始化
 * 流程后的基础上,再进行分析的))
 */
private void processSelectedKeys() {
    /*
    在之前NioEventLoopGroup的构造器中,已经对selectedKeys进行了初始化,所以这里会走
    processSelectedKeysOptimized方法中
     */
    if (selectedKeys != null) {
        processSelectedKeysOptimized();
    } else {
        processSelectedKeysPlain(selector.selectedKeys());
    }
}

/**
 * 第903行代码处:
 */
private void processSelectedKeysOptimized() {
    for (int i = 0; i < selectedKeys.size; ++i) {
        //处理集合中的每一个selectedKey
        final SelectionKey k = selectedKeys.keys[i];
        selectedKeys.keys[i] = null;

        final Object a = k.attachment();

        if (a instanceof AbstractNioChannel) {
            processSelectedKey(k, (AbstractNioChannel) a);
        } else {
            @SuppressWarnings("unchecked")
            NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
            processSelectedKey(k, task);
        }

        if (needsToSelectAgain) {
            selectedKeys.reset(i + 1);

            selectAgain();
            i = -1;
        }
    }
}

/**
 * 第921行代码处:
 */
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
    final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
    if (!k.isValid()) {
        final EventLoop eventLoop;
        try {
            eventLoop = ch.eventLoop();
        } catch (Throwable ignored) {
            return;
        }
        if (eventLoop == this) {
            unsafe.close(unsafe.voidPromise());
        }
        return;
    }

    try {
        int readyOps = k.readyOps();
        //处理OP_CONNECT事件
        if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
            int ops = k.interestOps();
            ops &= ~SelectionKey.OP_CONNECT;
            k.interestOps(ops);

            unsafe.finishConnect();
        }

        //处理OP_WRITE事件
        if ((readyOps & SelectionKey.OP_WRITE) != 0) {
            ch.unsafe().forceFlush();
        }

        //处理OP_READ或OP_ACCEPT事件
        if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
            /*
            这里来着重研究一下read方法(OP_ACCEPT事件是客户端连接服务端传来的事件,
            而OP_READ表示服务端和客户端收到彼此传来的读事件)
             */
            unsafe.read();
        }
    } catch (CancelledKeyException ignored) {
        unsafe.close(unsafe.voidPromise());
    }
}

/**
 * AbstractNioMessageChannel:
 * 第977行代码处:
 * 假设当前是客户端连接服务端传来的OP_ACCEPT事件
 */
@Override
public void read() {
    assert eventLoop().inEventLoop();
    final ChannelConfig config = config();
    /*
    重点:这里获取到的pipeline是NioServerSocketChannel的pipeline,
    也就是在之前第323行和第1682行代码处,往这个pipeline中添加了ServerBootstrapAcceptor
     */
    final ChannelPipeline pipeline = pipeline();
    final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    allocHandle.reset(config);

    boolean closed = false;
    Throwable exception = null;
    try {
        try {
            do {
                int localRead = doReadMessages(readBuf);
                if (localRead == 0) {
                    break;
                }
                if (localRead < 0) {
                    closed = true;
                    break;
                }

                allocHandle.incMessagesRead(localRead);
            } while (allocHandle.continueReading());
        } catch (Throwable t) {
            exception = t;
        }

        int size = readBuf.size();
        for (int i = 0; i < size; i++) {
            readPending = false;
            pipeline.fireChannelRead(readBuf.get(i));
        }
        readBuf.clear();
        allocHandle.readComplete();
        pipeline.fireChannelReadComplete();

        if (exception != null) {
            closed = closeOnReadError(exception);

            pipeline.fireExceptionCaught(exception);
        }

        if (closed) {
            inputShutdown = true;
            if (isOpen()) {
                close(voidPromise());
            }
        }
    } finally {
        if (!readPending && !config.isAutoRead()) {
            removeReadOp();
        }
    }
}

/**
 * NioServerSocketChannel:
 * 第1006行代码处:
 */
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
    SocketChannel ch = SocketUtils.accept(javaChannel());

    try {
        if (ch != null) {
            /*
            把当前客户端的NioSocketChannel加入到readBuf中(之前分析过,NioSocketChannel
            构造器中会把OP_READ事件赋值进去,并且配置为非阻塞)
             */
            buf.add(new NioSocketChannel(this, ch));
            return 1;
        }
    } catch (Throwable t) {
        logger.warn("Failed to create a new channel from an accepted socket.", t);

        try {
            ch.close();
        } catch (Throwable t2) {
            logger.warn("Failed to close a socket.", t2);
        }
    }

    return 0;
}

/**
 * SocketUtils:
 * 第1055行代码处:
 */
public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException {
    try {
        return AccessController.doPrivileged(new PrivilegedExceptionAction<SocketChannel>() {
            @Override
            public SocketChannel run() throws IOException {
                /*
                这里也就是在NIO编程中,ServerSocketChannel调用accept方法
                调用完之后,客户端的channel就已经连接起来了
                 */
                return serverSocketChannel.accept();
            }
        });
    } catch (PrivilegedActionException e) {
        throw (IOException) e.getCause();
    }
}

/**
 * DefaultChannelPipeline:
 * 第1024行代码处:
 */
@Override
public final ChannelPipeline fireChannelRead(Object msg) {
    AbstractChannelHandlerContext.invokeChannelRead(head, msg);
    return this;
}

/**
 * AbstractChannelHandlerContext:
 */
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
    final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
    EventExecutor executor = next.executor();
    //同上,inEventLoop方法会返回true
    if (executor.inEventLoop()) {
        next.invokeChannelRead(m);
    } else {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelRead(m);
            }
        });
    }
}

/**
 * 第1118行代码处:
 */
private void invokeChannelRead(Object msg) {
    if (invokeHandler()) {
        try {
            //这里也就是在执行每一个inboundHandler的read事件(以下以HeadContext为例来看一下执行过程)
            ((ChannelInboundHandler) handler()).channelRead(this, msg);
        } catch (Throwable t) {
            invokeExceptionCaught(t);
        }
    } else {
        fireChannelRead(msg);
    }
}

/**
 * DefaultChannelPipeline:
 * 第1136行代码处:
 */
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    //可以看到HeadContext的channelRead事件没有做什么事,只是调用了下一个handler的channelRead事件
    ctx.fireChannelRead(msg);
}

/**
 * AbstractChannelHandlerContext:
 */
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
    /*
    如上面对pipeline的解释,这里拿到的下一个inboundHandler其实是之前添加的ServerBootstrapAcceptor,
    所以接下来就来看一下它的channelRead的实现
     */
    invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
    return this;
}

/**
 * ServerBootstrap:
 */
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    //这里传进来的msg就是上面第1063行代码处赋值进去的NioSocketChannel
    final Channel child = (Channel) msg;

    /*
    addLast方法之前已经分析过了,这里也就是把我们在服务端自定义的childHandler
    放到了NioSocketChannel的pipeline中
     */
    child.pipeline().addLast(childHandler);

    setChannelOptions(child, childOptions, logger);
    setAttributes(child, childAttrs);

    try {
        /*
        这里的register方法非常重要(之前已经分析过该方法的实现了),这里的作用也就是注册
        NioSocketChannel到workerGroup的selector上,同时开启一个线程在select方法处被阻塞,
        后续客户端的读写事件都会交由workerGroup来进行处理。也就是在Netty线程模型图中,
        bossGroup和workerGroup中间连接的那条线的含义

        同时,在之前register方法的分析中,我们知道它最终会回调我们自定义childHandler中的
        ChannelInitializer中的的initChannel方法:也就是将我们自己写的所有handler都放到
        workerGroup的pipeline中
         */
        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);
    }
}

/**
 * AbstractNioByteChannel:
 * 第977行代码处:
 * 当执行完AbstractNioMessageChannel的read方法后,也就是客户端和服务端成功连接上了之后,
 * 这个时候如果客户端有事件来临的时候,就会触发OP_READ事件,也就是会调用本方法
 */
@Override
public final void read() {
    final ChannelConfig config = config();
    if (shouldBreakReadReady(config)) {
        clearReadPending();
        return;
    }
    //同上面的解释,这个时候拿到的pipeline就是workerGroup的pipeline,也就是里面装载着我们自己写的handler
    final ChannelPipeline pipeline = pipeline();
    final ByteBufAllocator allocator = config.getAllocator();
    final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
    allocHandle.reset(config);

    ByteBuf byteBuf = null;
    boolean close = false;
    try {
        do {
            //分配一个直接内存byteBuf
            byteBuf = allocHandle.allocate(allocator);
            //byteBuf此时就存着客户端写过来的数据
            allocHandle.lastBytesRead(doReadBytes(byteBuf));
            if (allocHandle.lastBytesRead() <= 0) {
                byteBuf.release();
                byteBuf = null;
                close = allocHandle.lastBytesRead() < 0;
                if (close) {
                    readPending = false;
                }
                break;
            }

            allocHandle.incMessagesRead(1);
            readPending = false;
            /*
            此时就会拿着客户端写过来的数据在服务端我们自定义的handler中,遍历地去执行channelRead方法
            至此整个流程就打通了
             */
            pipeline.fireChannelRead(byteBuf);
            byteBuf = null;
        } while (allocHandle.continueReading());

        allocHandle.readComplete();
        //fireChannelRead方法执行完毕后,会遍历去执行channelReadComplete方法
        pipeline.fireChannelReadComplete();

        if (close) {
            closeOnRead(pipeline);
        }
    } catch (Throwable t) {
        handleReadException(pipeline, byteBuf, t, close, allocHandle);
    } finally {
        if (!readPending && !config.isAutoRead()) {
            removeReadOp();
        }
    }
}

/**
 * SingleThreadEventExecutor:
 * 第825行代码处:
 * 这里也就是在Netty线程模型图中NioEventLoop循环所做的第三件事:runAllTasks,也就是执行taskQueue中的任务
 */
protected boolean runAllTasks() {
    assert inEventLoop();
    boolean fetchedAll;
    boolean ranAtLeastOne = false;

    //do-while循环确保执行完所有taskQueue中的任务
    do {
        fetchedAll = fetchFromScheduledTaskQueue();
        //执行taskQueue中的所有任务
        if (runAllTasksFrom(taskQueue)) {
            ranAtLeastOne = true;
        }
    } while (!fetchedAll);

    if (ranAtLeastOne) {
        lastExecutionTime = ScheduledFutureTask.nanoTime();
    }
    //钩子方法,空实现
    afterRunningAllTasks();
    return ranAtLeastOne;
}

/**
 * SingleThreadEventExecutor:
 * 第833行和第836行代码处:
 * 这里也就是在Netty线程模型图中NioEventLoop循环所做的第三件事:runAllTasks,也就是执行taskQueue中的任务
 * (本方法是上面方法的重载方法,需要考虑定时任务超时的问题)
 * (注:这两个方法为什么不考虑封装成一个公有的抽象,然后使用类似模板方法模式来进行不同的实现?)
 */
protected boolean runAllTasks(long timeoutNanos) {
    fetchFromScheduledTaskQueue();
    Runnable task = pollTask();
    if (task == null) {
        //钩子方法,空实现
        afterRunningAllTasks();
        return false;
    }

    final long deadline = timeoutNanos > 0 ? ScheduledFutureTask.nanoTime() + timeoutNanos : 0;
    long runTasks = 0;
    long lastExecutionTime;
    for (; ; ) {
        safeExecute(task);

        runTasks++;

        //每执行64个任务后获取一下当前时间,看是否已经超时了(因为nanoTime的获取也会有消耗,所以不是一个任务一次调用)
        if ((runTasks & 0x3F) == 0) {
            lastExecutionTime = ScheduledFutureTask.nanoTime();
            if (lastExecutionTime >= deadline) {
                break;
            }
        }

        task = pollTask();
        if (task == null) {
            lastExecutionTime = ScheduledFutureTask.nanoTime();
            break;
        }
    }

    //钩子方法,空实现
    afterRunningAllTasks();
    this.lastExecutionTime = lastExecutionTime;
    return true;
}

/**
 * 第1285行和第1308行代码处:
 * 这里需要说一下前提:除了taskQueue之外还有一个scheduledTaskQueue的定时任务队列。当taskQueue存满了的时候,
 * 会将剩下的任务存放进scheduledTaskQueue中。所以本方法的执行,达到的效果就是取出scheduledTaskQueue中的
 * 任务再放回到taskQueue,直到taskQueue再次存满为止
 */
private boolean fetchFromScheduledTaskQueue() {
    //如果scheduledTaskQueue本身就是空的,就直接返回true
    if (scheduledTaskQueue == null || scheduledTaskQueue.isEmpty()) {
        return true;
    }
    long nanoTime = AbstractScheduledEventExecutor.nanoTime();
    for (; ; ) {
        //从scheduledTaskQueue中拿走队头任务
        Runnable scheduledTask = pollScheduledTask(nanoTime);
        //如果scheduledTask是空的,说明scheduledTaskQueue中已经没有了任务(或者超时了),就直接返回true
        if (scheduledTask == null) {
            return true;
        }
        if (!taskQueue.offer(scheduledTask)) {
            /*
            将从scheduledTaskQueue中拿出的任务再次放到taskQueue中,循环这一过程。如果taskQueue满了放不下的话,
            就把这一次拿出的任务再次放回到scheduledTaskQueue中,并返回false
             */
            scheduledTaskQueue.add((ScheduledFutureTask<?>) scheduledTask);
            return false;
        }
    }
}

/**
 * AbstractScheduledEventExecutor:
 * 第1359行代码处:
 * 从scheduledTaskQueue中拿走队头任务
 */
protected final Runnable pollScheduledTask(long nanoTime) {
    assert inEventLoop();

    ScheduledFutureTask<?> scheduledTask = peekScheduledTask();
    if (scheduledTask == null || scheduledTask.deadlineNanos() - nanoTime > 0) {
        return null;
    }
    //如果peek获取的任务不为空或者没超时,就删除掉它,相当于拿走队头任务了
    scheduledTaskQueue.remove();
    scheduledTask.setConsumed();
    return scheduledTask;
}

/**
 * 第1383行代码处:
 */
final ScheduledFutureTask<?> peekScheduledTask() {
    Queue<ScheduledFutureTask<?>> scheduledTaskQueue = this.scheduledTaskQueue;
    //从scheduledTaskQueue中获取队头任务
    return scheduledTaskQueue != null ? scheduledTaskQueue.peek() : null;
}

/**
 * SingleThreadEventExecutor:
 * 第1287行代码处:
 */
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
    //拿取taskQueue中的一个任务
    Runnable task = pollTaskFrom(taskQueue);
    //如果任务为null,就直接返回false,说明此时taskQueue中已经没有任务了,也就不需要执行了
    if (task == null) {
        return false;
    }
    for (; ; ) {
        //执行任务
        safeExecute(task);
        //执行完一个任务后继续拿取taskQueue中的下一个任务去执行,死循环确保重复这一过程
        task = pollTaskFrom(taskQueue);
        //如果任务为null,就直接返回true,说明此时taskQueue中已经没有任务了
        if (task == null) {
            return true;
        }
    }
}

/**
 * 第1309行和第1332行代码处:
 */
protected Runnable pollTask() {
    assert inEventLoop();
    return pollTaskFrom(taskQueue);
}

/**
 * 第1408行、第1417行和第1430行代码处:
 */
protected static Runnable pollTaskFrom(Queue<Runnable> taskQueue) {
    for (; ; ) {
        //拿走taskQueue中的队头任务,如果为空任务就继续拿取下一个,直到不为空为止
        Runnable task = taskQueue.poll();
        if (task != WAKEUP_TASK) {
            return task;
        }
    }
}

/**
 * AbstractEventExecutor:
 * 第1320行和第1415行代码处:
 */
protected static void safeExecute(Runnable task) {
    try {
        /*
        这里也就是在真正执行任务的地方。现在已经搞清楚了任务是如何启动去执行的,而之前在register注册的时候
        放入了一个注册任务,那么下面就来看一下这个任务具体的执行代码
         */
        task.run();
    } catch (Throwable t) {
        logger.warn("A task raised an exception. Task: {}", task, t);
    }
}

/**
 * AbstractChannel:
 * 第580行代码处:
 */
private void register0(ChannelPromise promise) {
    try {
        if (!promise.setUncancellable() || !ensureOpen(promise)) {
            return;
        }
        boolean firstRegistration = neverRegistered;
        doRegister();
        neverRegistered = false;
        registered = true;

        pipeline.invokeHandlerAddedIfNeeded();

        safeSetSuccess(promise);
        pipeline.fireChannelRegistered();
        if (isActive()) {
            if (firstRegistration) {
                pipeline.fireChannelActive();
            } else if (config().isAutoRead()) {
                beginRead();
            }
        }
    } catch (Throwable t) {
        closeForcibly();
        closeFuture.setClosed();
        safeSetFailure(promise, t);
    }
}

/**
 * AbstractNioChannel:
 * 第1472行代码处:
 */
@Override
protected void doRegister() throws Exception {
    boolean selected = false;
    for (; ; ) {
        try {
            //这行话其实就对应于NIO编程中把ServerSocketChannel或SocketChannel注册到selector上
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
            return;
        } catch (CancelledKeyException e) {
            if (!selected) {
                eventLoop().selectNow();
                selected = true;
            } else {
                throw e;
            }
        }
    }
}

/**
 * DefaultChannelPipeline:
 * 第1476行代码处:
 */
final void invokeHandlerAddedIfNeeded() {
    assert channel.eventLoop().inEventLoop();
    if (firstRegistration) {
        firstRegistration = false;
        //之前说过,当channel被注册时会回调initChannel方法,所以这里就是在做这件事
        callHandlerAddedForAllHandlers();
    }
}

private void callHandlerAddedForAllHandlers() {
    final PendingHandlerCallback pendingHandlerCallbackHead;
    synchronized (this) {
        assert !registered;

        registered = true;

        pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
        this.pendingHandlerCallbackHead = null;
    }

    PendingHandlerCallback task = pendingHandlerCallbackHead;
    while (task != null) {
        task.execute();
        task = task.next;
    }
}

/**
 * 第1543行代码处:
 */
@Override
void execute() {
    EventExecutor executor = ctx.executor();
    //inEventLoop方法在之前第702行代码处的doStartThread方法里面已经对thread赋值成当前线程了,所以这里肯定返回true
    if (executor.inEventLoop()) {
        callHandlerAdded0(ctx);
    } else {
        try {
            executor.execute(this);
        } catch (RejectedExecutionException e) {
            if (logger.isWarnEnabled()) {
                logger.warn(
                        "Can't invoke handlerAdded() as the EventExecutor {} rejected it, removing handler {}.",
                        executor, ctx.name(), e);
            }
            atomicRemoveFromHandlerList(ctx);
            ctx.setRemoved();
        }
    }
}

/**
 * 第1556行代码处:
 */
private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) {
    try {
        ctx.callHandlerAdded();
    } catch (Throwable t) {
        boolean removed = false;
        try {
            atomicRemoveFromHandlerList(ctx);
            ctx.callHandlerRemoved();
            removed = true;
        } catch (Throwable t2) {
            if (logger.isWarnEnabled()) {
                logger.warn("Failed to remove a handler: " + ctx.name(), t2);
            }
        }

        if (removed) {
            fireExceptionCaught(new ChannelPipelineException(
                    ctx.handler().getClass().getName() +
                            ".handlerAdded() has thrown an exception; removed.", t));
        } else {
            fireExceptionCaught(new ChannelPipelineException(
                    ctx.handler().getClass().getName() +
                            ".handlerAdded() has thrown an exception; also failed to remove.", t));
        }
    }
}

/**
 * AbstractChannelHandlerContext:
 * 第1577行代码处:
 */
final void callHandlerAdded() throws Exception {
    if (setAddComplete()) {
        /*
        这里获取的handler正是之前第414行代码处,调用DefaultChannelHandlerContext构造器
        赋值进去的ChannelInitializer
         */
        handler().handlerAdded(this);
    }
}

/**
 * ChannelInitializer:
 */
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
    if (ctx.channel().isRegistered()) {
        if (initChannel(ctx)) {

            removeState(ctx);
        }
    }
}

/**
 * 第1622行代码处:
 */
@SuppressWarnings("unchecked")
private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
    if (initMap.add(ctx)) {
        try {
            //这里就是回调之前在第313行代码处的initChannel方法,下面就来看一下该方法的实现过程
            initChannel((C) ctx.channel());
        } catch (Throwable cause) {
            exceptionCaught(ctx, cause);
        } finally {
            ChannelPipeline pipeline = ctx.pipeline();
            //这里就可以看到当执行完initChannel方法后会删除当前ChannelInitializer实例
            if (pipeline.context(this) != null) {
                pipeline.remove(this);
            }
        }
        return true;
    }
    return false;
}

/**
 * ServerBootstrap:
 * 第313行代码处:
 * 为了延续一路分析下来的顺序,这里将之前initChannel回调方法的具体代码重新拷贝了一份放在下面,
 * 以此来连贯分析其具体执行过程
 */
@Override
public void initChannel(final Channel ch) {
    final ChannelPipeline pipeline = ch.pipeline();
    //因为我们之前调用ServerBootstrap和Bootstrap的构造器都是空实现,所以这里获取到的handler也是null
    ChannelHandler handler = config.handler();
    if (handler != null) {
        pipeline.addLast(handler);
    }

    /*
    这里又调用了一次execute方法,将任务放到taskQueue中,然后等待runAllTasks方法去执行
    之前在第621行代码处已经分析了其具体执行过程,这里就不再次重复分析了
     */
    ch.eventLoop().execute(new Runnable() {
        @Override
        public void run() {
            /*
            addLast方法在之前的第352行代码处也已经分析过了,将ChannelHandler添加进pipeline中
            只不过之前添加的是ChannelInitializer,而这里添加的是ServerBootstrapAcceptor
            (添加之后ChannelInitializer的initChannel方法就走完了,然后在上面的第1644行代码处
            可以看到,会从pipeline中删除当前ChannelInitializer实例,所以目前服务端的pipeline
            中除了tail和head之外,就只剩下了ServerBootstrapAcceptor(需要注意的是:添加
            ServerBootstrapAcceptor是在另一个线程中完成的,主线程不一定能及时感知到这个变化))
             */
            pipeline.addLast(new ServerBootstrapAcceptor(
                    ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
        }
    });
    /*
    目前这条线就算是走完了,再来回到最开始的地方,即第1476行代码处.我们刚才所有的分析都是从
    invokeHandlerAddedIfNeeded方法里面进行展开的,现在该方法走完了,就继续走接下来的代码
     */
}

/**
 * DefaultChannelPipeline:
 * 第1479行代码处:
 * 该方法实现的就是通过遍历pipeline中的每一个inboundHandler,执行其channelRegistered方法
 */
@Override
public final ChannelPipeline fireChannelRegistered() {
    AbstractChannelHandlerContext.invokeChannelRegistered(head);
    return this;
}

/**
 * AbstractChannelHandlerContext:
 */
static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {
    EventExecutor executor = next.executor();
    //同上,inEventLoop方法会返回true
    if (executor.inEventLoop()) {
        next.invokeChannelRegistered();
    } else {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelRegistered();
            }
        });
    }
}

/**
 * 第1710行代码处:
 */
private void invokeChannelRegistered() {
    //该方法返回true
    if (invokeHandler()) {
        try {
            ((ChannelInboundHandler) handler()).channelRegistered(this);
        } catch (Throwable t) {
            invokeExceptionCaught(t);
        }
    } else {
        fireChannelRegistered();
    }
}

/**
 * DefaultChannelPipeline:
 * 第1728行代码处:
 * 因为传进来的是head,所以这里调用的是HeadContext的channelRegistered方法
 */
@Override
public void channelRegistered(ChannelHandlerContext ctx) {
    /*
    invokeHandlerAddedIfNeeded方法之前已经分析过了,但是这里并不会具体执行后续的
    callHandlerAddedForAllHandlers,因为在之前的调用过程中已经把firstRegistration
    置为false了,详见第1524行代码处。所以这里不会再调用了,相当于是个空方法
     */
    invokeHandlerAddedIfNeeded();
    /*
    这里是调用下一个inboundHandler的channelRegistered方法。如果是TailContext的话,就会去执行
    它的channelRegistered方法。但是TailContext的channelRegistered方法是一个空实现,所以这里
    就不再具体展开分析了,调用的流程都是和HeadContext类似的
     */
    ctx.fireChannelRegistered();
}

/**
 * AbstractChannelHandlerContext:
 * 第1755行代码处:
 */
@Override
public ChannelHandlerContext fireChannelRegistered() {
    /*
    因为这里是调用channelRegistered事件,站在服务端的角度来说相当于入站事件
    所以当通过findContextInbound方法拿到下一个inboundHandler时候,就调用
    它的channelRegistered方法
     */
    invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));
    return this;
}

/**
 * 该方法就是用来找到下一个执行注册动作的inboundHandler
 */
private AbstractChannelHandlerContext findContextInbound(int mask) {
    AbstractChannelHandlerContext ctx = this;
    EventExecutor currentExecutor = executor();
    do {
        ctx = ctx.next;
    } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_INBOUND));
    return ctx;
}

/**
 * 如果返回true,则代表当前handler是需要跳过的。比如当前需要剔除outBoundHandler,那么传进来的
 * onlyMask就是MASK_ONLY_INBOUND,当遇到一个outBoundHandler的时候,本方法就会返回true;
 * 当遇到一个inboundHandler的时候,本方法就会返回false
 */
private static boolean skipContext(
        AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask) {
    return (ctx.executionMask & (onlyMask | mask)) == 0 ||
            (ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0);
}

/**
 * AbstractBootstrap:
 * 第14行代码处:
 * 上面所有的分析都是在分析initAndRegister这个方法,现在我们来接着分析在这之后的代码,
 * 首先是服务端的doBind方法。为了延续一路分析下来的顺序,这里将之前doBind方法的具体代码
 * 重新拷贝了一份放在下面,以此来连贯分析其具体执行过程
 */
private ChannelFuture doBind(final SocketAddress localAddress) {
    //之前已经分析了initAndRegister方法的具体执行过程
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();
    if (regFuture.cause() != null) {
        return regFuture;
    }

    //该方法会返回false
    if (regFuture.isDone()) {
        ChannelPromise promise = channel.newPromise();
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
        regFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Throwable cause = future.cause();
                if (cause != null) {
                    promise.setFailure(cause);
                } else {
                    promise.registered();

                    //这里也就是在做绑定端口的工作
                    doBind0(regFuture, channel, localAddress, promise);
                }
            }
        });
        return promise;
    }
}

/**
 * AbstractBootstrap:
 */
private static void doBind0(
        final ChannelFuture regFuture, final Channel channel,
        final SocketAddress localAddress, final ChannelPromise promise) {

    //之前已经分析过了,看到“eventLoop().execute”这行代码就知道是创建了一个新任务放到了taskQueue中
    channel.eventLoop().execute(new Runnable() {
        @Override
        public void run() {
            if (regFuture.isSuccess()) {
                channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            } else {
                promise.setFailure(regFuture.cause());
            }
        }
    });
}

/**
 * AbstractChannel:
 * 第1848行代码处:
 */
@Override
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
    /*
    其实这里和channelRegistered事件的执行过程是类似的,都是遍历handler去执行事件,
    但是这里是从tail到head的顺序找出outboundHandler
     */
    return pipeline.bind(localAddress, promise);
}

/**
 * DefaultChannelPipeline:
 */
@Override
public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
    return tail.bind(localAddress, promise);
}

/**
 * AbstractChannelHandlerContext:
 */
@Override
public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
    ObjectUtil.checkNotNull(localAddress, "localAddress");
    if (isNotValidPromise(promise, false)) {
        return promise;
    }

    //这里就是在找下一个执行绑定动作的outboundHandler
    final AbstractChannelHandlerContext next = findContextOutbound(MASK_BIND);
    EventExecutor executor = next.executor();
    //同之前的分析,该方法会返回true
    if (executor.inEventLoop()) {
        next.invokeBind(localAddress, promise);
    } else {
        safeExecute(executor, new Runnable() {
            @Override
            public void run() {
                next.invokeBind(localAddress, promise);
            }
        }, promise, null, false);
    }
    return promise;
}

/**
 * 第1888行代码处:
 * 该方法的代码和findContextInbound方法代码之间的区别除了onlyMask不同之外,还有一点就是
 * findContextInbound方法中是从head到tail依次遍历的;而findContextOutbound方法也就是
 * 本方法中是从tail到head依次遍历的
 */
private AbstractChannelHandlerContext findContextOutbound(int mask) {
    AbstractChannelHandlerContext ctx = this;
    EventExecutor currentExecutor = executor();
    do {
        ctx = ctx.prev;
    } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));
    return ctx;
}

/**
 * 第1892行代码处:
 */
private void invokeBind(SocketAddress localAddress, ChannelPromise promise) {
    if (invokeHandler()) {
        try {
            //这里也就是在执行每一个outboundHandler的bind事件(以下以HeadContext为例来看一下执行过程)
            ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise);
        } catch (Throwable t) {
            notifyOutboundHandlerException(t, promise);
        }
    } else {
        bind(localAddress, promise);
    }
}

/**
 * DefaultChannelPipeline:
 * 第1926行代码处:
 */
@Override
public void bind(
        ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) {
    unsafe.bind(localAddress, promise);
}

/**
 * AbstractChannel:
 */
@Override
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
    assertEventLoop();

    if (!promise.setUncancellable() || !ensureOpen(promise)) {
        return;
    }

    if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) &&
            localAddress instanceof InetSocketAddress &&
            !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() &&
            !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
        logger.warn(
                "A non-root user can't receive a broadcast packet if the socket " +
                        "is not bound to a wildcard address; binding to a non-wildcard " +
                        "address (" + localAddress + ") anyway as requested.");
    }

    boolean wasActive = isActive();
    try {
        doBind(localAddress);
    } catch (Throwable t) {
        safeSetFailure(promise, t);
        closeIfClosed();
        return;
    }

    if (!wasActive && isActive()) {
        invokeLater(new Runnable() {
            @Override
            public void run() {
                //这里看到会从pipeline中依次执行channelActive事件
                pipeline.fireChannelActive();
            }
        });
    }

    safeSetSuccess(promise);
}

/**
 * NioServerSocketChannel:
 * 第1968行代码处:
 */
@SuppressJava6Requirement(reason = "Usage guarded by java version check")
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
    /*
    这里会根据Java不同的版本来执行不同的绑定代码。而看到“javaChannel()”就知道这里会走到NIO编程中的代码里了,
    也就是NIO编程中的绑定端口的代码
     */
    if (PlatformDependent.javaVersion() >= 7) {
        javaChannel().bind(localAddress, config.getBacklog());
    } else {
        javaChannel().socket().bind(localAddress, config.getBacklog());
    }
}

/**
 * AbstractChannel:
 * 第1976行代码处:
 * 该方法就是把任务放到taskQueue中
 */
private void invokeLater(Runnable task) {
    try {
        eventLoop().execute(task);
    } catch (RejectedExecutionException e) {
        logger.warn("Can't invoke task later as EventLoop rejected it", e);
    }
}

/**
 * DefaultChannelPipeline:
 * 第1980行代码处:
 */
@Override
public final ChannelPipeline fireChannelActive() {
    //这里和channelRegistered事件的执行过程是类似的,从pipeline中head到tail执行所有的inboundHandler
    AbstractChannelHandlerContext.invokeChannelActive(head);
    return this;
}

/**
 * AbstractChannelHandlerContext:
 */
static void invokeChannelActive(final AbstractChannelHandlerContext next) {
    EventExecutor executor = next.executor();
    //同之前的分析,该方法会返回true
    if (executor.inEventLoop()) {
        next.invokeChannelActive();
    } else {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelActive();
            }
        });
    }
}

/**
 * 第2037行代码处:
 */
private void invokeChannelActive() {
    if (invokeHandler()) {
        try {
            //这里也就是在执行每一个inboundHandler的active事件(以下以HeadContext为例来看一下执行过程)
            ((ChannelInboundHandler) handler()).channelActive(this);
        } catch (Throwable t) {
            invokeExceptionCaught(t);
        }
    } else {
        fireChannelActive();
    }
}

/**
 * DefaultChannelPipeline:
 * 第2055行代码处:
 * 因为传进来的是head,所以这里调用的是HeadContext的channelActive方法
 */
@Override
public void channelActive(ChannelHandlerContext ctx) {
    /*
    这里是调用下一个inboundHandler的channelActive方法。如果是TailContext的话,就会去执行
    它的channelActive方法。但是TailContext的channelActive方法是一个空实现,所以这里
    就不再具体展开分析了,调用的流程都是和HeadContext类似的
     */
    ctx.fireChannelActive();

    readIfIsAutoRead();
}

/**
 * AbstractChannelHandlerContext:
 * 第2076行代码处:
 */
@Override
public ChannelHandlerContext fireChannelActive() {
    /*
    因为这里是调用channelActive事件,站在服务端的角度来说相当于入站事件
    所以当通过findContextInbound方法拿到下一个inboundHandler时候,就调用
    它的channelActive方法
     */
    invokeChannelActive(findContextInbound(MASK_CHANNEL_ACTIVE));
    return this;
}

/**
 * AbstractNioChannel:
 * 第2078行代码处:
 * readIfIsAutoRead方法中又会从pipeline中从tail到head遍历执行所有outboundHandler的读事件,
 * 之前已经分析过很多这样的流程了,这里就不再赘述了。所以下面就来看一下其中的关键代码:doBeginRead
 */
@Override
protected void doBeginRead() throws Exception {
    final SelectionKey selectionKey = this.selectionKey;
    if (!selectionKey.isValid()) {
        return;
    }

    readPending = true;

    final int interestOps = selectionKey.interestOps();
    if ((interestOps & readInterestOp) == 0) {
        /*
        这里可以看到跟NIO编程中一样,重新注册对OP_ACCEPT(服务端)或OP_READ(客户端)事件感兴趣
        (详见之前的第162行和第220行代码处)
         */
        selectionKey.interestOps(interestOps | readInterestOp);
    }
}

/**
 * Bootstrap:
 * 第59行代码处:
 * 分析完服务端的doBind方法后,现在来分析一下客户端的doResolveAndConnect方法
 */
private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
    //之前已经分析了initAndRegister方法的具体执行过程
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();

    if (regFuture.isDone()) {
        if (!regFuture.isSuccess()) {
            return regFuture;
        }
        return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
    } else {
        final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
        regFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Throwable cause = future.cause();
                if (cause != null) {
                    promise.setFailure(cause);
                } else {
                    promise.registered();
                    doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
                }
            }
        });
        return promise;
    }
}

private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress,
                                           final SocketAddress localAddress, final ChannelPromise promise) {
    try {
        final EventLoop eventLoop = channel.eventLoop();
        AddressResolver<SocketAddress> resolver;
        try {
            resolver = this.resolver.getResolver(eventLoop);
        } catch (Throwable cause) {
            channel.close();
            return promise.setFailure(cause);
        }

        if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) {
            doConnect(remoteAddress, localAddress, promise);
            return promise;
        }

        final Future<SocketAddress> resolveFuture = resolver.resolve(remoteAddress);

        if (resolveFuture.isDone()) {
            final Throwable resolveFailureCause = resolveFuture.cause();

            if (resolveFailureCause != null) {
                channel.close();
                promise.setFailure(resolveFailureCause);
            } else {
                doConnect(resolveFuture.getNow(), localAddress, promise);
            }
            return promise;
        }

        resolveFuture.addListener(new FutureListener<SocketAddress>() {
            @Override
            public void operationComplete(Future<SocketAddress> future) throws Exception {
                if (future.cause() != null) {
                    channel.close();
                    promise.setFailure(future.cause());
                } else {
                    doConnect(future.getNow(), localAddress, promise);
                }
            }
        });
    } catch (Throwable cause) {
        promise.tryFailure(cause);
    }
    return promise;
}

/**
 * 第2180行代码处:
 */
private static void doConnect(
        final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) {

    final Channel channel = connectPromise.channel();
    //同上,新创建了一个任务放到了taskQueue中
    channel.eventLoop().execute(new Runnable() {
        @Override
        public void run() {
            if (localAddress == null) {
                channel.connect(remoteAddress, connectPromise);
            } else {
                channel.connect(remoteAddress, localAddress, connectPromise);
            }
            connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
        }
    });
}

/**
 * AbstractChannel:
 * 第2214行代码处:
 */
@Override
public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
    return pipeline.connect(remoteAddress, promise);
}

/**
 * DefaultChannelPipeline:
 */
@Override
public final ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
    /*
    不出意外的话,又是从pipeline中从tail到head遍历执行所有outboundHandler的connect事件
    (注:既然有这么多pipeline中inbound、outbound的遍历执行的地方,为什么不抽象成两个公有的实现?
    通过传入不同的事件来实现不同的功能?)
     */
    return tail.connect(remoteAddress, promise);
}

/**
 * AbstractChannelHandlerContext:
 */
@Override
public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
    return connect(remoteAddress, null, promise);
}

@Override
public ChannelFuture connect(
        final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
    ObjectUtil.checkNotNull(remoteAddress, "remoteAddress");

    if (isNotValidPromise(promise, false)) {
        return promise;
    }

    //这里就是在找下一个执行连接动作的outboundHandler
    final AbstractChannelHandlerContext next = findContextOutbound(MASK_CONNECT);
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        next.invokeConnect(remoteAddress, localAddress, promise);
    } else {
        safeExecute(executor, new Runnable() {
            @Override
            public void run() {
                next.invokeConnect(remoteAddress, localAddress, promise);
            }
        }, promise, null, false);
    }
    return promise;
}

/**
 * 第2266行代码处:
 */
private void invokeConnect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
    if (invokeHandler()) {
        try {
            //这里也就是在执行每一个outboundHandler的connect事件(以下以HeadContext为例来看一下执行过程)
            ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise);
        } catch (Throwable t) {
            notifyOutboundHandlerException(t, promise);
        }
    } else {
        connect(remoteAddress, localAddress, promise);
    }
}

/**
 * DefaultChannelPipeline:
 * 第2285行代码处:
 */
@Override
public void connect(
        ChannelHandlerContext ctx,
        SocketAddress remoteAddress, SocketAddress localAddress,
        ChannelPromise promise) {
    unsafe.connect(remoteAddress, localAddress, promise);
}

/**
 * AbstractChannel:
 */
@Override
public final void connect(
        final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
    if (!promise.setUncancellable() || !ensureOpen(promise)) {
        return;
    }

    try {
        if (connectPromise != null) {
            throw new ConnectionPendingException();
        }

        boolean wasActive = isActive();
        if (doConnect(remoteAddress, localAddress)) {
            fulfillConnectPromise(promise, wasActive);
        } else {
            connectPromise = promise;
            requestedRemoteAddress = remoteAddress;

            int connectTimeoutMillis = config().getConnectTimeoutMillis();
            if (connectTimeoutMillis > 0) {
                //这里schedule方法会创建一个定时任务,之前遇到的都是execute方法,所以这里来具体看一下其是怎么实现的
                connectTimeoutFuture = eventLoop().schedule(new Runnable() {
                    @Override
                    public void run() {
                        ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise;
                        ConnectTimeoutException cause =
                                new ConnectTimeoutException("connection timed out: " + remoteAddress);
                        if (connectPromise != null && connectPromise.tryFailure(cause)) {
                            close(voidPromise());
                        }
                    }
                }, connectTimeoutMillis, TimeUnit.MILLISECONDS);
            }

            promise.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isCancelled()) {
                        if (connectTimeoutFuture != null) {
                            connectTimeoutFuture.cancel(false);
                        }
                        connectPromise = null;
                        close(voidPromise());
                    }
                }
            });
        }
    } catch (Throwable t) {
        promise.tryFailure(annotateConnectException(t, remoteAddress));
        closeIfClosed();
    }
}

/**
 * NioSocketChannel:
 * 第2322行代码处:
 */
@Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
    if (localAddress != null) {
        doBind0(localAddress);
    }

    boolean success = false;
    try {
        boolean connected = SocketUtils.connect(javaChannel(), remoteAddress);
        if (!connected) {
            //同NIO编程中一样,为该通道注册OP_CONNECT事件
            selectionKey().interestOps(SelectionKey.OP_CONNECT);
        }
        success = true;
        return connected;
    } finally {
        if (!success) {
            doClose();
        }
    }
}

/**
 * SocketUtils:
 * 第2375行代码处:
 */
public static boolean connect(final SocketChannel socketChannel, final SocketAddress remoteAddress)
        throws IOException {
    try {
        return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
            @Override
            public Boolean run() throws IOException {
                //这里也就是在NIO编程中,客户端连接服务端的代码
                return socketChannel.connect(remoteAddress);
            }
        });
    } catch (PrivilegedActionException e) {
        throw (IOException) e.getCause();
    }
}

/**
 * AbstractScheduledEventExecutor:
 * 第2331行代码处:
 */
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
    ObjectUtil.checkNotNull(command, "command");
    ObjectUtil.checkNotNull(unit, "unit");
    //delay非负处理
    if (delay < 0) {
        delay = 0;
    }
    validateScheduled0(delay, unit);

    return schedule(new ScheduledFutureTask<Void>(
            this,
            command,
            deadlineNanos(unit.toNanos(delay))));
}

private <V> ScheduledFuture<V> schedule(final ScheduledFutureTask<V> task) {
    //同之前的分析,该方法会返回true
    if (inEventLoop()) {
        scheduleFromEventLoop(task);
    } else {
        final long deadlineNanos = task.deadlineNanos();
        if (beforeScheduledTaskSubmitted(deadlineNanos)) {
            execute(task);
        } else {
            lazyExecute(task);
            if (afterScheduledTaskSubmitted(deadlineNanos)) {
                execute(WAKEUP_TASK);
            }
        }
    }

    return task;
}

/**
 * 第2431行代码处:
 */
final void scheduleFromEventLoop(final ScheduledFutureTask<?> task) {
    //这里实际上就是将任务放在了定时任务队列中,后续再去等线程执行runAllTasks方法,把任务拿出来再执行
    scheduledTaskQueue().add(task.setId(++nextTaskId));
}

PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue() {
    if (scheduledTaskQueue == null) {
        scheduledTaskQueue = new DefaultPriorityQueue<ScheduledFutureTask<?>>(
                SCHEDULED_FUTURE_TASK_COMPARATOR,
                11);
    }
    return scheduledTaskQueue;
}

@SuppressWarnings("unchecked")
public DefaultPriorityQueue(Comparator<T> comparator, int initialSize) {
    this.comparator = ObjectUtil.checkNotNull(comparator, "comparator");
    //这里可以看到创建了一个Netty自己定义的优先级队列(继承了java.util.AbstractQueue)
    queue = (T[]) (initialSize != 0 ? new PriorityQueueNode[initialSize] : EMPTY_ARRAY);
}

在执行完上述的所有过程后,运行NioEventLoop类run方法的线程,在没有遇到事件来临的时候,会阻塞在select方法处,直到有事件来临(这和NIO编程中的执行逻辑是一样的)。


4 sync方法

/**
 * DefaultChannelPromise:
 */
@Override
public ChannelPromise sync() throws InterruptedException {
    super.sync();
    return this;
}

/**
 * DefaultPromise:
 */
@Override
public Promise<V> sync() throws InterruptedException {
    await();
    rethrowIfFailed();
    return this;
}

/**
 * DefaultChannelPromise:
 * 第15行代码处:
 */
@Override
public ChannelPromise await() throws InterruptedException {
    super.await();
    return this;
}

/**
 * DefaultPromise:
 */
@Override
public Promise<V> await() throws InterruptedException {
    if (isDone()) {
        return this;
    }

    if (Thread.interrupted()) {
        throw new InterruptedException(toString());
    }

    checkDeadLock();

    synchronized (this) {
        while (!isDone()) {
            incWaiters();
            try {
                /*
                这里就是会让当前线程阻塞住,直到上一个异步操作执行完毕后再被唤醒,也就是“异步转同步”
                比如“bind(9000).sync()”这行代码就是在等待初始化注册和绑定端口工作都做完了以后,当前线程再被唤醒;
                而“closeFuture().sync()”这行代码就是在等待通道关闭、处理完毕后,当前线程再被唤醒
                 */
                wait();
            } finally {
                decWaiters();
            }
        }
    }
    return this;
}

5 writeAndFlush方法

/**
 * AbstractChannel:
 * 这里以服务端向客户端发送数据来举例
 */
@Override
public ChannelFuture writeAndFlush(Object msg) {
    /*
    需要注意的是:这里拿到的pipeline就是在服务端有我们自定义handler的pipeline,
    也就是NioServerSocketChannel的pipeline
     */
    return pipeline.writeAndFlush(msg);
}

/**
 * DefaultChannelPipeline:
 */
@Override
public final ChannelFuture writeAndFlush(Object msg) {
    //因为是出站事件,所以从tail开始遍历所有的outboundHandler
    return tail.writeAndFlush(msg);
}

/**
 * AbstractChannelHandlerContext:
 */
@Override
public ChannelFuture writeAndFlush(Object msg) {
    return writeAndFlush(msg, newPromise());
}

@Override
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
    write(msg, true, promise);
    return promise;
}

private void write(Object msg, boolean flush, ChannelPromise promise) {
    ObjectUtil.checkNotNull(msg, "msg");
    try {
        if (isNotValidPromise(promise, true)) {
            ReferenceCountUtil.release(msg);
            return;
        }
    } catch (RuntimeException e) {
        ReferenceCountUtil.release(msg);
        throw e;
    }

    //这里就是在找下一个执行写动作的outboundHandler
    final AbstractChannelHandlerContext next = findContextOutbound(flush ?
            (MASK_WRITE | MASK_FLUSH) : MASK_WRITE);
    final Object m = pipeline.touch(msg, next);
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        if (flush) {
            //传进来的flush为true,所以走下面的方法
            next.invokeWriteAndFlush(m, promise);
        } else {
            next.invokeWrite(m, promise);
        }
    } else {
        final WriteTask task = WriteTask.newInstance(next, m, promise, flush);
        if (!safeExecute(executor, task, promise, m, !flush)) {
            task.cancel();
        }
    }
}

void invokeWriteAndFlush(Object msg, ChannelPromise promise) {
    if (invokeHandler()) {
        //这里就可以看到writeAndFlush方法是通过write和flush两个事件来执行的
        invokeWrite0(msg, promise);
        invokeFlush0();
    } else {
        writeAndFlush(msg, promise);
    }
}

/**
 * 第72行代码处:
 */
private void invokeWrite0(Object msg, ChannelPromise promise) {
    try {
        /*
        这里拿到的handler是编码的handler,即StringEncoder、ObjectEncoder等等,
        执行它写好的write方法就行了
         */
        ((ChannelOutboundHandler) handler()).write(this, msg, promise);
    } catch (Throwable t) {
        notifyOutboundHandlerException(t, promise);
    }
}

/**
 * 第73行代码处:
 */
private void invokeFlush0() {
    try {
        /*
        这里的handler跟上面invokeWrite0方法的handler是同一个,也就是那个编码的handler,
        执行它写好的flush方法即可(里面同时还会调用HeadContext的flush方法)
         */
        ((ChannelOutboundHandler) handler()).flush(this);
    } catch (Throwable t) {
        invokeExceptionCaught(t);
    }
}

6 心跳检测机制

所谓心跳,即在TCP长连接中,客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线,以确保TCP连接的有效性。在Netty中,实现心跳机制的关键是IdleStateHandler(我之前写过一个Netty心跳检测的示例程序,感兴趣的可以查看《Netty实现心跳检测机制》)。

使用IdleStateHandler的方式也是十分简单,只需要在pipeline中添加就行了(还需要在后面的handler中加上超时的处理):

pipeline.addLast(new IdleStateHandler(3, 0, 0));

这里演示的是IdleStateHandler的readerIdleTime参数指定超过3秒还没收到客户端的连接,会触发IdleStateEvent事件并且交给下一个handler处理。所以下一个handler必须实现userEventTriggered方法处理对应的事件。

6.1 构造器

/**
 * IdleStateHandler:
 * <1>readerIdleTimeSeconds:读超时。即当在指定的时间间隔内没有从Channel中读取到数据时,会触发一个READER_IDLE的
 * IdleStateEvent事件;
 *
 * <2>writerIdleTimeSeconds:写超时。即当在指定的时间间隔内没有数据写入到Channel时,会触发一个WRITER_IDLE的
 * IdleStateEvent事件;
 *
 * <3>allIdleTimeSeconds:读写超时。即当在指定的时间间隔内没有读或写操作时,会触发一个ALL_IDLE的IdleStateEvent事件
 */
public IdleStateHandler(
        int readerIdleTimeSeconds,
        int writerIdleTimeSeconds,
        int allIdleTimeSeconds) {

    this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds,
            TimeUnit.SECONDS);
}

public IdleStateHandler(
        long readerIdleTime, long writerIdleTime, long allIdleTime,
        TimeUnit unit) {
    this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}

public IdleStateHandler(boolean observeOutput,
                        long readerIdleTime, long writerIdleTime, long allIdleTime,
                        TimeUnit unit) {
    ObjectUtil.checkNotNull(unit, "unit");

    /*
    该参数用来表示是否考虑出站特别慢的情况(可能是网络传输比较慢,也可能是客户端处理比较慢)。比如出站用了10秒,
    而空闲时间是5秒,那么在数据还有没有处理完的时候,就已经触发了空闲超时事件。这明显是不合理的。但这里传进来的
    observeOutput是false,也就是不考虑这种情况(如果需要考虑这种情况的话,调用带observeOutput参数的构造器
    就行了)
     */
    this.observeOutput = observeOutput;

    //设置readerIdleTime、writerIdleTimeNanos和allIdleTimeNanos
    if (readerIdleTime <= 0) {
        readerIdleTimeNanos = 0;
    } else {
        readerIdleTimeNanos = Math.max(unit.toNanos(readerIdleTime), MIN_TIMEOUT_NANOS);
    }
    if (writerIdleTime <= 0) {
        writerIdleTimeNanos = 0;
    } else {
        writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS);
    }
    if (allIdleTime <= 0) {
        allIdleTimeNanos = 0;
    } else {
        allIdleTimeNanos = Math.max(unit.toNanos(allIdleTime), MIN_TIMEOUT_NANOS);
    }
}

6.2 channelActive方法

/**
 * IdleStateHandler:
 */
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    //该方法会把定时任务放到eventLoop的任务队列中等待去执行
    initialize(ctx);
    //该处会调用下一个handler的channelActive方法
    super.channelActive(ctx);
}

/**
 * 第7行代码处:
 */
private void initialize(ChannelHandlerContext ctx) {
    switch (state) {
        case 1:
        case 2:
            return;
    }

    /*
    state置为1表示已经初始化过了,同一次channelRead别处调用再进来就会在上面的代码中return了
    (为2表示已经被销毁了,也直接退出)
     */
    state = 1;
    //如果observeOutput设置为true的话,需要记录一些出站缓冲区的相关信息,以考虑出站特别慢的情况
    initOutputChanged(ctx);

    //重置lastReadTime和lastWriteTime为当前时间
    lastReadTime = lastWriteTime = ticksInNanos();
    //如果readerIdleTimeNanos>0,就会把定时任务加到scheduledTaskQueue中
    if (readerIdleTimeNanos > 0) {
        readerIdleTimeout = schedule(ctx, new ReaderIdleTimeoutTask(ctx),
                readerIdleTimeNanos, TimeUnit.NANOSECONDS);
    }
    //如果writerIdleTimeNanos>0,就会把定时任务加到scheduledTaskQueue中
    if (writerIdleTimeNanos > 0) {
        writerIdleTimeout = schedule(ctx, new WriterIdleTimeoutTask(ctx),
                writerIdleTimeNanos, TimeUnit.NANOSECONDS);
    }
    //如果allIdleTimeNanos>0,就会把定时任务加到scheduledTaskQueue中
    if (allIdleTimeNanos > 0) {
        allIdleTimeout = schedule(ctx, new AllIdleTimeoutTask(ctx),
                allIdleTimeNanos, TimeUnit.NANOSECONDS);
    }
}

/**
 * 第28行代码处:
 */
private void initOutputChanged(ChannelHandlerContext ctx) {
    if (observeOutput) {
        Channel channel = ctx.channel();
        Channel.Unsafe unsafe = channel.unsafe();
        ChannelOutboundBuffer buf = unsafe.outboundBuffer();

        /*
        这里会记录一些出站缓冲区的相关信息(缓冲对象的hashCode、buf剩余待写的字节数和当前信息的刷新进度),
        为了后面的hasOutputChanged方法做判断用
         */
        if (buf != null) {
            lastMessageHashCode = System.identityHashCode(buf.current());
            lastPendingWriteBytes = buf.totalPendingWriteBytes();
            lastFlushProgress = buf.currentProgress();
        }
    }
}

/**
 * 第34行、第39行、第44行、第102行、第124行、第140行、第163行、第184行和第208行代码处:
 */
ScheduledFuture<?> schedule(ChannelHandlerContext ctx, Runnable task, long delay, TimeUnit unit) {
    /*
    可以看到这里也是调用了schedule方法。之前已经分析过了,该方法会把任务放进scheduledTaskQueue中,
    后续再去等线程执行runAllTasks方法,把任务拿出来再执行
     */
    return ctx.executor().schedule(task, delay, unit);
}

/**
 * 第34行代码处:
 * ReaderIdleTimeoutTask的run方法,定时任务最终会走到这里
 */
@Override
protected void run(ChannelHandlerContext ctx) {
    long nextDelay = readerIdleTimeNanos;
    if (!reading) {
        /*
        ticksInNanos方法是用来获取当前时间,减去上次channelRead的时间表示的就是距离上次channelRead
        后已经过了多久了。这时候用设置好的read超时时间再去减的话,结果就是下次的超时时间(注意:这一步是发生在
        reading为false,也就是channelRead方法执行完毕的时候)
         */
        nextDelay -= ticksInNanos() - lastReadTime;
    }

    if (nextDelay <= 0) {
        /*
        如上面所说,如果nextDelay<=0就说明已经到达或超过了超时时间。此时再次添加心跳任务进行下一次的心跳检测
        从这里可以看出,Netty的心跳定时任务是通过循环调用schedule方法来添加任务,然后判断当前时间差来实现的
         */
        readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);

        boolean first = firstReaderIdleEvent;
        //firstReaderIdleEvent重新置为false
        firstReaderIdleEvent = false;

        try {
            //构建一个READER_IDLE事件交给下面的userEventTriggered方法
            IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first);
            /*
            执行下一个handler的userEventTriggered方法(也就是我们必须要实现的方法)来处理超时
            (该方法中就一行代码:ctx.fireUserEventTriggered(evt);)    
             */
            channelIdle(ctx, event);
        } catch (Throwable t) {
            ctx.fireExceptionCaught(t);
        }
    } else {
        /*
        如上面所说,如果nextDelay>0就说明此时还没有超时,那么就会把新的定时任务加到scheduledTaskQueue中
        此时nextDelay为更新过的超时时间
         */
        readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
    }
}

/**
 * 第39行代码处:
 * WriterIdleTimeoutTask的run方法,定时任务最终会走到这里
 */
@Override
protected void run(ChannelHandlerContext ctx) {

    long lastWriteTime = this.lastWriteTime;
    //和ReaderIdleTimeoutTask的run方法一样,更新一下此时的nextDelay
    long nextDelay = writerIdleTimeNanos - (ticksInNanos() - lastWriteTime);
    if (nextDelay <= 0) {
        //如果nextDelay<=0就说明已经到达或超过了超时时间。此时再次添加心跳任务进行下一次的心跳检测
        writerIdleTimeout = schedule(ctx, this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);

        boolean first = firstWriterIdleEvent;
        //firstWriterIdleEvent重新置为false
        firstWriterIdleEvent = false;

        try {
            //考虑出站特别慢的情况
            if (hasOutputChanged(ctx, first)) {
                return;
            }
            //构建一个WRITER_IDLE事件交给下面的userEventTriggered方法
            IdleStateEvent event = newIdleStateEvent(IdleState.WRITER_IDLE, first);
            //执行下一个handler的userEventTriggered方法(也就是我们必须要实现的方法)来处理超时
            channelIdle(ctx, event);
        } catch (Throwable t) {
            ctx.fireExceptionCaught(t);
        }
    } else {
        /*
        如果nextDelay>0就说明此时还没有超时,那么就会把新的定时任务加到scheduledTaskQueue中
        此时nextDelay为更新过的超时时间
         */
        writerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
    }
}

/**
 * 第44行代码处:
 * AllIdleTimeoutTask的run方法,定时任务最终会走到这里
 */
@Override
protected void run(ChannelHandlerContext ctx) {

    long nextDelay = allIdleTimeNanos;
    if (!reading) {
        /*
        同理,更新一下此时的nextDelay(注意:这一步是发生在reading为false,也就是channelRead方法
        执行完毕的时候)
         */
        nextDelay -= ticksInNanos() - Math.max(lastReadTime, lastWriteTime);
    }
    if (nextDelay <= 0) {
        //如果nextDelay<=0就说明已经到达或超过了超时时间。此时再次添加心跳任务进行下一次的心跳检测
        allIdleTimeout = schedule(ctx, this, allIdleTimeNanos, TimeUnit.NANOSECONDS);

        boolean first = firstAllIdleEvent;
        //firstAllIdleEvent重新置为false
        firstAllIdleEvent = false;

        try {
            //考虑出站特别慢的情况
            if (hasOutputChanged(ctx, first)) {
                return;
            }

            //构建一个ALL_IDLE事件交给下面的userEventTriggered方法
            IdleStateEvent event = newIdleStateEvent(IdleState.ALL_IDLE, first);
            //执行下一个handler的userEventTriggered方法(也就是我们必须要实现的方法)来处理超时
            channelIdle(ctx, event);
        } catch (Throwable t) {
            ctx.fireExceptionCaught(t);
        }
    } else {
        /*
        如果nextDelay>0就说明此时还没有超时,那么就会把新的定时任务加到scheduledTaskQueue中
        此时nextDelay为更新过的超时时间
         */
        allIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
    }
}

/**
 * 第148行和第192行代码处:
 */
private boolean hasOutputChanged(ChannelHandlerContext ctx, boolean first) {
    //如果observeOutput为false,也就是不考虑出站特别慢,就直接返回false
    if (observeOutput) {

        /*
        如果最后记录的时间和上一次记录的不同,说明此时是第一次进入该方法,或者可能是写操作已经完成了,
        更新了lastWriteTime。此时重新更新一下lastChangeCheckTimeStamp
         */
        if (lastChangeCheckTimeStamp != lastWriteTime) {
            lastChangeCheckTimeStamp = lastWriteTime;

            /*
            如果在出站处理完成之前又触发了下一次的定时任务,从而走到这里的话,first就是false
            也就是说在定时任务两次调用hasOutputChanged方法的过程中,出站事件一直在处理中、没有执行
            完毕。那么此时就直接返回true,后面也不会再处理userEventTriggered方法,直到出站结束
             */
            if (!first) {
                return true;
            }
        }

        Channel channel = ctx.channel();
        Unsafe unsafe = channel.unsafe();
        ChannelOutboundBuffer buf = unsafe.outboundBuffer();

        if (buf != null) {
            //如果出站缓冲区有数据的话,说明之前在initOutputChanged方法中记录了这些信息,此时再次获取这些信息进行比对
            int messageHashCode = System.identityHashCode(buf.current());
            long pendingWriteBytes = buf.totalPendingWriteBytes();

            //如果不等,说明缓冲区的数据在慢慢发生变化,也就是出站特别慢的情况。此时重新更新一下这些值
            if (messageHashCode != lastMessageHashCode || pendingWriteBytes != lastPendingWriteBytes) {
                lastMessageHashCode = messageHashCode;
                lastPendingWriteBytes = pendingWriteBytes;

                /*
                走到这里还是要判断一下first的值,如果为false(不是第一次调用),就不会触发下一个handler的
                userEventTriggered方法;如果为true(第一次调用),就会触发。按照原先设想的逻辑:如果发现
                出站特别慢,那么此时就不应该去触发userEventTriggered方法,静静等待出站完毕就好了。那么为什么
                第一次调用的时候需要触发呢?其实这里是Netty设计者的考虑。如果真的是发生了出站特别慢的情况,
                很可能会引发后续的OOM。所以这里第一次调用会触发userEventTriggered方法,从而给使用者一个警告
                如果这里不触发,从而最终可能发生OOM的话,可能会花费很大的功夫才能找到原来是出站特别慢(可能是
                网络传输比较慢,也可能是客户端处理比较慢)才导致的OOM
                 */
                if (!first) {
                    return true;
                }
            }

            /*
            lastFlushProgress属性是4.1.x版本中新加的,之前4.0.x版本中没有这个属性。添加的原因详见
            https://github.com/netty/netty/commit/51112e2b36ec5550a73d72bfc59f4523f7b8ec27
             */
            long flushProgress = buf.currentProgress();
            if (flushProgress != lastFlushProgress) {
                lastFlushProgress = flushProgress;

                //同上面的解释
                if (!first) {
                    return true;
                }
            }
        }
    }

    return false;
}

6.3 channelRead方法

/**
 * IdleStateHandler:
 */
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (readerIdleTimeNanos > 0 || allIdleTimeNanos > 0) {
        /*
        reading为true表示channelRead方法还在执行中,在channelReadComplete方法中会重置为false,
        也就是channelRead方法执行完毕了
         */
        reading = true;
        //每一次channelRead进来的时候都会将firstReaderIdleEvent和firstAllIdleEvent置为true
        firstReaderIdleEvent = firstAllIdleEvent = true;
    }
    /*
    该处会调用下一个handler的channelRead方法,也就是IdleStateHandler的channelRead方法并没有做什么
    实际的事情,只是更改了一些标志位而已
     */
    ctx.fireChannelRead(msg);
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!