Netty之EventLoop

EventLoop:英译事件循环器,感觉起来就是是不停的处理事件
EventLoopGroup:事件循环器组,感觉就是一大推的EventLoop处理事件。那么究竟是怎么回事呢?往下面看看

本篇文章先通过查看EventLoop和EventLoopGroup实现的部分细节,然后分析我们在使用代码的启动流程,当然主要了解NioEventLoop和NioEventLoopGroup

1.EventLoopGoup

​ 首先,我们先纵览一下EventLoopGroup 的类结构图,如下图所示:

image

从上面图中先分析下EventLoopGroup有哪些功能:

  • 首先通过ScheduledExecutorService发现使用的jdk的api,包含了调度任务的定时或某种频率执行任务,
  • EventExecutorGoup 除了添加了迭代功能,next()和shutdown的功能等就是继承ScheduledExecutorService相关功能了
  • EventLoopGroup 主要的功能有next获取下一个NextLoop,和register注册服务,类似将某一个channel注册到具体的EventLoop中
   EventLoop next();
   ChannelFuture register(Channel channel);

然后我们接着分析实现细节

1.1 AbstractEventExecutorGroup

明显发现没有成员变量,只有部分接口实现。可以简单的发现全部都是通过next()调用调度任务的方法,意味着next()就表示线程和线程池。所以接下来就需要看看next的实现了

public abstract class AbstractEventExecutorGroup implements EventExecutorGroup {
    @Override
    public Future submit(Runnable task) {
        return next().submit(task);
    }

    @Override
    public  Future submit(Runnable task, T result) {
        return next().submit(task, result);
    }

    @Override
    public  Future submit(Callable task) {
        return next().submit(task);
    }

    @Override
    public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) {
        return next().schedule(command, delay, unit);
    }
....

1.2 MultithreadEventExecutorGroup

继续看成员变量

public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {

    private final EventExecutor[] children;   //持有 多个事件执行器数组
    private final Set readonlyChildren;  //只读执行器列表
    private final AtomicInteger terminatedChildren = new AtomicInteger();  //结束的执行器个数
    private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
    private final EventExecutorChooserFactory.EventExecutorChooser chooser;    //执行器选择器
}

核心API看下

    //构造器中数据初始化
    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());
        }
        //一个线程对应一个eventExecutor
        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 terminationListener = new FutureListener() {
            @Override
            public void operationComplete(Future future) throws Exception {
                //所有的线程都关闭的状态
                if (terminatedChildren.incrementAndGet() == children.length) {
                    terminationFuture.setSuccess(null);
                }
            }
        };
        //添加事件监听器
        for (EventExecutor e: children) {
            e.terminationFuture().addListener(terminationListener);
        }

         //由当前的线程组生成只读readOnlyChildren
        Set childrenSet = new LinkedHashSet(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

    //next方法实现,很明显是通过上面生成的chooser方法从children数组中选择一个执行事件执行器(线程)
    @Override
    public EventExecutor next() {
        return chooser.next();
    }
 
 

1.3 MultithreadEventLoopGroup

这个类比较简单,继承了MultithreadEventExecutorGroup的功能,然后实现了EventLoopGroup功能(主要是注册和next返回eventLoop)。
主要实现功能有几点:

  • 1) 构造默认的线程数量
  • 2)调用next()返回EventLoop,而不是EventExector(EventLoop是子接口)
  • 3)调用next()的register完成注册功能
    -4)仍然将父类留下来的newChild留给子类实现
public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(MultithreadEventLoopGroup.class);

    private static final int DEFAULT_EVENT_LOOP_THREADS;

    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);
        }
    }
  protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
    }

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

    @Override
    protected abstract EventLoop newChild(Executor executor, Object... args) throws Exception;

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

1.4 NioEventLoopGroup

这个类就更加简单了,除了构造方法就看newChild的实现了

public class NioEventLoopGroup extends MultithreadEventLoopGroup {

// 。。。省略
// 主要是线程大小,执行器,selector的提供者以及选择策略,还有拒接处理器
//不过我们平时用的多的就是设置线程数量了,拒绝策略,最多还有线程的命名了
 public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
                             final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory,
                             final RejectedExecutionHandler rejectedExecutionHandler) {
        super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory, rejectedExecutionHandler);
    }

    @Override
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
      //返回一个NioEventLoop,再次应征了EventLoopGroup就是多个EventLoop的组合,每一个EventLoop就是一个线程
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
    }

总结下:上面的EventLoopGoup功能很明确:

  • 1)构造一组EventLoop池,初始化chooser,调用next()返回不同的EventLoop
    1. 持有调度功能,不过是通过next()获取的EventLoop实现的
  • 3)含有register功能,同样也是需要EventLoop实现

2.EventLoop

EventLoopGroup的分析告诉我们,事件处理还是需要我们EventLoop来做具体实现,上面Group只是管理EventLoop的创建和调用;就是线程池和线程的概念,只是包装了一层壳罢了。具体实现的情况继续分析:

先看类继承图


image

图中很明显的发现我们的EventLoop接口继承了EventLoopGroup,说明我们EventLoop除了拥有上面的所有功能还做了功能增强。

2.1 AbstractEventExecutor

主要看看这个parent成员变量,这个就将EventLoop和EventLoopGroup给联系起来了,EventLoopGroup作为父类被EventLoop给持有

public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEventExecutor.class);

    static final long DEFAULT_SHUTDOWN_QUIET_PERIOD = 2;
    static final long DEFAULT_SHUTDOWN_TIMEOUT = 15;
    //持有父类
    private final EventExecutorGroup parent;

    //netxt()返回自身,相对group明显不同
    @Override
    public EventExecutor next() {
        return this;
    }
    //通过英文名称表示当前线程 是否处于事件循环中(线程执行)了
    @Override
    public boolean inEventLoop() {
      //具体实现留给子类了
        return inEventLoop(Thread.currentThread());
    }

2.2 AbstractScheduledEventExecutor

功能很明确主要是Schedule功能,持有一个调度队列,

  • 对于任务队列有crud功能,
  • 另外实现了就是调度任务 执行大体功能了,核心执行留给子类实现
public abstract class AbstractScheduledEventExecutor extends AbstractEventExecutor {

    Queue> scheduledTaskQueue;
    Queue> scheduledTaskQueue() {
        if (scheduledTaskQueue == null) {
            scheduledTaskQueue = new PriorityQueue>();
        }
        return scheduledTaskQueue;
    }
  ....

  //查看调度任务
   final ScheduledFutureTask peekScheduledTask() {
        Queue> scheduledTaskQueue = this.scheduledTaskQueue;
        if (scheduledTaskQueue == null) {
            return null;
        }
        return scheduledTaskQueue.peek();
    }

     //执行某一个调度任务
    @Override
    public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) {
        ObjectUtil.checkNotNull(command, "command");
        ObjectUtil.checkNotNull(unit, "unit");
        if (delay < 0) {
            delay = 0;
        }
        return schedule(new ScheduledFutureTask(
                this, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
    }

    //执行调度任务,按时间间隔
   @Override
    public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
        ObjectUtil.checkNotNull(command, "command");
        ObjectUtil.checkNotNull(unit, "unit");
        if (initialDelay < 0) {
            throw new IllegalArgumentException(
                    String.format("initialDelay: %d (expected: >= 0)", initialDelay));
        }
        if (period <= 0) {
            throw new IllegalArgumentException(
                    String.format("period: %d (expected: > 0)", period));
        }

        return schedule(new ScheduledFutureTask(
                this, Executors.callable(command, null),
                ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), unit.toNanos(period)));
    }


    //上面的最终执行会交给
   ScheduledFuture schedule(final ScheduledFutureTask task) {
        if (inEventLoop()) {  
            scheduledTaskQueue().add(task);   //会添加到队列中
        } else {
            execute(new Runnable() {   //这里交给子类实现
                @Override
                public void run() {  //目的还是运行添加到队列中
                    scheduledTaskQueue().add(task);
                }
            });
        }

        return task;
    }
}

2.3 SingleThreadEventExecutor

这个才是关键核心实现类,从名称也可以发现单线程的事件执行器。主要是持有一个线程的应用,然后使用当前线程的做某些处理,也是最核心的。

先看成员变量,可以发现线程,线程任务,线程参数等变量。

public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
    //线程pending的最大任务数量了
    static final int DEFAULT_MAX_PENDING_EXECUTOR_TASKS = Math.max(16,
            SystemPropertyUtil.getInt("io.netty.eventexecutor.maxPendingTasks", Integer.MAX_VALUE));

    private static final InternalLogger logger =
            InternalLoggerFactory.getInstance(SingleThreadEventExecutor.class);
    
   //线程状态了
    private static final int ST_NOT_STARTED = 1;
    private static final int ST_STARTED = 2;
    private static final int ST_SHUTTING_DOWN = 3;
    private static final int ST_SHUTDOWN = 4;
    private static final int ST_TERMINATED = 5;

    private static final Runnable WAKEUP_TASK = new Runnable() {
        @Override
        public void run() {
            // Do nothing.
        }
    };
    private static final Runnable NOOP_TASK = new Runnable() {
        @Override
        public void run() {
            // Do nothing.
        }
    };
    //原子性处理线程 state值了
    private static final AtomicIntegerFieldUpdater STATE_UPDATER =
            AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state");
    //原子性处理线程参数了
    private static final AtomicReferenceFieldUpdater PROPERTIES_UPDATER =
            AtomicReferenceFieldUpdater.newUpdater(
                    SingleThreadEventExecutor.class, ThreadProperties.class, "threadProperties");
    //任务队列
    private final Queue taskQueue;
   //线程了
    private volatile Thread thread;
    @SuppressWarnings("unused")
    private volatile ThreadProperties threadProperties;
    private final Executor executor;
    private volatile boolean interrupted;

    private final Semaphore threadLock = new Semaphore(0);
    private final Set shutdownHooks = new LinkedHashSet();
    private final boolean addTaskWakesUp;
    private final int maxPendingTasks;
    private final RejectedExecutionHandler rejectedExecutionHandler;

    private long lastExecutionTime;

    @SuppressWarnings({ "FieldMayBeFinal", "unused" })
    private volatile int state = ST_NOT_STARTED;

    private volatile long gracefulShutdownQuietPeriod;
    private volatile long gracefulShutdownTimeout;
    private long gracefulShutdownStartTime;

    private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
...
}
    //简单看下构造器
    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 = ObjectUtil.checkNotNull(executor, "executor");
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

接着我们再瞧瞧任务执行实现:

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

        boolean inEventLoop = inEventLoop();  //这里就是eventLoop线程和执行线程是否同一个
        if (inEventLoop) {
            addTask(task);  //满足当前线程,将任务放入队列中
        } else {
            startThread(); // 开启一个线程
            addTask(task); //然后把任务添加到后台任务与对垒中
            if (isShutdown() && removeTask(task)) {
                reject();
            }
        }

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


  @Override
    public boolean inEventLoop(Thread thread) {
        return thread == this.thread;
    }
   //开启线程
   private void startThread() {
        if (state == ST_NOT_STARTED) {
            //原子操作,保证只启动一次
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                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) {
                        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 (;;) {
                            //hooks 对于关闭
                            if (confirmShutdown()) {
                                break;
                            }
                        }
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.release();
                            if (!taskQueue.isEmpty()) {
                                logger.warn(
                                        "An event executor terminated with " +
                                                "non-empty task queue (" + taskQueue.size() + ')');
                            }

                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

2.4 SingleThreadEventLoop

相对SingleThreadEventExecutor多实现了EventLoop功能,这个提供parent接口,然后也是持有一个任务队列信息。


public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {

    protected static final int DEFAULT_MAX_PENDING_TASKS = Math.max(16,
            SystemPropertyUtil.getInt("io.netty.eventLoop.maxPendingTasks", Integer.MAX_VALUE));

    private final Queue tailTasks;
.....
}

2.5 NioEventLoop

主要是核心API --> run方法

public final class NioEventLoop extends SingleThreadEventLoop {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioEventLoop.class);

    private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization.

    private static final boolean DISABLE_KEYSET_OPTIMIZATION =
            SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false);

    private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3;
    private static final int SELECTOR_AUTO_REBUILD_THRESHOLD;

    private final IntSupplier selectNowSupplier = new IntSupplier() {
        @Override
        public int get() throws Exception {
            return selectNow();
        }
    };
    private final Callable pendingTasksCallable = new Callable() {
        @Override
        public Integer call() throws Exception {
            return NioEventLoop.super.pendingTasks();
        }
    };

    /**
     * The NIO {@link Selector}.
     */
    private Selector selector;   //核心的选择器
    private Selector unwrappedSelector;
    private SelectedSelectionKeySet selectedKeys;

    private final SelectorProvider provider;

    /**
     * Boolean that controls determines if a blocked Selector.select should
     * break out of its selection process. In our case we use a timeout for
     * the select method and the select method will block for that time unless
     * waken up.
     */
    private final AtomicBoolean wakenUp = new AtomicBoolean();

    private final SelectStrategy selectStrategy;

    private volatile int ioRatio = 50;
    private int cancelledKeys;
    private boolean needsToSelectAgain;

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
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }
    }

如下事NIO逻辑操作,只有NioEventLoop收到退出指令才会退出,否则一直下面方法一直执行下去,这也是NIO线程的执行方式。

 @Override
protected void run() {
        for (;;) {
            try {
              //selectorNowSupplier和hasTasks判断是否有需要处理的channel
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    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:
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;  //表示IO的执行比例  
                if (ioRatio == 100) {    //IO如果是100,那么全部优先执行完IO在执行调度任务
                    try {    
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        runAllTasks();
                    }
                } else {
                    final long ioStartTime = System.nanoTime();
                    try {
                        processSelectedKeys(); //先执行IO任务
                    } finally {
                         //这里给出了IO执行的时长,然后根据IO比例计算调度任务应该执行的超时时长
                        // 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);
            }
        }

IO执行流程:主要分析主流程,其他支路没有分析,如果感兴趣可以自己分析下

    
   private void processSelectedKeys() {
        if (selectedKeys != null) {
            processSelectedKeysOptimized();
        } else {
            //执行这个    
            processSelectedKeysPlain(selector.selectedKeys());
        }
    }

    private void processSelectedKeysPlain(Set selectedKeys) {
        // check if the set is empty and if so just return to not create garbage by
        // creating a new Iterator every time even if there is nothing to process.
        // See https://github.com/netty/netty/issues/597
        if (selectedKeys.isEmpty()) {
            return;
        }

        Iterator i = selectedKeys.iterator();
        for (;;) {
            final SelectionKey k = i.next();
            final Object a = k.attachment();
            i.remove();

            if (a instanceof AbstractNioChannel) {
                //之前我们分析channel有提到附件是把自身给当做附件的
                processSelectedKey(k, (AbstractNioChannel) a);
            } else {
                @SuppressWarnings("unchecked")
                NioTask task = (NioTask) a;
                processSelectedKey(k, task);
            }

            if (!i.hasNext()) {
                break;
            }

            if (needsToSelectAgain) {
                selectAgain();
                selectedKeys = selector.selectedKeys();

                // Create the iterator again to avoid ConcurrentModificationException
                if (selectedKeys.isEmpty()) {
                    break;
                } else {
                    i = selectedKeys.iterator();
                }
            }
        }
    }

   private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
                // 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 {
            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.
            //如果还有消息没有写出去,通过flush全部写出
            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());
        }
    }

调度任务执行:主要分析主流程,其他支路没有分析,如果感兴趣可以自己分析下,如下分析的是IO线程执行不是100%的情况下

  protected boolean runAllTasks(long timeoutNanos) {
        fetchFromScheduledTaskQueue();
        Runnable task = pollTask();
        if (task == null) {
            afterRunningAllTasks();
            return false;
        }

        final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
        long runTasks = 0;
        long lastExecutionTime;
        for (;;) {
            safeExecute(task); //直接调用task的run方法进行调用了
 
            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.
            if ((runTasks & 0x3F) == 0) {
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                if (lastExecutionTime >= deadline) {  //超时需要返回
                    break;
                }
            }

            task = pollTask();
            if (task == null) {  //任务执行完了也返回
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                break;
            }
        }

        afterRunningAllTasks();
        this.lastExecutionTime = lastExecutionTime;
        return true;
    }

总结一下:
EventLoop就是持有一个线程的执行器,执行的大体逻辑流程由SingleThreadEventExecutor实现,然后具体的IO流程实现有NioEventLoop来实现,从而完成IO任务和调度任务。

3.业务启动代码源码

我们业务代码一般服务端会初始化如下两个group,这里需要结合之前提到的Reactor模型,第一个bossGroup负责处理连接操作,后者处理具体的IO操作。

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);

我们就看看构造NioEventLoopGroup()做了什么事情?

 public NioEventLoopGroup(int nThreads) {
        this(nThreads, (Executor) null);
    }
 public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }
// 接着继续看,执行到了MultithreadEventLoopGroup
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
 //这里就回到我们介绍eventGroup的信息了。
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());
        }
        //根据线程数量构建对应的EventExecutor数目
        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 terminationListener = new FutureListener() {
            @Override
            public void operationComplete(Future future) throws Exception {
                if (terminatedChildren.incrementAndGet() == children.length) {
                    terminationFuture.setSuccess(null);
                }
            }
        };

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

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

                            
                        
                    
                    
                    

你可能感兴趣的:(Netty之EventLoop)