一、Netty-Server端启动流程
-
从ServerBootstrap的bind方法开始:
initAndRegister();方法
//1. 绑定端口 public ChannelFuture bind(SocketAddress localAddress) { validate(); if (localAddress == null) { throw new NullPointerException("localAddress"); } return doBind(localAddress); } //2. 调用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 { // 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; } } //3. 调用doBind → initAndRegister方法 final ChannelFuture initAndRegister() { Channel channel = null; try { /** 反射获取NioServerSocketChannel(它class是我们传入的) **/ channel = channelFactory.newChannel(); init(channel); } catch (Throwable t) { if (channel != null) { // channel can be null if newChannel crashed (eg SocketException("too many open files")) channel.unsafe().closeForcibly(); // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); } // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t); } ChannelFuture regFuture = config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } // If we are here and the promise is not failed, it's one of the following cases: // 1) If we attempted registration from the event loop, the registration has been completed at this point. // i.e. It's safe to attempt bind() or connect() now because the channel has been registered. // 2) If we attempted registration from the other thread, the registration request has been successfully // added to the event loop's task queue for later execution. // i.e. It's safe to attempt bind() or connect() now: // because bind() or connect() will be executed *after* the scheduled registration task is executed // because register(), bind(), and connect() are all bound to the same thread. return regFuture; } //4. 调用 doBind → initAndRegister → newChannel方法 public T newChannel() { try { return clazz.getConstructor().newInstance(); } catch (Throwable t) { throw new ChannelException("Unable to create Channel from class " + clazz, t); } } //5. 调用 doBind → initAndRegister → init方法 @Override void init(Channel channel) throws Exception { //ServerBootstrap创建时如果设置了NioServerSokectChannel的选项,就把它设置进去 final Map<ChannelOption<?>, Object> options = options0(); //LinkedHashMap线程不安全 synchronized (options) { setChannelOptions(channel, options, logger); } //ServerBootstrap创建时如果设置了NioServerSokectChannel的属性,就把它设置进去 final Map<AttributeKey<?>, Object> attrs = attrs0(); //LinkedHashMap线程不安全 synchronized (attrs) { 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(); 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(childOptions.size())); } //设置客户端连接的属性 synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); } 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)); } }); } }); } //6. 调用 doBind → initAndRegister → init → p.addLast方法 //6 -(1) @Override public final ChannelPipeline addLast(ChannelHandler... handlers) { //6 -(2) return addLast(null, handlers); } //6 -(2) @Override public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) { if (handlers == null) { throw new NullPointerException("handlers"); } for (ChannelHandler h: handlers) { if (h == null) { break; } //6 -(3) addLast(executor, null, h); } return this; } //6 -(3) @Override public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) { final AbstractChannelHandlerContext newCtx; synchronized (this) { //检查是否有@Sharable注解(作用:ChannelHandler是否可以在多个channel直接共享)或者 有没有被使用过,没有注解且被使用则抛异常 checkMultiplicity(handler); //ChannelHandler封装成ChannelHandlerContext (ChannelHandlerContext 是连接ChannelPipeline和ChannelHandler的桥梁) newCtx = newContext(group, filterName(name, handler), handler); //6 -(4) addLast0(newCtx); // If the registered is false it means that the channel was not registered on an eventloop yet. // In this case we add the context to the pipeline and add a task that will call // ChannelHandler.handlerAdded(...) once the channel is registered. //进入这里 并把ChannelHandlerContext包装成一个任务 if (!registered) { newCtx.setAddPending(); callHandlerCallbackLater(newCtx, true); return this; } EventExecutor executor = newCtx.executor(); if (!executor.inEventLoop()) { newCtx.setAddPending(); executor.execute(new Runnable() { @Override public void run() { callHandlerAdded0(newCtx); } }); return this; } } callHandlerAdded0(newCtx); return this; } //6 -(4) private void addLast0(AbstractChannelHandlerContext newCtx) { AbstractChannelHandlerContext prev = tail.prev; newCtx.prev = prev; newCtx.next = tail; prev.next = newCtx; tail.prev = newCtx; } //7. 分析重写的initChannel方法 p.addLast(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); //ServerBootstrap创建时如果设置了NioServerSokectChannel的ChannelHandler ,就把它添加进pipeline中 ChannelHandler handler = config.handler(); if (handler != null) { //可以debug看看,这个handler的handlerAdded方法会被回调~~ pipeline.addLast(handler); } //这里很重要,用channel绑定的NioEventLoop执行一个任务,把Acceptor派发器添加进NioServerSokectChannel的pipeline中,用于给每个连进来的NioSocketChannel初始化 //它传入NioServerSocketChannel、worker线程组、所有的连接ChannelHandler、选项配置、属性配置 ch.eventLoop().execute(new Runnable() { @Override public void run() { //7 -(1) pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); //7 -(1) ServerBootstrapAcceptor的channelRead方法 @Override @SuppressWarnings("unchecked") public void channelRead(ChannelHandlerContext ctx, Object msg) { //拿到NioSocketChannel final Channel child = (Channel) msg; //将NioSocketChannel的pipeline初始化 child.pipeline().addLast(childHandler); //将NioSocketChannel的选项初始化 setChannelOptions(child, childOptions, logger); //将NioSocketChannel的属性初始化 for (Entry<AttributeKey<?>, Object> e: childAttrs) { child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue()); } try { //从worker线程组中抽一个NioEventLoop,并将NioSocketChannel注册到NioEventLoop上和添加监听器 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); } } //8. 回到//3. 步 final ChannelFuture initAndRegister() { Channel channel = null; try { channel = channelFactory.newChannel(); init(channel); } catch (Throwable t) { if (channel != null) { // channel can be null if newChannel crashed (eg SocketException("too many open files")) channel.unsafe().closeForcibly(); // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); } // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t); } //boss线程组注册NioServerSocketChannel //8 -(1) ChannelFuture regFuture = config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } // If we are here and the promise is not failed, it's one of the following cases: // 1) If we attempted registration from the event loop, the registration has been completed at this point. // i.e. It's safe to attempt bind() or connect() now because the channel has been registered. // 2) If we attempted registration from the other thread, the registration request has been successfully // added to the event loop's task queue for later execution. // i.e. It's safe to attempt bind() or connect() now: // because bind() or connect() will be executed *after* the scheduled registration task is executed // because register(), bind(), and connect() are all bound to the same thread. return regFuture; } //8 -(1) @Override public ChannelFuture register(Channel channel) { //chooser选择器获取一个NioEventLoop并register //8 -(2) return next().register(channel); } //8 -(2) @Override public ChannelFuture register(Channel channel) { //1.创建DefaultChannelPromise,构造器传入NioServerSocketChannel 和 NioEventLoop //2.register //8 -(3) return register(new DefaultChannelPromise(channel, this)); } //8 -(3) @Override public ChannelFuture register(final ChannelPromise promise) { ObjectUtil.checkNotNull(promise, "promise"); //1.拿到NioMessageUnsafe //2.NioMessageUnsafe父类AbstractUnsafe中进行register //8 -(4) promise.channel().unsafe().register(this, promise); return promise; } //8 -(4) AbstractUnsafe类 @Override public final void register(EventLoop eventLoop, final ChannelPromise promise) { if (eventLoop == null) { throw new NullPointerException("eventLoop"); } if (isRegistered()) { promise.setFailure(new IllegalStateException("registered to an event loop already")); return; } if (!isCompatible(eventLoop)) { promise.setFailure( new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName())); return; } //给NioServerSocketChannel保存NioEnvetLoop AbstractChannel.this.eventLoop = eventLoop; //netty的线程模型高性能在于对当前线程身份的确认 //eventLoop当前不在自己的线程中 if (eventLoop.inEventLoop()) { register0(promise); //这里eventLoop把boss线程启动了,把这个runnable加入任务队列,并启动boss线程执行 } else { try { eventLoop.execute(new Runnable() { @Override public void run() { //8 -(5) 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); } } } //8 -(5) 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; //进行注册 //8 -(6) doRegister(); neverRegistered = false; registered = true; // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the // user may already fire events through the pipeline in the ChannelFutureListener. //如果pipeline中有需要执行的HandlerAdded就去执行 //8 -(7) pipeline.invokeHandlerAddedIfNeeded(); //这步告诉ChannelPromise设置成功了 //这将影响到第 //2 步中 regFuture.isDone()的判断结果 safeSetSuccess(promise); //8 -(12) pipeline.fireChannelRegistered(); // Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (isActive()) { if (firstRegistration) { pipeline.fireChannelActive(); } else if (config().isAutoRead()) { // This channel was registered before and autoRead() is set. This means we need to begin read // again so that we process inbound data. // // See https://github.com/netty/netty/issues/4805 beginRead(); } } } catch (Throwable t) { // Close the channel directly to avoid FD leak. closeForcibly(); closeFuture.setClosed(); safeSetFailure(promise, t); } } //8 -(6) @Override protected void doRegister() throws Exception { boolean selected = false; for (;;) { try { //1.jdk的注册,将ServerSocketChannel注册到Selector上,感兴趣事件是0,并把NioServerSocketChannel绑定selectKey 上 //2.有异常就强制刷新一次 //3.还是注册失败就抛异常 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; } } } } //8 -(7) final void invokeHandlerAddedIfNeeded() { //很明显是在boss线程 assert channel.eventLoop().inEventLoop(); if (firstRegistration) { firstRegistration = false; // We are now registered to the EventLoop. It's time to call the callbacks for the ChannelHandlers, // that were added before the registration was done. //处理之前在//6 -(3)中被包装成任务的ChannelHandlerContext //8 -(8) callHandlerAddedForAllHandlers(); } } //8 -(8) private void callHandlerAddedForAllHandlers() { final PendingHandlerCallback pendingHandlerCallbackHead; synchronized (this) { assert !registered; // This Channel itself was registered. registered = true; pendingHandlerCallbackHead = this.pendingHandlerCallbackHead; // Null out so it can be GC'ed. this.pendingHandlerCallbackHead = null; } // This must happen outside of the synchronized(...) block as otherwise handlerAdded(...) may be called while // holding the lock and so produce a deadlock if handlerAdded(...) will try to add another handler from outside // the EventLoop. PendingHandlerCallback task = pendingHandlerCallbackHead; while (task != null) {. //PendingHandlerAddedTask //8 -(8) task.execute(); task = task.next; } } //8 -(8) @Override void execute() { EventExecutor executor = ctx.executor(); //明显是在当前的NioEventLoop线程中 if (executor.inEventLoop()) { //8 -(9) callHandlerAdded0(ctx); } else { try { executor.execute(this); } catch (RejectedExecutionException e) { if (logger.isWarnEnabled()) { logger.warn( "Can't invoke handlerAdded() as the EventExecutor {} rejected it, removing handler {}.", executor, ctx.name(), e); } remove0(ctx); ctx.setRemoved(); } } } //8 -(9) private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) { try { // We must call setAddComplete before calling handlerAdded. Otherwise if the handlerAdded method generates // any pipeline events ctx.handler() will miss them because the state will not allow it. ctx.setAddComplete(); //回调ChannelHandler的handlerAdded方法 //8 -(10) ctx.handler().handlerAdded(ctx); } catch (Throwable t) { boolean removed = false; try { remove0(ctx); try { ctx.handler().handlerRemoved(ctx); } finally { ctx.setRemoved(); } removed = true; } catch (Throwable t2) { if (logger.isWarnEnabled()) { logger.warn("Failed to remove a handler: " + ctx.name(), t2); } } if (removed) { fireExceptionCaught(new ChannelPipelineException( ctx.handler().getClass().getName() + ".handlerAdded() has thrown an exception; removed.", t)); } else { fireExceptionCaught(new ChannelPipelineException( ctx.handler().getClass().getName() + ".handlerAdded() has thrown an exception; also failed to remove.", t)); } } } //8 -(10) 当前是被回调的是 ChannelInitializer类 /** * {@inheritDoc} If override this method ensure you call super! */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { if (ctx.channel().isRegistered()) { // This should always be true with our current DefaultChannelPipeline implementation. // The good thing about calling initChannel(...) in handlerAdded(...) is that there will be no ordering // surprises if a ChannelInitializer will add another ChannelInitializer. This is as all handlers // will be added in the expected order. //8 -(11) initChannel(ctx); } } //8 -(11) 看完跳回 //8 -(5) 步 还是ChannelInitializer的方法 private boolean initChannel(ChannelHandlerContext ctx) throws Exception { if (initMap.putIfAbsent(ctx, Boolean.TRUE) == null) { // Guard against re-entrance. try { //这个就回到我们 //5 步中重写的initChannel方法 initChannel((C) ctx.channel()); } catch (Throwable cause) { // Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...). // We do so to prevent multiple calls to initChannel(...). exceptionCaught(ctx, cause); } finally { remove(ctx); } return true; } return false; } //8 -(12) @Override public final ChannelPipeline fireChannelRegistered() { //从pipeline的头结点的下一个结点开始 //8 -(13) AbstractChannelHandlerContext.invokeChannelRegistered(head); return this; } //8 -(13) static void invokeChannelRegistered(final AbstractChannelHandlerContext next) { EventExecutor executor = next.executor(); if (executor.inEventLoop()) { //8 -(14) next.invokeChannelRegistered(); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelRegistered(); } }); } } //8 -(14) private void invokeChannelRegistered() { if (invokeHandler()) { try { //调用pipeline上所有的ChannelHandler的channelRegistered方法 //8 -(15) 当前调用的是HeadContext ((ChannelInboundHandler) handler()).channelRegistered(this); } catch (Throwable t) { notifyHandlerException(t); } } else { fireChannelRegistered(); } } //8 -(15) @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { //head结点中再次检查pipeline是否有延迟执行的任务 invokeHandlerAddedIfNeeded(); //执行ChannelHandlerContext的 fireChannelRegistered方法 //8 -(16) ctx.fireChannelRegistered(); } //8 -(16) 头结点是outBound,此时下一个结点是ChannelInitializer为inBound,再下一个结点是DefaultChannelPipeline$TailContext为inBound。必须是inBound的入栈ChannelHandler才可以执行成功fireChannelRegistered方法 private AbstractChannelHandlerContext findContextInbound() { AbstractChannelHandlerContext ctx = this; do { ctx = ctx.next; } while (!ctx.inbound); return ctx; } //除了第一个ChannelInitializer是初始化就加进pipeline,后面的匿名ChannelHnadler和ServerBootstrapAcceptor都是异步的
-
doBind0方法
//1. private ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister(); final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } //ChannelFuture保存Channel异步操作的结果 //官方定义的四种状态:每种状态都有对应的方法获取,netty推荐配合ChannelFutureListener监听IO事件的完成 //并且ChannelHandler中不要await(),因为它被NioEventLoop线程执行,会死锁 /** * +---------------------------+ * | Completed successfully | * +---------------------------+ * +----> isDone() = true | * +--------------------------+ | | isSuccess() = true | * | Uncompleted | | +===========================+ * +--------------------------+ | | Completed with failure | * | isDone() = false | | +---------------------------+ * | isSuccess() = false |----+----> isDone() = true | * | isCancelled() = false | | | cause() = non-null | * | cause() = null | | +===========================+ * +--------------------------+ | | Completed by cancellation | * | +---------------------------+ * +----> isDone() = true | * | isCancelled() = true | * +---------------------------+ **/ //DefaultChannelPromise是否完成状态 if (regFuCture.isDone()) { // At this point we know that the registration was complete and successful. ChannelPromise promise = channel.newPromise(); // doBind0(regFuture, channel, localAddress, promise); return promise; //不是完成状态 } else { // Registration future is almost always fulfilled already, but just in case it's not. final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); //添加一个监听器,会在 1. //8 -(5)中safeSetSuccess(promise);方法执行时调用ChannelFutureListener的operationComplete方法 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; } } //2. private static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up // the pipeline in its channelRegistered() implementation. //向NioEventLoop添加一个任务 channel.eventLoop().execute(new Runnable() { @Override public void run() { //如果成功状态 if (regFuture.isSuccess()) { //2 -(1) channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); } //2 -(1) @Override public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { //从尾部TailHandlerContext开始找outBound //2 -(2) return tail.bind(localAddress, promise); } //2 -(2) @Override public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { if (localAddress == null) { throw new NullPointerException("localAddress"); } if (isNotValidPromise(promise, false)) { // cancelled return promise; } //while循环找outbound final AbstractChannelHandlerContext next = findContextOutbound(); EventExecutor executor = next.executor(); //在NioEventLoop线程中 if (executor.inEventLoop()) { //2 -(3) next.invokeBind(localAddress, promise); } else { safeExecute(executor, new Runnable() { @Override public void run() { next.invokeBind(localAddress, promise); } }, promise, null); } return promise; } //2 -(3) private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { //是不是添加的handler if (invokeHandler()) { try { //此时HeadHandlerContext是outbound //2 -(4) ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } } else { bind(localAddress, promise); } } //2 -(4) HeadHandlerContext @Override public void bind( ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception { //NioMessageUnsafe //2 -(5) unsafe.bind(localAddress, promise); } //2 -(5) @Override public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { assertEventLoop(); if (!promise.setUncancellable() || !ensureOpen(promise)) { return; } // See: https://github.com/netty/netty/issues/576 if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() && !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) { // Warn a user about the fact that a non-root user can't receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. logger.warn( "A non-root user can't receive a broadcast packet if the socket " + "is not bound to a wildcard address; binding to a non-wildcard " + "address (" + localAddress + ") anyway as requested."); } //false boolean wasActive = isActive(); try { //2 -(6) doBind(localAddress); } catch (Throwable t) { safeSetFailure(promise, t); closeIfClosed(); return; } if (!wasActive && isActive()) { //添加一个任务 invokeLater(new Runnable() { @Override public void run() { //执行通道的channel激活传播方法,从头节点开始 //2 -(7) pipeline.fireChannelActive(); } }); } safeSetSuccess(promise); } //2 -(6) jdk的bind方法 @Override protected void doBind(SocketAddress localAddress) throws Exception { if (PlatformDependent.javaVersion() >= 7) { javaChannel().bind(localAddress, config.getBacklog()); } else { javaChannel().socket().bind(localAddress, config.getBacklog()); } } //2 -(7) H @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelActive(); //还记得ServerSocketChannel初始化时候注册的感兴趣事件是0吧,这个方法就是把0改成accept事件 //2 -(8) readIfIsAutoRead(); } //2 -(8) private void readIfIsAutoRead() { if (channel.config().isAutoRead()) { //2 -(9) channel.read(); } } //2 -(9) AbstractChannel @Override public Channel read() { pipeline.read(); return this; } //2 -(10) DefaultChannelPipeline @Override public final ChannelPipeline read() { //从尾节点开始执行read方法 tail.read(); return this; } //2 -(11) AbstractChannelHandlerContext @Override public ChannelHandlerContext read() { //尾节点开始找Outbound final AbstractChannelHandlerContext next = findContextOutbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { //head节点是outbound 执行他的read方法 //2 -(12) next.invokeRead(); } else { Runnable task = next.invokeReadTask; if (task == null) { next.invokeReadTask = task = new Runnable() { @Override public void run() { next.invokeRead(); } }; } executor.execute(task); } return this; } //2 -(12) private void invokeRead() { if (invokeHandler()) { try { //2 -(13) ((ChannelOutboundHandler) handler()).read(this); } catch (Throwable t) { notifyHandlerException(t); } } else { read(); } } //2 -(13) HeadContext @Override public void read(ChannelHandlerContext ctx) { //2 -(14) unsafe.beginRead(); } //2 -(14) @Override public final void beginRead() { assertEventLoop(); if (!isActive()) { return; } try { //2 -(15) doBeginRead(); } catch (final Exception e) { invokeLater(new Runnable() { @Override public void run() { pipeline.fireExceptionCaught(e); } }); close(voidPromise()); } } //2 -(15) AbstractNioChannel @Override protected void doBeginRead() throws Exception { // Channel.read() or ChannelHandlerContext.read() was called final SelectionKey selectionKey = this.selectionKey; if (!selectionKey.isValid()) { return; } readPending = true; //初始化时候设置的是 0 final int interestOps = selectionKey.interestOps(); //readInterestOp=16, 变成ACCEPT事件了 if ((interestOps & readInterestOp) == 0) { selectionKey.interestOps(interestOps | readInterestOp); } }
整个netty启动完成
-
InBound与OutBound
小伙伴搞不清楚他们的执行顺序,In是tail节点添加进去的,out是head节点输出出去的。因此netty处理in的时候是从头部开始找每一个inbound(一般被通知调用),处理out是从尾部开始找每一个oubound(一般是主动调用out)。
举个栗子://1.ServerBootStrap .childHandler(new ChannelInitializer<ServerSocketChannel>() { @Override protected void initChannel(ServerSocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(Charset.forName("utf-8"))); System.out.println("who am i"); pipeline.addLast(new MyService()); } }); //2. 这是一个InBound 配合 StringDecoder这个Inbound 就形成了 //head(out) <=> StringDecoder(in) <=> StringEncoder(out) <=> MyService(in) <=> tail(in) //这样就形成了消息进来先解码再处理业务, 最后写出去时候进行编码。这个设计真的很niubility public class MyService extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //todo 这里会调用oubound写出去 所以ChannelHandler添加的顺序是有要求的 ~~~~~ ctx.writeAndFlush(""); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
-
ChannelPromise和ChannelFuture
ChannelFuture扩展自java的Future接口,能添加监听器异步获取执行任务的结果。
ChannelPromise继承了ChannelFuture和Promise接口,不但有ChannelFuture的功能还可以设置执行状态