netty服务端源码分析

服务端源码

首先从服务端模板代码入手

public class NettyServer {

public static void main(String[] args) throws Exception {

    // 创建两个线程组bossGroup和workerGroup, 含有的子线程NioEventLoop的个数默认为cpu核数的两倍
    // bossGroup只是处理连接请求 ,真正的和客户端业务处理,会交给workerGroup完成
    EventLoopGroup bossGroup = new NioEventLoopGroup(3);
    EventLoopGroup workerGroup = new NioEventLoopGroup(8);
    try {
        // 创建服务器端的启动对象
        ServerBootstrap bootstrap = new ServerBootstrap();
        // 使用链式编程来配置参数
        bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                // 使用NioServerSocketChannel作为服务器的通道实现
                .channel(NioServerSocketChannel.class)
                // 初始化服务器连接队列大小,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。
                // 多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数,在 SocketChannel 建立起来之前执行

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //对workerGroup的SocketChannel设置处理器
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                });
        System.out.println("netty server start。。");
        // 绑定一个端口并且同步, 生成了一个ChannelFuture异步对象,通过isDone()等方法可以判断异步事件的执行情况
        // 启动服务器(并绑定端口),bind是异步操作,sync方法是等待异步操作执行完毕
        ChannelFuture cf = bootstrap.bind(9000).sync();
        // 给cf注册监听器,监听我们关心的事件
        /*cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (cf.isSuccess()) {
                    System.out.println("监听端口9000成功");
                } else {
                    System.out.println("监听端口9000失败");
                }
            }
        });*/
        // 等待服务端监听端口关闭,closeFuture是异步操作
        // 通过sync方法同步等待通道关闭处理完毕,这里会阻塞等待通道关闭完成,内部调用的是Object的wait()方法
        cf.channel().closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
}

首先根据netty程序 这是netty两个线程模型的对象 它的模型就是 一个用来负责处理 连接请求 一个用来负责读写等请求

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup(8);

查看NioEventLoopGroup这个类型是什么东西 进入它的构造方法

 /**
 * Create a new instance using the specified number of threads, {@link ThreadFactory} and the
 * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
 * 中文意思
 * 使用指定数量的线程创建一个新实例,{@link ThreadFactory}和
 * {@link SelectorProvider}由{@link SelectorProvider#provider()}返回。
 */
public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

上面的代码传入了一个Executor类型的null 一个没实现的线程 跟进this

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

SelectorProvider.provider()这个是nio实现的 创建一个selector对象 Selector.open();这个open方法

public static Selector open() throws IOException {
    return SelectorProvider.provider().openSelector();
}

SelectorProvider.provider()这个创建selector对象 openSelector在linux系统上创建一个epoll或者说开启一个epoll 就是执行epoll_create(int size)这个函数在BIO、NIO、AIO这个文章里写过

然后再跟进this

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

再跟进this

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

再跟进super

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

再跟进super

 protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }

DEFAULT_EVENT_LOOP_THREADS 是在MultithreadEventLoopGroup这个类的静态代码块中赋值

static {
        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);
    }
}

NettyRuntime.availableProcessors()返回当前机器cpu逻辑核数 根据它的逻辑默认是cpu逻辑核的两倍 也就是说如果使用new NioEventLoopGroup()这个无参构造 默认是cpu逻辑核的两倍

然后在跟进super

 /**
     * Create a new instance.
     *
     * @param nThreads          the number of threads that will be used by this instance.
     * @param executor          the Executor to use, or {@code null} if the default should be used.
     * @param args              arguments which will passed to each {@link #newChild(Executor, Object...)} call
     * 中文意思
     * 创建一个新实例。
     * @param nThreads该实例将使用的线程数。
     * @param executor要使用的executor,或者{@code null},如果应该使用默认值。
     * @param args参数将传递给每个{@link #newChild(Executor, Object…)}调用
     */
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }

进入this

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

    if (executor == null) {
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

    children = new EventExecutor[nThreads];

    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
            // TODO: Think about if this is a good exception type
            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) {
                        // Let the caller handle the interruption.
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }

    chooser = chooserFactory.newChooser(children);

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

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

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

可以看到 executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); 在这里创建了一个线程

children = new EventExecutor[nThreads];这个创建了一个数组 EventExecutor这个类型就是ChannelPipeline它的一个实现用来关联handler

在for循环中 children[i] = newChild(executor, args); 这个newChild 是一个抽象方法protected abstract EventExecutor newChild(Executor executor, Object… args) throws Exception; 选择NioEventLoopGroup这个类型进入newChild方法

@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
        ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}

这里创建了一个NioEventLoop 这个类型就可以理解为select对象 看它的构造方法

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        if (selectorProvider == null) {
            throw new NullPointerException("selectorProvider");
        }
        if (strategy == null) {
            throw new NullPointerException("selectStrategy");
        }
        provider = selectorProvider;
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

先看super

 protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        tailTasks = newTaskQueue(maxPendingTasks);
    }

还有super 再进入super

 protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = Math.max(16, maxPendingTasks);
        this.executor = ThreadExecutorMap.apply(executor, this);
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

还是有super 再次进入

 protected AbstractScheduledEventExecutor(EventExecutorGroup parent) {
        super(parent);
    }

再进入super

 protected AbstractEventExecutor(EventExecutorGroup parent) {
        this.parent = parent;
    }

就赋了个值 没了 然后返回 返回到

 protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = Math.max(16, maxPendingTasks);
        this.executor = ThreadExecutorMap.apply(executor, this);
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

这里创建了一个队列newTaskQueue(this.maxPendingTasks); 然后剩下的看不懂了 然后返回

 protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        tailTasks = newTaskQueue(maxPendingTasks);
    }

返回之后又看到 tailTasks = newTaskQueue(maxPendingTasks);创建了一个队列 没别的东西了然后返回

返回到

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        if (selectorProvider == null) {
            throw new NullPointerException("selectorProvider");
        }
        if (strategy == null) {
            throw new NullPointerException("selectStrategy");
        }
        provider = selectorProvider;
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

这里 看到  final SelectorTuple selectorTuple = openSelector();


private SelectorTuple openSelector() {
        final Selector unwrappedSelector;
        try {
            unwrappedSelector = provider.openSelector();
        } catch (IOException e) {
            throw new ChannelException("failed to open a new selector", e);
        }

    if (DISABLE_KEY_SET_OPTIMIZATION) {
        return new SelectorTuple(unwrappedSelector);
    }

    Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
            try {
                return Class.forName(
                        "sun.nio.ch.SelectorImpl",
                        false,
                        PlatformDependent.getSystemClassLoader());
            } catch (Throwable cause) {
                return cause;
            }
        }
    });

    if (!(maybeSelectorImplClass instanceof Class) ||
        // ensure the current selector implementation is what we can instrument.
        !((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {
        if (maybeSelectorImplClass instanceof Throwable) {
            Throwable t = (Throwable) maybeSelectorImplClass;
            logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t);
        }
        return new SelectorTuple(unwrappedSelector);
    }

    final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
    final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

    Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
            try {
                Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
                Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

                if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
                    // Let us try to use sun.misc.Unsafe to replace the SelectionKeySet.
                    // This allows us to also do this in Java9+ without any extra flags.
                    long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
                    long publicSelectedKeysFieldOffset =
                            PlatformDependent.objectFieldOffset(publicSelectedKeysField);

                    if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
                        PlatformDependent.putObject(
                                unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
                        PlatformDependent.putObject(
                                unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
                        return null;
                    }
                    // We could not retrieve the offset, lets try reflection as last-resort.
                }

                Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
                if (cause != null) {
                    return cause;
                }
                cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
                if (cause != null) {
                    return cause;
                }

                selectedKeysField.set(unwrappedSelector, selectedKeySet);
                publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
                return null;
            } catch (NoSuchFieldException e) {
                return e;
            } catch (IllegalAccessException e) {
                return e;
            }
        }
    });

这个方法很长 我们看 unwrappedSelector = provider.openSelector();这个 provider之前执行了 就是这个SelectorProvider.provider() 然后这里又执行了openSelector()也就是nio里的SelectorProvider.provider().openSelector();这一句 创建epoll上面 然后好像没别的东西了然后返回到最开始

NioEventLoopGroup这个类型里面封装了一个EventExecutor 这个EventExecutor这个是一个数组 然后这个类型里面又有 NioEventLoop这个类型 这个类型里面封装了一个队列还有select创建完epoll的对象

然后查看 bootstrap.group(bossGroup, workerGroup)这个方法 看这个之前要先看一下这个 ServerBootstrap bootstrap = new ServerBootstrap();是什么 进入new ServerBootstrap();看到调用的一个无参并且是空方法

 public ServerBootstrap() { }

然后在看bootstrap.group(bossGroup, workerGroup) 这个方法 进入这个方法 到了ServerBootstrap这个类中

 /**
 * Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These
 * {@link EventLoopGroup}'s are used to handle all the events and IO for {@link ServerChannel} and
 * {@link Channel}'s.
 * 中文意思
 * 为父(接受器)和子(客户端)设置{@link EventLoopGroup}。这些
 * {@link EventLoopGroup}用于处理{@link ServerChannel}和的所有事件和IO
 * {@link频道}。
 */
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
// 这个方法目前来看出传入的参数为
//      EventLoopGroup bossGroup = new NioEventLoopGroup(1);      是这个parentGroup 中文意思 父组
    //      EventLoopGroup workerGroup = new NioEventLoopGroup(8);    是这个childGroup  中文字样 孩子组
    super.group(parentGroup);
    if (childGroup == null) {
        throw new NullPointerException("childGroup");
    }
    if (this.childGroup != null) {
        throw new IllegalStateException("childGroup set already");
    }
// childGroup在这给赋值了
    this.childGroup = childGroup;
    return this;
}

然后我们看super.group把bossGroup传入之后做了什么 进入这个方法 到了AbstractBootstrap这个类中

 /**
 * The {@link EventLoopGroup} which is used to handle all the events for the to-be-created
 * {@link Channel}
 * 中文意思
 * {@link EventLoopGroup}用于处理将要创建的所有事件
 * {@link频道}
 */
public B group(EventLoopGroup group) {
    if (group == null) {
        throw new NullPointerException("group");
    }
    if (this.group != null) {
        throw new IllegalStateException("group set already");
    }
    this.group = group;
    return self();
}

看到bossGroup在这赋值给了this.group 这个self();返回了当前对象 因为是链式编程所以要返回当前对象

  private B self() {
        return (B) this;
    }

bootstrap.group(bossGroup, workerGroup) 这个方法就是做了把bossGroup在这赋值给了AbstractBootstrap类中的this.group属性 workerGroup赋值给了ServerBootstrap的this.childGroup属性 然后就结束了 然后继续往下看bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
看channel这个方法 进入这个方法 来到了AbstractBootstrap这个类中

   /**
     * The {@link Class} which is used to create {@link Channel} instances from.
     * You either use this or {@link #channelFactory(io.netty.channel.ChannelFactory)} if your
     * {@link Channel} implementation has no no-args constructor.
     * 中文意思
     * 用于创建{@link Channel}实例的{@link Class}。
     * 你可以使用这个或{@link #channelFactory(io.net .channel. channelFactory)}
     * {@link Channel}实现没有无参数构造函数。
     */
    public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }

这个方法只有 channelFactory(new ReflectiveChannelFactory(channelClass));这个东西可以看 进入这个方法之前 先看new ReflectiveChannelFactory(channelClass)这个构造方法做了什么 所以进入这个构造方法

public ReflectiveChannelFactory(Class<? extends T> clazz) {
        ObjectUtil.checkNotNull(clazz, "clazz");
        try {
            this.constructor = clazz.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                    " does not have a public non-arg constructor", e);
        }
    }

看到构造方法中 使用java反射机制 返回了一个构造函数 也就是NioServerSocketChannel.class这个东西 就是返回了一个new NioServerSocketChannel() 然后看看 ObjectUtil.checkNotNull(clazz, “clazz”);

 /**
 * Checks that the given argument is not null. If it is, throws {@link NullPointerException}.
 * Otherwise, returns the argument. 
 * 中文意思
 *检查给定参数是否为空。如果是,抛出{@link NullPointerException}。
 *否则返回参数。
 */
public static <T> T checkNotNull(T arg, String text) {
    if (arg == null) {
        throw new NullPointerException(text);
    }
    return arg;
}

也就是判断clazz 是不是空的没什么逻辑 然后构造方法中没什么东西了 然后返回到channelFactory(new ReflectiveChannelFactory(channelClass));这里 查看channelFactory这个方法 进入这个方法还是在AbstractBootstrap这个类中

 /**
     * {@link io.netty.channel.ChannelFactory} which is used to create {@link Channel} instances from
     * when calling {@link #bind()}. This method is usually only used if {@link #channel(Class)}
     * is not working for you because of some more complex needs. If your {@link Channel} implementation
     * has a no-args constructor, its highly recommend to just use {@link #channel(Class)} to
     * simplify your code.
     * 中文意思
     * {@link io.nettty.channel.channelfactory}用于创建{@link Channel}实例
     * 当调用{@link #bind()}时。这个方法通常只在{@link #channel(Class)}中使用。
     * 并不适合您,因为一些更复杂的需求。如果你的{@link Channel}实现
     * 有一个无参数的构造函数,强烈建议使用{@link #channel(Class)} to
     * 简化你的代码。
     */
    @SuppressWarnings({ "unchecked", "deprecation" })
    public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) {
        return channelFactory((ChannelFactory<C>) channelFactory);
    }

然后进入channelFactory 方法 还是在AbstractBootstrap这个类中

/**
 * @deprecated Use {@link #channelFactory(io.netty.channel.ChannelFactory)} instead.、
 * 中文意思
 * @deprecated使用{@link #channelFactory(io.net .channel. channelFactory)}代替。
 */
@Deprecated
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
    if (channelFactory == null) {
        throw new NullPointerException("channelFactory");
    }
    if (this.channelFactory != null) {
        throw new IllegalStateException("channelFactory set already");
    }

    this.channelFactory = channelFactory;
    return self();
}

这个方法中 把我们上面传入的new ReflectiveChannelFactory(channelClass)这个赋值给了AbstractBootstrap类中的channelFactory这个属性然后没别的东西了 然后返回到最开始 查看 bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024)这个option方法 然后就会进入AbstractBootstrap这个类中

 /**
 * Allow to specify a {@link ChannelOption} which is used for the {@link Channel} instances once they got
 * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}.
 * 中文意思
 * 允许指定一个{@link ChannelOption},用于{@link Channel}实例
 * 创建。使用{@code null}的值来删除之前设置的{@link ChannelOption}。
 */
public <T> B option(ChannelOption<T> option, T value) {
    if (option == null) {
        throw new NullPointerException("option");
    }
    if (value == null) {
        synchronized (options) {
            options.remove(option);
        }
    } else {
        synchronized (options) {
            options.put(option, value);
        }
    }
    return self();
}

感觉这个方法看不懂 然后看看options是什么 private final Map<ChannelOption<?>, Object> options = new LinkedHashMap

ChannelInitializer这是一个抽象类 重写了它的initChannel方法 查看childHandler这个方法 然后查看childHandler这个方法 进入这个方法来到了ServerBootstrap这个类

 /**
 * Set the {@link ChannelHandler} which is used to serve the request for the {@link Channel}'s.
 * 中文意思
 * 设置用于为{@link Channel}的请求提供服务的{@link ChannelHandler}。
 */
public ServerBootstrap childHandler(ChannelHandler childHandler) {
    if (childHandler == null) {
        throw new NullPointerException("childHandler");
    }
    this.childHandler = childHandler;
    return this;
}

这个方法吧

	   new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数,在 SocketChannel 建立起来之前执行

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //对workerGroup的SocketChannel设置处理器
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                }

这一堆赋值给了ServerBootstrap这个类中的childHandler这个属性 然后没别的东西了 到这就结束了 可以看到

 // 使用链式编程来配置参数
        bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                // 使用NioServerSocketChannel作为服务器的通道实现
                .channel(NioServerSocketChannel.class)
                // 初始化服务器连接队列大小,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。
                // 多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数,在 SocketChannel 建立起来之前执行

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //对workerGroup的SocketChannel设置处理器
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                });

这一堆代码 就是赋值 没做其它的东西 然后回到最开始继续往下看

ChannelFuture cf = bootstrap.bind(9000).sync(); 看这个 然后看bind这个方法 进入bind方法 来到AbstractBootstrap这个类

 /**
 * Create a new {@link Channel} and bind it.
 * 中文意思
 * 创建一个新的{@link Channel}并绑定它。
 */
public ChannelFuture bind(int inetPort) {
    return bind(new InetSocketAddress(inetPort));
}

然后再进入 bind(new InetSocketAddress(inetPort));这个InetSocketAddress类的构造方法中看看在构造方法中做了什么 进入构造方法

 /**
 * Creates a socket address where the IP address is the wildcard address
 * and the port number a specified value.
 * <p>
 * A valid port value is between 0 and 65535.
 * A port number of {@code zero} will let the system pick up an
 * ephemeral port in a {@code bind} operation.
 * <p>
 * @param   port    The port number
 * @throws IllegalArgumentException if the port parameter is outside the specified
 * range of valid port values.
 * 中文意思
 * 创建一个套接字地址,其中IP地址是通配符地址
 * 和端口号指定值。
 * < p >
 * 有效端口值为0 ~ 65535。
 * 一个端口号{@code 0}将让系统拾取一个
 * 在{@code绑定}操作中的临时端口。
 * < p >
 * @param port端口号
 * @throws IllegalArgumentException如果端口参数不在指定的范围内
 * 有效端口值的范围。
 */
public InetSocketAddress(int port) {
    this(InetAddress.anyLocalAddress(), port);
}

InetAddress.anyLocalAddress()返回一个IP地址

然后this又会到这里

 /**
 *
 * Creates a socket address from an IP address and a port number.
 * <p>
 * A valid port value is between 0 and 65535.
 * A port number of {@code zero} will let the system pick up an
 * ephemeral port in a {@code bind} operation.
 * <P>
 * A {@code null} address will assign the <i>wildcard</i> address.
 * <p>
 * @param   addr    The IP address
 * @param   port    The port number
 * @throws IllegalArgumentException if the port parameter is outside the specified
 * range of valid port values.
 * 中文意思
 * 从IP地址和端口号创建套接字地址。
 * < p >
 * 有效端口值为0 ~ 65535。
 * 一个端口号{@code 0}将让系统拾取一个
 * 在{@code绑定}操作中的临时端口。
 * < p >
 * 一个{@code null}地址将分配<i>通配符</i>地址。
 * < p >
 * @param addr IP地址
 * @param port端口号
 * @throws IllegalArgumentException如果端口参数不在指定的范围内
 * 有效端口值的范围。
 */
public InetSocketAddress(InetAddress addr, int port) {
    holder = new InetSocketAddressHolder(
                    null,
                    addr == null ? InetAddress.anyLocalAddress() : addr,
                    checkPort(port));
}

然后进入new InetSocketAddressHolder就会到这

private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
            this.hostname = hostname;
            this.addr = addr;
            this.port = port;
        }

这个构造bind(new InetSocketAddress(inetPort));的new InetSocketAddress(inetPort)中就赋值了一个ip地址跟端口 然后进入bind方法 来到AbstractBootstrap这个类

 /**
 * Create a new {@link Channel} and bind it.
 * 中文意思
 * 创建一个新的{@link Channel}并绑定它。
 */
public ChannelFuture bind(SocketAddress localAddress) {
    validate();
    if (localAddress == null) {
        throw new NullPointerException("localAddress");
    }
    return doBind(localAddress);
}

validate()方法

 /**
 * Validate all the parameters. Sub-classes may override this, but should
 * call the super method in that case.
 * 中文意思
 * 验证所有参数。子类可以重写这个,但是应该重写 
 * 在这种情况下调用super方法。
 */
public B validate() {
    if (group == null) {
        throw new IllegalStateException("group not set");
    }
    if (channelFactory == null) {
        throw new IllegalStateException("channel or channelFactory not set");
    }
    return self();
}

doBind方法 来到AbstractBootstrap这个类中

private ChannelFuture doBind(final SocketAddress localAddress) {
        final ChannelFuture regFuture = initAndRegister();
        final Channel channel = regFuture.channel();
        if (regFuture.cause() != null) {
            return regFuture;
        }

    if (regFuture.isDone()) {
        // At this point we know that the registration was complete and successful.
    // 中文意思  此时,我们知道注册已经完成并成功了。
        ChannelPromise promise = channel.newPromise();
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        // Registration future is almost always fulfilled already, but just in case it's not.
        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) {
                    // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
                    // IllegalStateException once we try to access the EventLoop of the Channel.
		// 中文意思
		// 在EventLoop上注册失败,因此直接失败的ChannelPromise,以不引起
		// 当我们试图访问通道的EventLoop时,IllegalStateException。
                    promise.setFailure(cause);
                } else {
                    // Registration was successful, so set the correct executor to use.
                    // See https://github.com/netty/netty/issues/2586
		// 中文意思
		// 注册成功,因此设置正确的执行器使用。
                    // 参见https://github.com/netty/netty/issues/2586
                    promise.registered();

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

然后看initAndRegister(); 这个方法 来到AbstractBootstrap这个类中

final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            channel = channelFactory.newChannel();
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                // channel can be null if newChannel crashed (eg SocketException("too many open files"))
                channel.unsafe().closeForcibly();
                // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }

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


    // If we are here and the promise is not failed, it's one of the following cases:
    // 1) If we attempted registration from the event loop, the registration has been completed at this point.
    //    i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
    // 2) If we attempted registration from the other thread, the registration request has been successfully
    //    added to the event loop's task queue for later execution.
    //    i.e. It's safe to attempt bind() or connect() now:
    //         because bind() or connect() will be executed *after* the scheduled registration task is executed
    //         because register(), bind(), and connect() are all bound to the same thread.
    return regFuture;
}

channelFactory.newChannel(); 这个方法之前在 
	   // 使用链式编程来配置参数
            bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                    // 使用NioServerSocketChannel作为服务器的通道实现
                    .channel(NioServerSocketChannel.class)
这个channel中给channelFactory赋值了 ReflectiveChannelFactory这个类型的 然后这个
newChannel就是创建了一个NioServerSocketChannel这个类型的对象

ReflectiveChannelFactory类中的 newChannel方法

 @Override
    public T newChannel() {
        try {
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }

然后查看NioServerSocketChannel它的构造方法

 /**
 * Create a new instance
 * 中文意思
 * 创建一个新实例
 */
public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

newSocket(DEFAULT_SELECTOR_PROVIDER)创建一个ServerSocketChannel

DEFAULT_SELECTOR_PROVIDER一个这个  private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            /**
             *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
             *  {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
             *
             *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
             */
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }

调用的nio原生api provider.openServerSocketChannel(); 返回一个ServerSocketChannel实例

然后返回再跟进this

 /**
 * Create a new instance using the given {@link ServerSocketChannel}.
 * 中文意思
 * 使用给定的{@link ServerSocketChannel}创建一个新实例。
 */
public NioServerSocketChannel(ServerSocketChannel channel) {
    super(null, channel, SelectionKey.OP_ACCEPT);
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

跟进super

 /**
     * @see AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)
     */
    protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent, ch, readInterestOp);
    }

跟进super

/**
     * Create a new instance
     *
     * @param parent            the parent {@link Channel} by which this instance was created. May be {@code null}
     * @param ch                the underlying {@link SelectableChannel} on which it operates
     * @param readInterestOp    the ops to set to receive data from the {@link SelectableChannel}
     * 中文意思
     * 创建一个新实例
     * @param parent创建该实例的父类{@link Channel}。可能是{@code null}
     * @param ch底层{@link selectabchannel},它在上面操作
     * @param readInterestOp设置从{@link SelectableChannel}接收数据的操作
     */
    protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent);
        this.ch = ch;
        this.readInterestOp = readInterestOp;
        try {
            ch.configureBlocking(false);
        } catch (IOException e) {
            try {
                ch.close();
            } catch (IOException e2) {
                if (logger.isWarnEnabled()) {
                    logger.warn(
                            "Failed to close a partially initialized socket.", e2);
                }
            }

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

ch.configureBlocking(false); 设置NIO非阻塞

跟进super

 protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }

看到这里 pipeline = newChannelPipeline(); 创建了一个保存handler的实例

进入newChannelPipeline();方法 来到AbstractChannel类中

 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);

    tail = new TailContext(this);
    head = new HeadContext(this);

    head.next = tail;
    tail.prev = head;
}

在这里看到 创建了两个handler 之前说过netty会创建两个handler 一个是head一个是tail head在第一个 tail最后一个 业务handler都会在tail之前插入

    tail = new TailContext(this);
    head = new HeadContext(this);


    head.next = tail;   // next这个属性在这里可以看出 指向后面的handler
    tail.prev = head;   // prev这个属性在这里可以看出 指向前面的handler

然后没别的逻辑了返回到initAndRegister方法

init(channel);
然后返回跟进init方法是一个抽象方法abstract void init(Channel channel) throws Exception; 跟进如果使用idea会看到有两个实现Bootstrap跟ServerBootstrap 我们看的服务端源码这里选择服务端ServerBootstrap实现的init方法
来到ServerBootstrap类查看init方法

  @Override
    void init(Channel channel) throws Exception {
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
            setChannelOptions(channel, options, logger);
        }

    final Map<AttributeKey<?>, Object> attrs = attrs0();
    synchronized (attrs) {
        for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
            @SuppressWarnings("unchecked")
            AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
            channel.attr(key).set(e.getValue());
        }
    }

    ChannelPipeline p = channel.pipeline();

    final EventLoopGroup currentChildGroup = childGroup;
    final ChannelHandler currentChildHandler = childHandler;
    final Entry<ChannelOption<?>, Object>[] currentChildOptions;
    final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
    synchronized (childOptions) {
        currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
    }
    synchronized (childAttrs) {
        currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
    }

    p.addLast(new ChannelInitializer<Channel>() {
        @Override
        public void initChannel(final Channel ch) throws Exception {
            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));
                }
            });
        }
    });
}

这个方法有点长 慢慢分析

看到这个 ChannelPipeline p = channel.pipeline(); 返回的是上面说的哪个pipeline实例

p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                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));
                }
            });
        }
    });

然后又在下面添加了一个handler 然后就结束了 然后我们看看它是怎么在tail之前添加handler的 进入 addLast方法

来到 DefaultChannelPipeline 这个类里面

 @Override
    public final ChannelPipeline addLast(ChannelHandler... handlers) {
        return addLast(null, handlers);
    }

然后再跟进addLast(null, handlers);

@Override
    public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
        if (handlers == null) {
            throw new NullPointerException("handlers");
        }

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

    return this;
}

跟进addLast(executor, null, h);

 @Override
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);

        newCtx = newContext(group, filterName(name, handler), handler);

        addLast0(newCtx);

        // If the registered is false it means that the channel was not registered on an eventLoop yet.
        // In this case we add the context to the pipeline and add a task that will call
        // ChannelHandler.handlerAdded(...) once the channel is registered.
        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;
}

newCtx = newContext(group, filterName(name, handler), handler); 这里把当前的handler进行了封装 就让这个handler跟ChannelPipeline做了个绑定

跟进这里 addLast0(newCtx);

 private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

AbstractChannelHandlerContext newCtx就是我们传进来的哪个handler

tail.prev根据上面的逻辑 这里指向的是第一个handler

newCtx.prev = prev; 这里它又指向的第一个handler

newCtx.next = tail; 这里它指向了最后一个handler

prev.next = newCtx; prev是第一个handler用来指向后一个hadnler的指针 然后它指向了当前handler

tail.prev = newCtx; 最后一个handler用来指向前一个hadnler的指针 指向了当前handler

也就是在这里实现了 在head跟tail之间在tail之前插入handler

然后返回到initAndRegister方法继续往下看

看到 ChannelFuture regFuture = config().group().register(channel); 这一行

config()返回的是ServerBootstrap

group()返回的是父组

然后跟进register 进入这个MultithreadEventLoopGroup类中

  @Override
    public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }

next() 从父组中拿出一个对象也就是 children[i] = newChild(executor, args); 拿出一个newChild具体是什么翻上去看

然后跟进register(channel); 进入 SingleThreadEventLoop 这个类型

 @Override
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }

然后跟进 register(new DefaultChannelPromise(channel, this));

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

然后跟进 register(this, promise); 进入 AbstractChannel 这个类中

  @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            if (eventLoop == null) {
                throw new NullPointerException("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;
            }

        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);
            }
        }
    }

然后先进入execute 这个方法

@Override
    public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }

    boolean inEventLoop = inEventLoop();
    addTask(task);
    if (!inEventLoop) {
        startThread();
        if (isShutdown()) {
            boolean reject = false;
            try {
                if (removeTask(task)) {
                    reject = true;
                }
            } catch (UnsupportedOperationException e) {
                // The task queue does not support removal so the best thing we can do is to just move on and
                // hope we will be able to pick-up the task before its completely terminated.
                // In worst case we will log on termination.
            }
            if (reject) {
                reject();
            }
        }

    }

    if (!addTaskWakesUp && wakesUpForTask(task)) {
        wakeup(inEventLoop);
    }
}

addTask(task);把一个线程放到了一个队列中

然后看 startThread();这个方法

 private void startThread() {
        if (state == ST_NOT_STARTED) {
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                try {
                    doStartThread();
                } catch (Throwable cause) {
                    STATE_UPDATER.set(this, ST_NOT_STARTED);
                    PlatformDependent.throwException(cause);
                }
            }
        }
    }

再看 doStartThread();这个方法

private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                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;
                    }
                }

                // Check if confirmShutdown() was called at the end of the loop.
                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 {
                    // Run all remaining tasks and shutdown hooks.
                    for (;;) {
                        if (confirmShutdown()) {
                            break;
                        }
                    }
                } finally {
                    try {
                        cleanup();
                    } finally {
                        // Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
                        // the future. The user may block on the future and once it unblocks the JVM may terminate
                        // and start unloading classes.
                        // See https://github.com/netty/netty/issues/6596.
                        FastThreadLocal.removeAll();

                        STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                        threadLock.release();
                        if (!taskQueue.isEmpty()) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("An event executor terminated with " +
                                        "non-empty task queue (" + taskQueue.size() + ')');
                            }
                        }
                        terminationFuture.setSuccess(null);
                    }
                }
            }
        }
    });
}

看到这个SingleThreadEventExecutor.this.run(); 进入到NioEventLoop类中

@Override
    protected void run() {
        for (;;) {
            try {
                try {
                    switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;

                case SelectStrategy.BUSY_WAIT:
                    // fall-through to SELECT since the busy-wait is not supported with NIO

                case SelectStrategy.SELECT:
                    select(wakenUp.getAndSet(false));

                    // 'wakenUp.compareAndSet(false, true)' is always evaluated
                    // before calling 'selector.wakeup()' to reduce the wake-up
                    // overhead. (Selector.wakeup() is an expensive operation.)
                    //
                    // However, there is a race condition in this approach.
                    // The race condition is triggered when 'wakenUp' is set to
                    // true too early.
                    //
                    // 'wakenUp' is set to true too early if:
                    // 1) Selector is waken up between 'wakenUp.set(false)' and
                    //    'selector.select(...)'. (BAD)
                    // 2) Selector is waken up between 'selector.select(...)' and
                    //    'if (wakenUp.get()) { ... }'. (OK)
                    //
                    // In the first case, 'wakenUp' is set to true and the
                    // following 'selector.select(...)' will wake up immediately.
                    // Until 'wakenUp' is set to false again in the next round,
                    // 'wakenUp.compareAndSet(false, true)' will fail, and therefore
                    // any attempt to wake up the Selector will fail, too, causing
                    // the following 'selector.select(...)' call to block
                    // unnecessarily.
                    //
                    // To fix this problem, we wake up the selector again if wakenUp
                    // is true immediately after selector.select(...).
                    // It is inefficient in that it wakes up the selector for both
                    // the first case (BAD - wake-up required) and the second case
                    // (OK - no wake-up required).

                    if (wakenUp.get()) {
                        selector.wakeup();
                    }
                    // fall through
                default:
                }
            } catch (IOException e) {
                // If we receive an IOException here its because the Selector is messed up. Let's rebuild
                // the selector and retry. https://github.com/netty/netty/issues/8566
                rebuildSelector0();
                handleLoopException(e);
                continue;
            }

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

看到 select(wakenUp.getAndSet(false));这个 然后进入这个方法

private void select(boolean oldWakenUp) throws IOException {
        Selector selector = this.selector;
        try {
            int selectCnt = 0;
            long currentTimeNanos = System.nanoTime();
            long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos);

        for (;;) {
            long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L;
            if (timeoutMillis <= 0) {
                if (selectCnt == 0) {
                    selector.selectNow();
                    selectCnt = 1;
                }
                break;
            }

            // If a task was submitted when wakenUp value was true, the task didn't get a chance to call
            // Selector#wakeup. So we need to check task queue again before executing select operation.
            // If we don't, the task might be pended until select operation was timed out.
            // It might be pended until idle timeout if IdleStateHandler existed in pipeline.
            if (hasTasks() && wakenUp.compareAndSet(false, true)) {
                selector.selectNow();
                selectCnt = 1;
                break;
            }

            int selectedKeys = selector.select(timeoutMillis);
            selectCnt ++;

            if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {
                // - Selected something,
                // - waken up by user, or
                // - the task queue has a pending task.
                // - a scheduled task is ready for processing
                break;
            }
            if (Thread.interrupted()) {
                // Thread was interrupted so reset selected keys and break so we not run into a busy loop.
                // As this is most likely a bug in the handler of the user or it's client library we will
                // also log it.
                //
                // See https://github.com/netty/netty/issues/2426
                if (logger.isDebugEnabled()) {
                    logger.debug("Selector.select() returned prematurely because " +
                            "Thread.currentThread().interrupt() was called. Use " +
                            "NioEventLoop.shutdownGracefully() to shutdown the NioEventLoop.");
                }
                selectCnt = 1;
                break;
            }

            long time = System.nanoTime();
            if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) {
                // timeoutMillis elapsed without anything selected.
                selectCnt = 1;
            } else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 &&
                    selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) {
                // The code exists in an extra method to ensure the method is not too big to inline as this
                // branch is not very likely to get hit very frequently.
                selector = selectRebuildSelector(selectCnt);
                selectCnt = 1;
                break;
            }

            currentTimeNanos = time;
        }

        if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS) {
            if (logger.isDebugEnabled()) {
                logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",
                        selectCnt - 1, selector);
            }
        }
    } catch (CancelledKeyException e) {
        if (logger.isDebugEnabled()) {
            logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?",
                    selector, e);
        }
        // Harmless exception - log anyway
    }
}

看到把之前创建的的selector在这进行了赋值

Selector selector = this.selector;

往下走又看到

int selectedKeys = selector.select(timeoutMillis);

selector.select(timeoutMillis);这一句跟 selector.select();一样 java多态 传入参数表示超时时间 如果在这阻塞的时间超过了这个值它就会退出阻塞继续往下执行 然后等执行完了再回来阻塞然后超时再继续往下执行。。。然后返回到NioEventLoop类中的run方法继续往下看

看到有这个

	    try {
                    processSelectedKeys();
                } finally {
                    // Ensure we always run tasks.
                    runAllTasks();
                }

processSelectedKeys();用来处理事件的 今天不写

runAllTasks();用来处理之前创建的taskQueue 中存放的那些线程任务 进入runAllTasks方法

protected boolean runAllTasks() {
        assert inEventLoop();
        boolean fetchedAll;
        boolean ranAtLeastOne = false;

    do {
        fetchedAll = fetchFromScheduledTaskQueue();
        if (runAllTasksFrom(taskQueue)) {
            ranAtLeastOne = true;
        }
    } while (!fetchedAll); // keep on processing until we fetched all scheduled tasks.

    if (ranAtLeastOne) {
        lastExecutionTime = ScheduledFutureTask.nanoTime();
    }
    afterRunningAllTasks();
    return ranAtLeastOne;
}

进入runAllTasksFrom(taskQueue)这个方法

protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
        Runnable task = pollTaskFrom(taskQueue);
        if (task == null) {
            return false;
        }
        for (;;) {
            safeExecute(task);
            task = pollTaskFrom(taskQueue);
            if (task == null) {
                return true;
            }
        }
    }

pollTaskFrom(taskQueue);从队列中拿出来一个 根据上面写的这里就是拿出一个线程

然后看这个方法safeExecute(task);

  protected static void safeExecute(Runnable task) {
        try {
            task.run();
        } catch (Throwable t) {
            logger.warn("A task raised an exception. Task: {}", task, t);
        }
    }



执行该线程run方法 之前加入了一个线程 到这里 我们返回去看那个线程任务 做了什么

回到

eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
这里 然后进入egister0(promise);查看



private void register0(ChannelPromise promise) {
            try {
                // check if the channel is still open as it could be closed in the mean time when the register
                // call was outside of the eventLoop
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                doRegister();
                neverRegistered = false;
                registered = true;

            // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the
            // user may already fire events through the pipeline in the ChannelFutureListener.
            pipeline.invokeHandlerAddedIfNeeded();

            safeSetSuccess(promise);
            pipeline.fireChannelRegistered();
            // Only fire a channelActive if the channel has never been registered. This prevents firing
            // multiple channel actives if the channel is deregistered and re-registered.
            if (isActive()) {
                if (firstRegistration) {
                    pipeline.fireChannelActive();
                } else if (config().isAutoRead()) {
                    // This channel was registered before and autoRead() is set. This means we need to begin read
                    // again so that we process inbound data.
                    //
                    // See https://github.com/netty/netty/issues/4805
                    beginRead();
                }
            }
        } catch (Throwable t) {
            // Close the channel directly to avoid FD leak.
            closeForcibly();
            closeFuture.setClosed();
            safeSetFailure(promise, t);
        }
    }

doRegister();进入这个方法 不知道哪个实现类 使用断点 断点进入AbstractNioChannel这个类中

@Override
protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try {
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
            return;
        } catch (CancelledKeyException e) {
            if (!selected) {
                // Force the Selector to select now as the "canceled" SelectionKey may still be
                // cached and not removed because no Select.select(..) operation was called yet.
                eventLoop().selectNow();
                selected = true;
            } else {
                // We forced a select operation on the selector before but the SelectionKey is still cached
                // for whatever reason. JDK bug ?
                throw e;
            }
        }
    }
}

selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);

javaChannel() 这里返回的之前创建的ServerSocketChannel

所以这行代码就相当于serverSocket.register(selector, SelectionKey.OP_ACCEPT);这一句 让一个ServerSocketChannel 跟一个selector进行绑定

以上 写的netty服务端启动时创建ServerSocketChannel、创建selector、ServerSocketChannel 跟 selector进行绑定、 两个线程模型EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(8);


pipeline模型
请添加图片描述

netty线程模型 以上的源码 只写了NioEvectLoop里面的Selector跟TaskQueue还有 select、runAlTasks
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值