启动流程
服务端启动流程概览:
- 创建
ServerBootStrap启动类 - 设置并绑定
NioEventLoopGroup线程池 - 创建服务端
Channel - 添加并设置
ChannelHandler - 绑定并启动监听端口
Channel的创建和初始化过程
Netty服务端的Channel类型是 NioServerSocketChannel,NioServerSocketChannel的创建实际上是从 ServerBootStrap的bind()方法开始的,bind()调用doBind():
private ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister(); final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } if (regFuture.isDone()) { // At this point we know that the registration was complete and successful. ChannelPromise promise = channel.newPromise(); doBind0(regFuture, channel, localAddress, promise); return promise; } else { ...
一个 initAndRegister()方法,这个方法就负责 NioServerSocketChannel的初始化和注册操作
final ChannelFuture initAndRegister() { Channel channel = null; try { channel = channelFactory.newChannel(); init(channel); } catch (Throwable t) { if (channel != null) { channel.unsafe().closeForcibly(); return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); } return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t); } ChannelFuture regFuture = config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } return regFuture; }
源码里是调用 channelFactory.newChannel()来创建 channel,创建 Channel的是ReflectiveChannelFactory类,它是ChannelFactory的一个重要实现类
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> { private final Class<? extends T> clazz; public ReflectiveChannelFactory(Class<? extends T> clazz) { if (clazz == null) { throw new NullPointerException("clazz"); } this.clazz = clazz; } @Override public T newChannel() { try { return clazz.getConstructor().newInstance(); } catch (Throwable t) { throw new ChannelException("Unable to create Channel from class " + clazz, t); } } @Override public String toString() { return StringUtil.simpleClassName(clazz) + ".class"; } }
ServerBootstrap中的ChannelFactory的实现是ReflectiveChannelFactory- 生成的 Channel的具体类型是
NioServerSocketChannel Channel的实例化过程其实就是调用ChannelFactory.newChannel方法,实际上是通过反射方式进行创建的
NioServerSocketChanel的实例化过程
private static ServerSocketChannel newSocket(SelectorProvider provider) { try { return provider.openServerSocketChannel(); } catch (IOException e) { throw new ChannelException("Failed to open a server socket.", e); } } public NioServerSocketChannel() { this(newSocket(DEFAULT_SELECTOR_PROVIDER)); }
方法newSocket利用 provider.openServerSocketChannel()生成Nio中的 ServerSocketChannel对象,然后调用重载的构造器:
public NioServerSocketChannel(ServerSocketChannel channel) { super(null, channel, SelectionKey.OP_ACCEPT); config = new NioServerSocketChannelConfig(this, javaChannel().socket()); }
调用父类的构造器,传入的参数是 SelectionKey.OP_ACCEPT
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent, ch, readInterestOp); } --------------父类------------------------ protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent); this.ch = ch; this.readInterestOp = readInterestOp; try { ch.configureBlocking(false); } catch (IOException e) { try { ch.close(); } catch (IOException e2) { if (logger.isWarnEnabled()) { logger.warn( "Failed to close a partially initialized socket.", e2); } } throw new ChannelException("Failed to enter non-blocking mode.", e); } }
设置当前 ServerSocketChannel为非阻塞通道,然后再次进入父类构造器 AbstractChannel(Channel parent):
protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); }
- parent属性设置为null
- 初始化unsafe,用来负责底层的connect,register,read和write操作
- 初始化pipeline,在实例化一个Channel的同时,当有事件发生的时候,pipeline负责调用相应的Handler进行处理
unsafe实际是封装了 Java 底层 Socket的操作,因此是沟通 Netty上层和Java 底层重要的桥梁。
ChannelPipeline的初始化
每个Channel都有对应的 ChannelPipeline,当一个Channel被创建时,对应的ChannelPipeline也会自动创建
protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); } ... protected DefaultChannelPipeline newChannelPipeline() { return new DefaultChannelPipeline(this); }
pipeline最终被初始化为一个 DefaultChannelPipeline,DefaultChannelPipeline是ChannelPipeline的实现类,进入它的构造方法
NioEventLoopGroup
Netty服务端代码中初始化了两个 NioEventLoopGroup,即一个处理客户端连接请求的线程池——bossGroup,一个处理客户端读写操作的线程池——workerGroup,NioEventLoopGroup实现了 Executor接口,Executor框架可以用来创建线程池的,也是一个线程执行器.构造函数最终调用父类MultithreadEventLoopGroup的构造器
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) { if (nThreads <= 0) { throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads)); } if (executor == null) { executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } children = new EventExecutor[nThreads]; for (int i = 0; i < nThreads; i ++) { boolean success = false; try { children[i] = newChild(executor, args); success = true; } catch (Exception e) { // TODO: Think about if this is a good exception type throw new IllegalStateException("failed to create a child event loop", e); } finally { if (!success) { for (int j = 0; j < i; j ++) { children[j].shutdownGracefully(); } for (int j = 0; j < i; j ++) { EventExecutor e = children[j]; try { while (!e.isTerminated()) { e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); } } catch (InterruptedException interrupted) { // Let the caller handle the interruption. Thread.currentThread().interrupt(); break; } } } } } chooser = chooserFactory.newChooser(children); final FutureListener<Object> terminationListener = new FutureListener<Object>() { @Override public void operationComplete(Future<Object> future) throws Exception { if (terminatedChildren.incrementAndGet() == children.length) { terminationFuture.setSuccess(null); } } }; for (EventExecutor e: children) { e.terminationFuture().addListener(terminationListener); } Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length); Collections.addAll(childrenSet, children); readonlyChildren = Collections.unmodifiableSet(childrenSet); }
MultithreadEventExecutorGroup管理着 eventLoop的生命周期,变量:
- children: EventExecutor数组,保存eventloop
- chooser: 线程选择器,从children中选取一个 eventloop的策略
MultithreadEventExecutorGroup的构造器主要分为以下几个步骤:
- 创建线程执行器——
ThreadPerTaskExecutor - 调用
newChild方法初始化children数组 - 创建线程选择器——
chooser
创建ThreadPerTaskExecutor
开始初始化 NioEventLoopGroup,并没有传入 Executor参数:
public NioEventLoopGroup(int nThreads) { this(nThreads, (Executor) null); }
到父类MultithreadEventExecutorGroup构造器时,executor 为null, 然后执行:
if (executor == null) { executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); }
hreadPerTaskExecutor是一个线程执行器,它实现了 Executor接口
public final class ThreadPerTaskExecutor implements Executor { private final ThreadFactory threadFactory; public ThreadPerTaskExecutor(ThreadFactory threadFactory) { if (threadFactory == null) { throw new NullPointerException("threadFactory"); } this.threadFactory = threadFactory; } @Override public void execute(Runnable command) { threadFactory.newThread(command).start(); } }
ThreadPerTaskExecutor 实现了 execute方法,每次通过调用execute方法执行线程任务
调用 newChild 方法初始化 children 数组
children[i] = newChild(executor, args);
通过 newChild方法初始化 EventExecutor数组的每个元素,而 newChild方法如下:
protected EventLoop newChild(Executor executor, Object... args) throws Exception { return new NioEventLoop(this, executor, (SelectorProvider) args[0], ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]); }
每次循环通过newChild实例化一个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; final SelectorTuple selectorTuple = openSelector(); selector = selectorTuple.selector; unwrappedSelector = selectorTuple.unwrappedSelector; selectStrategy = strategy; }
创建线程选择器——chooser
public EventExecutorChooser newChooser(EventExecutor[] executors) { if (isPowerOfTwo(executors.length)) { return new PowerOfTwoEventExecutorChooser(executors); } else { return new GenericEventExecutorChooser(executors); } }
Channel的注册过程
Channel的创建和初始化过程,是在 initAndRegister方法中进行的,这个方法里还会将初始化好的 channel注册到 EventLoop线程中去
final ChannelFuture initAndRegister() { Channel channel = null; try { channel = channelFactory.newChannel(); init(channel); } catch (Throwable t) { ..... } ChannelFuture regFuture = config().group().register(channel); ...... }
调用config().group().register方法将 channel注册到 EventLoopGroup中去,其目的就是为了实现NIO中把ServerSocketChannel注册到 Selector中去,这样就是可以实现client请求的监听
public ChannelFuture register(Channel channel) { return next().register(channel); } ...... public EventLoop next() { return (EventLoop) super.next(); }
父类MultithreadEventExecutorGroup的next()方法,next方法使用 chooser策略从 EventExecutor[]数组中选择一个 SingleThreadEventLoop:
public EventExecutor next() { return chooser.next(); } ..... public EventExecutor next() { return executors[idx.getAndIncrement() & executors.length - 1]; }
再执行 SingleThreadEventLoop的 register()注册方法:
public ChannelFuture register(Channel channel) { return register(new DefaultChannelPromise(channel, this)); } ... public ChannelFuture register(final ChannelPromise promise) { ObjectUtil.checkNotNull(promise, "promise"); promise.channel().unsafe().register(this, promise); return promise; }
调用了 unsafe的register方法,具体是AbstractUnsafe.register,而unsafe主要用于实现底层的 rergister,read,write等操作。该register方法是:
public final void register(EventLoop eventLoop, final ChannelPromise promise) { ...... AbstractChannel.this.eventLoop = eventLoop; if (eventLoop.inEventLoop()) { register0(promise); } else { ...... } }
将 eventLoop 赋值给 Channel 的 eventLoop 属性,然后又调用了 register0()方法
private void register0(ChannelPromise promise) { try { ...... boolean firstRegistration = neverRegistered; doRegister(); neverRegistered = false; registered = true; pipeline.invokeHandlerAddedIfNeeded(); safeSetSuccess(promise); pipeline.fireChannelRegistered(); if (isActive()) { if (firstRegistration) { pipeline.fireChannelActive(); } else if (config().isAutoRead()) { beginRead(); } } } catch (Throwable t) { ...... } }
doRegister才是最终Nio的注册方法:
protected void doRegister() throws Exception { boolean selected = false; for (;;) { try { selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this); return; } catch (CancelledKeyException e) { if (!selected) { eventLoop().selectNow(); selected = true; } else { throw e; } } } }
通过javaChannel().register(eventLoop().unwrappedSelector(), 0, this)将 Channel对应的Java NIO ServerSocketChannel注册到 EventLoop中的Selector上,最终完成了channel向eventLoop的注册过程。
添加 ChannelHandler
initAndRegister()方法里,里面有个 init()方法,如下:
void init(Channel channel) throws Exception { final Map<ChannelOption<?>, Object> options = options0(); synchronized (options) { setChannelOptions(channel, options, logger); } final Map<AttributeKey<?>, Object> attrs = attrs0(); synchronized (attrs) { for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) { @SuppressWarnings("unchecked") AttributeKey<Object> key = (AttributeKey<Object>) e.getKey(); channel.attr(key).set(e.getValue()); } } ChannelPipeline p = channel.pipeline(); final EventLoopGroup currentChildGroup = childGroup; final ChannelHandler currentChildHandler = childHandler; final Entry<ChannelOption<?>, Object>[] currentChildOptions; final Entry<AttributeKey<?>, Object>[] currentChildAttrs; synchronized (childOptions) { currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0)); } synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0)); } p.addLast(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } }); }
pipeline的 addLast方法,该方法就是添加用于处理出站和入站数据流的 ChannelHandler,而pipeline是从 channel中获取的,之前分析过当创建channel时会自动创建一个对应的 channelPipeline。
serverbootstrap.handler()设置的handler在初始化就会执行,而 serverbootstrap.childHandler()设置的childHandler在客户端连接成功才会执行
浙公网安备 33010602011771号