4.1.36这篇netty讲懂了-- Netty源码剖析

NettyServer端源码

根据代码演示分析

public static void main(String[] args) throws InterruptedException {
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(parentGroup, childGroup)
                    // 指定要创建Channel类型
                     .channel(NioServerSocketChannel.class)
                     .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 获取channel中的Pipeline
                            ChannelPipeline pipeline = ch.pipeline();
                            // StringDecoder:字符串解码器,将Channel中的ByteBuf数据解码为String
                            pipeline.addLast(new StringDecoder());
                            // StringEncoder:字符串编码器,将String编码为将要发送到Channel中的ByteBuf
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new SomeServerHandler());
                        }
                    });
            ChannelFuture future = bootstrap.bind(8080).sync();
            System.out.println("服务器已启动");
            future.channel().closeFuture().sync();
        } finally {
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }

4.1.36源码从绑定开始分析:

Netty服务端启动

创建指定channel

在执行bind之前,先执行了channel(NioServerSocketChannel.class) ,先创建指定的channel

【AbstractBootstrap.classpublic B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        // 返回一个channelFactory
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}

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

执行bind流程

private ChannelFuture doBind(final SocketAddress localAddress) {
        // 创建、初始化channel,并将其注册到Selector
        final ChannelFuture regFuture = initAndRegister();
        // 从异步结果中获取channel
        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.
            // 创建一个可修改的异步结果对象channelFuture
            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.
                        // 修改异步结果为:失败
                        promise.setFailure(cause);
                    } else {
                        // Registration was successful, so set the correct executor to use.
                        // See https://github.com/netty/netty/issues/2586
                        promise.registered();
                        // 绑定端口号
                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }

注册流程

initAndRegister 流程

final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            // 创建一个channel
            channel = channelFactory.newChannel();
            // 初始化channel
            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);
        }

        // 将当前channel注册给selector
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }
		return regFuture;
}

channelFactory.newChannel()流程

创建channel

public T newChannel() {
    try {
        // 使用反射机制,调用其无参构造器,创建channel
        return constructor.newInstance();
    } catch (Throwable t) {
        throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
    }
}

最终调用NioServerSocketChannel的无参构造函数

// 获取到一个全局性的provider
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

public NioServerSocketChannel() {
    // 我们Netty的channel实际上是对原生的NIO的channel的封装
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

// netty最终调用了 jdk原生nio,
private static ServerSocketChannel newSocket(SelectorProvider provider) {
    try {
        // 通过全局性的provider,创建一个原生的NIO的channel
        return provider.openServerSocketChannel();
    } catch (IOException e) {
        throw new ChannelException(
            "Failed to open a server socket.", e);
    }
 }

protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent);
    this.ch = ch;
    this.readInterestOp = readInterestOp;
    try {
        // 指定channel为非阻塞
        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);
    }
}
protected AbstractChannel(Channel parent) {
        this.parent = parent;
        // 为Netty的channel生成id
        id = newId();
        // 底层操作对象
        unsafe = newUnsafe();
        // 创建当前channel所绑定的channelPipeline
        pipeline = newChannelPipeline();
}

初始化channel

【ServerBootstrap】#init
@Override
void init(Channel channel) throws Exception {
        // 处理bootstrap中的option设置属性
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
            setChannelOptions(channel, options, logger);
        }

        // 处理bootstrap中的attr设置属性
        final Map<AttributeKey<?>, Object> attrs = attrs0();
        synchronized (attrs) {
            // 将bootstrap中设置的所有attr属性配置给channel
            for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }

        // 向pipeline中添加处理器
        ChannelPipeline p = channel.pipeline();

        // 获取bootstrap中设置的所有child开头的属性
        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));
        }

        // ChannelInitializer是一个处理器,其存在的意义是,为pipeline添加其它处理器
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) throws Exception {
                final ChannelPipeline pipeline = ch.pipeline();
                // 获取bootstrap中配置的handler()
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                // ch.eventLoop()是获取到当前channel所绑定的evenLoop
                // 然后再使用该eventLoop所绑定的线程来执行指定的任务
                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        // 向pipeline中添加ServerBootstrapAcceptor处理器
                        // 该处理器用于处理client的连接
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
   }
   
static void setChannelOptions(
    Channel channel, Map<ChannelOption<?>, Object> options, InternalLogger logger) {
    // 遍历通过bootstrap设置的所有option
    for (Map.Entry<ChannelOption<?>, Object> e: options.entrySet()) {
        setChannelOption(channel, e.getKey(), e.getValue(), logger);
    }
}

ServerBootstrapAcceptor.class

ServerBootstrapAcceptor(
    final Channel channel, EventLoopGroup childGroup, ChannelHandler childHandler,
    Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs) {
    this.childGroup = childGroup;
    this.childHandler = childHandler;
    this.childOptions = childOptions;
    this.childAttrs = childAttrs;

    // Task which is scheduled to re-enable auto-read.
    // It's important to create this Runnable before we try to submit it as otherwise the URLClassLoader may
    // not be able to load the class because of the file limit it already reached.
    //
    // See https://github.com/netty/netty/issues/1328
    enableAutoReadTask = new Runnable() {
        @Override
        public void run() {
            channel.config().setAutoRead(true);
        }
    };
}

// 当client发送来连接请求时,会触发channelRead()方法的执行
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    // 注意,这里client发送来的就是连接当前Server的子channel
    final Channel child = (Channel) msg;

    // 初始化这个子channel
    // 对用于处理client 读写请求的子channel设置handler,以及添加到对应的selector中
    child.pipeline().addLast(childHandler);

    setChannelOptions(child, childOptions, logger);

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

    try {
        // 将当前子channel注册到selector
        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);
    }
 }

channel注册到selector上

ChannelFuture regFuture = config().group().register(channel); 将当前channel注册给selector,这里指的是parentGroup

【MultithreadEventLoopGroup.class】
@Override
public ChannelFuture register(Channel channel) {
    // 从parentGroup中根据算法选择一个eventLoop来完成注册
    return next().register(channel);
}

【AbstractChannel.class】中的【AbstractUnsafe.class】#register
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;
            }

            // 这里实现了channel与eventLoop的绑定
            AbstractChannel.this.eventLoop = eventLoop;

            // 判断当前正在执行的线程是否是当前eventLoop所绑定的线程
            if (eventLoop.inEventLoop()) {
                // 若当前线程是eventLoop绑定线程,则直接让这个线程来完成注册操作
                register0(promise);
            } else {
                // 当前线程不是eventLoop绑定线程,则首先会创建一个线程,
                // 然后使用这个新创建的eventLoop线程来完成注册
                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);
                }
            }
}

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.
                // 触发handlerAdded()方法的执行
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                // 触发channelRegistered()方法的执行
                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.

                // 若当前channel是激活状态,且是第一次注册,
                // 则触发channelActive()的执行
                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】#doRegister
protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                // 其实netty的channel的注册,本质上是原生的nio的channel的注册
                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;
                }
            }
        }
 }
在执行bind之前,先执行了channel(NioServerSocketChannel.class)
【AbstractBootstrap】#bind
	|--dobind
		|-- final ChannelFuture regFuture = initAndRegister(); 创建、初始化channel,并将其注册到selector
			|-- channel = channelFactory.newChannel(); //创建一个channel
				|--【ReflectiveChannelFactory】#newChannel
					|--constructor.newInstance(); 使用反射机制 调用其无参构造器 在调用之前,这里其实就是先执行了NioServerSocketChannel.class 这个方法,创建了

NioEventLoop分析

NioEventLoopGroup与NioEventLoop

​ 两个类都最后都继承自Executor。所以都是一个执行器

​ NioEventLoopGroup本身是个执行器(Executor),里面还包含了executor,可以调用execute,是线程池实现的execute

​ NioEventLoop本身是个执行器(Executor),里面还包含了executor,子executor里面又包含了线程,这个线程是总的executor绑定的factory创建的,可以调用execute,是线程实现的execute

​ EventLoop绑定的线程是在什么时候创建的?执行注册的时候创建的

在这里插入图片描述

NioEventLoopGroup创建

new NioEventLoopGroup 跟进去

跳转到 MultithreadEventLoopGroup

private static final int DEFAULT_EVENT_LOOP_THREADS;
static {
        // 该默认值为当前主机逻辑处理器数量的2倍
        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);
        }
}
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}


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,这个executor将来会为每一个EventLoop创建一个子executor,
            // 然后再使用当前这个总executor所绑定的线程Factory为每个子executor再创建一个线程
            // 与这个子executor绑定
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }

        // 使用一个数组来存放当前group中所包含的eventLoop
        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                // 创建每一个eventLoop实例,并初始化到相应的数组元素中
                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;
                        }
                    }
                }
            }
        }

        // 创建一个EventLoop数组元素的选择器
        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);
}

newDefaultThreadFactory()跟进去

【DefaultThreadFactory.classpublic DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
        if (poolName == null) {
            throw new NullPointerException("poolName");
        }
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                    "priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
        }
        // 最终获取到的prefix的值为    nioEventLoopGroup-线程池id-
        prefix = poolName + '-' + poolId.incrementAndGet() + '-';
        this.daemon = daemon;
        this.priority = priority;
        this.threadGroup = threadGroup;
    }

newChild(executor, args); 跟进去

【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 构造器

【NioEventLoop】
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;
        // 创建一个Selector元组
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
}

super 跟进去调用SingleThreadEventLoop 构造器

【SingleThreadEventLoop】
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        // 创建一个尾部任务队列,收尾任务存放在这里
        tailTasks = newTaskQueue(maxPendingTasks);
}

super 跟进去调用SingleThreadEventExecutor构造器

protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = Math.max(16, maxPendingTasks);
        // 使用总的executor为当前eventLoop创建一个executor  this.executor是eventLoop中的executor,executor是总的
        this.executor = ThreadExecutorMap.apply(executor, this);
        // 创建一个任务队列
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}

ThreadExecutorMap.apply(executor, this);跟进去

【ThreadExecutorMap】
	/**
     *
     * @param executor  总的executor
     * @param eventExecutor  当前正在创建的eventLoop
     * @return
     * 线程套线程,相当于责任链 这时候才创建了个匿名的executor,这个new Executor现在不会执行,只有在任务开始的时候才会执行
     */
public static Executor apply(final Executor executor, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(executor, "executor");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Executor() {
            @Override
            public void execute(final Runnable command) {
                // executor.execute()会使用这个总的executor所绑定的线程factory创建一个线程
                executor.execute(apply(command, eventExecutor));
            }
        };
}

public static Runnable apply(final Runnable command, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(command, "command");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Runnable() {
            @Override
            public void run() {
                // 为了保证线程安全,这里为当前线程指定其所关联的eventLoop
                setCurrentEventExecutor(eventExecutor);
                try {
                    // 真正任务的执行是在这里开始的
                    command.run();
                } finally {
                    setCurrentEventExecutor(null);
                }
            }
        };
}

有任务的时候就去执行上面那个匿名的executor

NioEventLoop添加任务

举例:register时候线程创建,其他的任务会直接放入队列中等待执行

// 判断当前正在执行的线程是否是当前eventLoop所绑定的线程
            if (eventLoop.inEventLoop()) {
                // 若当前线程是eventLoop绑定线程,则直接让这个线程来完成注册操作
                register0(promise);
            } else {
                // 当前线程不是eventLoop绑定线程,则首先会创建一个线程,
                // 然后使用这个新创建的eventLoop线程来完成注册
                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);
                }
            }

eventLoop.execute跟进去

【SingleThreadEventExecutor】#execute
 @Override
    public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }
        // 若当前线程是当前EventLoop所绑定的线程,则返回true,否则返回false
        boolean inEventLoop = inEventLoop();
        // 将任务添加到taskQueue
        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);
        }
} startThread();

startThread();方法跟进去

private void startThread() {
        if (state == ST_NOT_STARTED) {
            // 通过CAS将状态修改为已启动
            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);
                }
            }
        }
}

private void doStartThread() {
        assert thread == null;
        // 调用当前EventLoop所包含的executor(子executor)
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    // 进行selector的选择,然后执行三类任务
                    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);
                        }
                    }
                }
            }
        });
    }

// 调用当前EventLoop所包含的executor(子executor)
executor.execute(new Runnable()

这时候就会去调用刚才那个匿名创建的 Executor 进来

【ThreadExecutorMap】
	/**
     *
     * @param executor  总的executor
     * @param eventExecutor  当前正在创建的eventLoop
     * @return
     * 线程套线程,相当于责任链 这时候才创建了个匿名的executor,这个new Executor现在不会执行,只有在任务开始的时候才会执行
     */
public static Executor apply(final Executor executor, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(executor, "executor");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Executor() {
            @Override
            public void execute(final Runnable command) {
                // executor.execute()会使用这个总的executor所绑定的线程factory创建一个线程
                executor.execute(apply(command, eventExecutor));
            }
        };
}

最终会调用走到

【ThreadPerTaskExecutor】#execute
@Override
    public void execute(Runnable command) {
        // 这里会创建一个线程,并且启动这个线程,就是执行command的run()方法
        threadFactory.newThread(command).start();
}
【DefaultThreadFactory】#newThread
@Override
    public Thread newThread(Runnable r) {
        // 创建一个线程,使用线程的名称为  nioEventLoopGroup-线程池id-线程id
        Thread t = newThread(FastThreadLocalRunnable.wrap(r), prefix + nextId.incrementAndGet());
        try {
            if (t.isDaemon() != daemon) {
                t.setDaemon(daemon);
            }

            if (t.getPriority() != priority) {
                t.setPriority(priority);
            }
        } catch (Exception ignored) {
            // Doesn't matter even if failed to set.
        }
        return t;
    }

NioEventLoop任务执行

SingleThreadEventExecutor.this.run();

【NioEventLoop】#run
protected void run() {
        // 永久循环
        for (;;) {
            try {
                try {
                    // ------------------------- 1 selector选择 -------------------
                    // 计算出选择selector策略
                    switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                        case SelectStrategy.CONTINUE:  // NioEventLoop不支持
                            continue;

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

                        case SelectStrategy.SELECT:   // NioEventLoop支持的唯一策略
                            // 若执行这里,说明当前任务队列中没有任务
                            select(wakenUp.getAndSet(false));

                            // 若当前线程刚被唤醒,selector立即将其选择的结果返回给我们
                            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;
                // ioRatio用于控制IO处理与任务队列中任务的处理所占时间比例
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100) {
                    try {
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        runAllTasks();
                    }
                } else {
                    // ------------------------- 2 处理就绪的IO -------------------
                    // IO操作的开始时间
                    final long ioStartTime = System.nanoTime();
                    try {
                        processSelectedKeys();
                    } finally {
                        // ------------------------- 3 执行任务队列中的任务 -------------------
                        // Ensure we always run tasks.
                        // IO操作总用时
                        final long ioTime = System.nanoTime() - ioStartTime;
                        // ioTime * [(100 - ioRatio) / ioRatio]
                        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);
            }
        }
    }

selectStrategy.calculateStrategy(selectNowSupplier, hasTasks()) 跟进去

先看下selectNowSupplier

private final IntSupplier selectNowSupplier = new IntSupplier() {
        @Override
        public int get() throws Exception {
            // 非阻塞选择
            return selectNow();
        }
};

int selectNow() throws IOException {
        try {
            // 非阻塞选择
            return selector.selectNow();
        } finally {
            // restore wakeup state if needed
            // wakenUp为true,表示当前eventLoop所绑定的线程刚刚被唤醒
            // wakenUp为false,表示当前eventLoop所绑定的线程即将被阻塞
            if (wakenUp.get()) {
                // 立即将选择的结果写入到当前eventLoop的集合
                selector.wakeup();
            }
        }
}
【SingleThreadEventLoop】
@Override
protected boolean hasTasks() {
        // 判断 taskQueue  或  tailTasks  任务队列是否为空
        return super.hasTasks() || !tailTasks.isEmpty();
}

calculateStrategy跟进来

【DefaultSelectStrategy】#calculateStrategy
 @Override
public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
        // 若任务队列有任务,则马上进行非阻塞选择
        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;
}

select(wakenUp.getAndSet(false));跟进来,执行这里,说明当前任务队列中没有任务

private void select(boolean oldWakenUp) throws IOException {
        Selector selector = this.selector;
        try {
            // 计数器,记录当前选择执行的轮数
            int selectCnt = 0;
            // 获取当前select()开始的时间点
            long currentTimeNanos = System.nanoTime();
            // delayNanos():从定时任务队列中取出一个定时任务,计算其还有多久就要执行了
            // selectDeadLineNanos : 表示这个定时任务要开始执行的时间点
            long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos);

            for (;;) {
                // --------------------- 1 处理定时任务 ------------------
                // 对于马上就要到执行时间的定时任务,立即进行选择
                long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L;
                if (timeoutMillis <= 0) {
                    if (selectCnt == 0) {
                        // 非阻塞选择
                        selector.selectNow();
                        selectCnt = 1;
                    }
                    break;
                }

                // --------------------- 2 在选择期间,任务队列中有新任务加入 ------------------
                // 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;
                }

                // --------------------- 3 阻塞式选择 ------------------
                // select()方法结束的条件:
                // 1)有channel被选择
                // 2)seleter.wakeup()被调用
                // 3)当前线程被打断
                // 4)阻塞时间超时
                // 5)其实这里还有一个结束的条件:
                // 当长时间没有就绪的channel时,轮询会出现长时间空转,从而会导致CPU占用率飙升,
                // 此时会使select()结束
                // 注意,timeoutMillis 在这里是作为select()的阻塞时长的
                int selectedKeys = selector.select(timeoutMillis);
                selectCnt ++;

                if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {
                    // - Selected something,         有channel被选择
                    // - waken up by user, or     或 seleter.wakeup()被调用
                    // - the task queue has a pending task.   // 任务队列中有挂起的任务
                    // - a scheduled task is ready for processing   // 有定时任务
                    break;
                }

                // --------------------- 4 处理Nio中的Bug ------------------
                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;
                }


                // 代码走到这里,说明select()结束的条件是4)或5)

                // 记录当前时间
                long time = System.nanoTime();
                // 下面的式子等价于:
                // time - currentTimeNanos >= TimeUnit.MILLISECONDS.toNanos(timeoutMillis)
                // 当前for循环已经执行的时长 >= 阻塞时长
                // 若if的这个条件成立,说明前面的select()方法是通过条件4)结束的
                if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) {
                    // timeoutMillis elapsed without anything selected.
                    selectCnt = 1;

                    // 执行else说明  当前for循环已经执行的时长 < 阻塞时长 ,说明前面的select()是通过
                    // 条件5)结束的。若空转次数大于等于指定的阈值512,则重新构建selector
                } 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
        }
}

processSelectedKeys 跟进来

private void processSelectedKeys() {
    // 若selectedKeys是优化过的
    if (selectedKeys != null) {
        // 优化的
        processSelectedKeysOptimized();
    } else {
        // 一般的
        processSelectedKeysPlain(selector.selectedKeys());
    }
}

private void processSelectedKeysOptimized() {
    for (int i = 0; i < selectedKeys.size; ++i) {
        final SelectionKey k = selectedKeys.keys[i];
        // null out entry in the array to allow to have it GC'ed once the Channel close
        // See https://github.com/netty/netty/issues/2363
        // 其就相当于对set集合处理时,要将处理过的key从set集合中删除是一样的,
        // 为了避免对key的重复处理
        selectedKeys.keys[i] = null;

        // 对于NioEventLoop,key中的附件attachement中存放的是当前key所关联的NioChannel
        final Object a = k.attachment();

        if (a instanceof AbstractNioChannel) {
            // 处理当前遍历的key
            processSelectedKey(k, (AbstractNioChannel) a);
        } else {
            @SuppressWarnings("unchecked")
            NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
            processSelectedKey(k, task);
        }

        if (needsToSelectAgain) {
            // null out entries in the array to allow to have it GC'ed once the Channel close
            // See https://github.com/netty/netty/issues/2363
            selectedKeys.reset(i + 1);

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

private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
    final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
    // 处理key失效的情况
    if (!k.isValid()) {
        final EventLoop eventLoop;
        try {
            eventLoop = ch.eventLoop();
        } catch (Throwable ignored) {
            // If the channel implementation throws an exception because there is no event loop, we ignore this
            // because we are only trying to determine if ch is registered to this event loop and thus has authority
            // to close ch.
            return;
        }
        // Only close ch if ch is still registered to this EventLoop. ch could have deregistered from the event loop
        // and thus the SelectionKey could be cancelled as part of the deregistration process, but the channel is
        // still healthy and should not be closed.
        // See https://github.com/netty/netty/issues/5125
        if (eventLoop != this || eventLoop == null) {
            return;
        }
        // close the channel if the key is not valid anymore
        unsafe.close(unsafe.voidPromise());
        return;
    }

    try {
        // 获取到当前key所有就绪的操作
        int readyOps = k.readyOps();
        // We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise
        // the NIO JDK channel implementation may throw a NotYetConnectedException.
        // 若就绪操作中包含连接操作,处理连接就绪
        if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
            // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
            // See https://github.com/netty/netty/issues/924
            int ops = k.interestOps();
            ops &= ~SelectionKey.OP_CONNECT;
            k.interestOps(ops);
            // 进行连接
            unsafe.finishConnect();
        }

        // Process OP_WRITE first as we may be able to write some queued buffers and so free memory.
        // 处理写就绪
        // 当将数据写入到buffer,那么当前channel就处于写就绪
        if ((readyOps & SelectionKey.OP_WRITE) != 0) {
            // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
            ch.unsafe().forceFlush();
        }

        // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
        // to a spin loop
        // 处理读就绪  或  接收连接就绪
        if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
            unsafe.read();
        }
    } catch (CancelledKeyException ignored) {
        unsafe.close(unsafe.voidPromise());
    }
}

runAllTasks 跟进来

【SingleThreadEventExecutor】#runAllTasks
protected boolean runAllTasks(long timeoutNanos) {
    // // 将所有定时任务队列中的任务添加到taskQueue
    fetchFromScheduledTaskQueue();
    // 从taskQueue中获取一个任务
    Runnable task = pollTask();
    // 若该任务为null,说明当前任务队列中没有任务了,
    // 此时执行tailTasks中的收尾任务
    if (task == null) {
        afterRunningAllTasks();
        return false;
    }

    // 计算taskQueue中所有任务执行完毕的时间
    final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
    long runTasks = 0;
    long lastExecutionTime;
    // 遍历执行taskQueue中的所有任务
    for (;;) {
        // 执行当前遍历的任务
        safeExecute(task);

        runTasks ++;

        // Check timeout every 64 tasks because nanoTime() is relatively expensive.
        // XXX: Hard-coded value - will make it configurable if it is really a problem.
        // 每64次任务检查一次超时
        if ((runTasks & 0x3F) == 0) {
            lastExecutionTime = ScheduledFutureTask.nanoTime();
            if (lastExecutionTime >= deadline) {
                break;
            }
        }

        task = pollTask();
        if (task == null) {
            lastExecutionTime = ScheduledFutureTask.nanoTime();
            break;
        }
    }  // end-for

    // 执行tailTasks中的收尾任务
    afterRunningAllTasks();
    this.lastExecutionTime = lastExecutionTime;
    return true;
}

fetchFromScheduledTaskQueue跟进去

// 将所有定时任务队列中的任务添加到taskQueue
private boolean fetchFromScheduledTaskQueue() {
    // 获取当前时间相对于定时任务实例创建时间的时长(定时任务实例已经存活了多久)
    long nanoTime = AbstractScheduledEventExecutor.nanoTime();
    // 从定时任务队列中取出一个最紧急的任务
    Runnable scheduledTask  = pollScheduledTask(nanoTime);
    while (scheduledTask != null) {
        // 在定时任务不空的前提下,将任务添加到taskQueue
        if (!taskQueue.offer(scheduledTask)) {
            // No space left in the task queue add it back to the scheduledTaskQueue so we pick it up again.
            // 若没有添加成功,则重新放回到定时任务队列
            scheduledTaskQueue().add((ScheduledFutureTask<?>) scheduledTask);
            return false;
        }
        // 从定时任务队列中再取出一个最紧急的任务
        scheduledTask  = pollScheduledTask(nanoTime);
    }
    return true;
}
【AbstractScheduledEventExecutor】#pollScheduledTask
protected final Runnable pollScheduledTask(long nanoTime) {
        assert inEventLoop();
        // 从定时任务队列中取一个任务
        Queue<ScheduledFutureTask<?>> scheduledTaskQueue = this.scheduledTaskQueue;
        ScheduledFutureTask<?> scheduledTask = scheduledTaskQueue == null ?
                                        null : scheduledTaskQueue.peek();
        if (scheduledTask == null) {
            return null;
        }

        // 若配置的需要推迟的时间比当前的时间还要小,说明这个任务早就应该执行了
        if (scheduledTask.deadlineNanos() <= nanoTime) {
            // 从定时任务队列中删除该任务
            scheduledTaskQueue.remove();
            // 返回该任务,以将其添加到taskQUeue去执行
            return scheduledTask;
        }
        return null;
}

pollTask();跟进去

protected static Runnable pollTaskFrom(Queue<Runnable> taskQueue) {
    // 从任务队列中取出一个任务,只要其不是一个唤醒任务,则直接返回
    for (;;) {
        Runnable task = taskQueue.poll();
        if (task == WAKEUP_TASK) {
            continue;
        }
        return task;
    }
}

afterRunningAllTasks();跟进来

【SingleThreadEventExecutor】#runAllTasks
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
        // 从任务队列中获取一个任务
        Runnable task = pollTaskFrom(taskQueue);
        if (task == null) {
            return false;
        }
        for (;;) {
            safeExecute(task);
            task = pollTaskFrom(taskQueue);
            // task为null,说明taskQueue中的任务全部执行完毕
            if (task == null) {
                return true;
            }
        }
}
protected static void safeExecute(Runnable task) {
        try {
            // 任务的run()最终在这里执行了
            task.run();
        } catch (Throwable t) {
            logger.warn("A task raised an exception. Task: {}", task, t);
        }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章