Netty source code analysis Series Three: Netty start of NioEventLoop create

introduction

From the beginning of this article, we take a reading Nettyof the source code to achieve, mainly for Nettythe core to achieve further sort out. But then again, if we look directly at Nettythe source code, they may not know where to start, then multiple source packages large and small, like a mess, a multitude of things. Therefore, this article from Nettystart to start, according to the startup process to gradually open the service Nettyof the mystery, clarifying Nettytechnical context.

  • NioEventLoopcreate
  • to sum up

Here Insert Picture Description
Today is the weekend, but the clock is still on time wake up tired himself. No work day, then have the class write blog, ha ha.
Below is Nettythe Reactorthread schematic model can facilitate understanding of this part of the follow-up article in this chart will continue to occur, mainly related to the contents of this article contains several of these steps.
Here Insert Picture Description
(Picture from the network)


A, NioEventLoop create

NettyService starts, the most important thing is ready to accept client connections. We look at each custom thread and bossthread to complete the task and process, as follows:
Here Insert Picture Description
Here Insert Picture Description
Here a list of some of the more important class names and their corresponding main functional description, so that everyone at the time reading the source code can quickly understand the corresponding class Features:

class effect
ServerBootstrap Server side, start the auxiliary class
NioEventLoop Nio event handler (Reactor model)
NioEventLoopGroup A group of Nio event handlers (Reactor model)

In the Nettysource pack, we first look io.netty.example.echopackage EchoServerclass that contains the Nettyservice starts the relevant code, source code and source code specific part of the analysis is shown below NOTE:

public final class EchoServer {

    static final boolean SSL = System.getProperty("ssl") != null;
    static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));

    public static void main(String[] args) throws Exception {
        // Configure SSL.
        final SslContext sslCtx;
        if (SSL) {
            SelfSignedCertificate ssc = new SelfSignedCertificate();
            sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        } else {
            sslCtx = null;
        }

        //处理连接事件
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //处理读以及写的事件
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        final EchoServerHandler serverHandler = new EchoServerHandler();
        try {
        	//服务引导类
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .option(ChannelOption.SO_BACKLOG, 100)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                 	 //初始化channel.pipeline
                     ChannelPipeline p = ch.pipeline();
                     if (sslCtx != null) {
                         p.addLast(sslCtx.newHandler(ch.alloc()));
                     }
                     //p.addLast(new LoggingHandler(LogLevel.INFO));
                     p.addLast(serverHandler);
                 }
             });

            // 启动服务,绑定端口
            ChannelFuture f = b.bind(PORT).sync();

            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down all event loops to terminate all threads.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

Start Nettythe service process, creating two EventLoopGroupobjects, these two objects are Nettythe core of the object, which bossGroupis configured to receive a request workerGroupto process the request. As follows:

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

We can look NioEventLoopGroupclass inheritance structure of the case, as follows:
Here Insert Picture Description
From the figure shows, NioEventLoopGroupimplements ScheduledExecutorServicethe interface, it can achieve timing functions related tasks. It also inherits the SingleThreadEventExecutorclass, the class can be seen from the name, this is a single-threaded executor thread. In Nettyby NioEventLoopGroupcreation created to achieve NioEventLoopthe purpose. There reference parameters by constructing NioEventLoopGroupthe object, the actual call is MultithreadEventExecutorGroupconstructor, as follows:

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) {
        	//ewDefaultThreadFactory()会创建一个线程工厂,该线程工厂的作用就是用来创建线程,同时给线程设置名称:nioEventLoop-1-XX
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
		// 根据传进来的线程数,来创建指定大小的数组大小,这个数组就是用来存放NioEventLoop对象实例
        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
        	//异常标志
            boolean success = false;
            try {
            	////创建nThreads个nioEventLoop保存到children数组中
                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);
    }

Corresponding parameter parsing, as shown in the following table:

parameter Explanation
nThreads The number of threads created
executor Thread actuator (the user can customize, was not null, subsequent initialized)
chooserFactory Event execution selection Plant

EventLoopGroupIn the creation of the calls NioEventLoopin the openSelector()method.

EventLoopGroupCreating essence is to create more NioEventLoop, to create here NioEventLoopis a initialization Reactor, including selectorand taskQueue.

NioEventLoop Source as follows:

public final class NioEventLoop extends SingleThreadEventLoop {
...
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;
                }
            }
        });

        if (maybeException instanceof Exception) {
            selectedKeys = null;
            Exception e = (Exception) maybeException;
            logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e);
            return new SelectorTuple(unwrappedSelector);
        }
        selectedKeys = selectedKeySet;
        logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector);
        return new SelectorTuple(unwrappedSelector,
                                 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
    }
...
}

Second, summary

In this paper, by Nettythe startup code of the service, a preliminary understanding of Nettywhat had been done things during the boot process. It focuses on the NioEventLoopcreation process, after the article then describes the startup process, Nettythe other operations.

Published 88 original articles · won praise 49 · Views 100,000 +

Guess you like

Origin blog.csdn.net/Diamond_Tao/article/details/103108799