io-5-netty-工作原理

ServerBootStrap

    服務啓動輔助類,無參構造,採用builder模式(返回本對象構造參數)。

group (初始化線程組)

//加入線程組  
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        super.group(parentGroup);  //線程parentGroup 加入父對象中
        if (childGroup == null) {
            throw new NullPointerException("childGroup");
        }
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        this.childGroup = childGroup;  //指定子子線程組  
        return this;  
    }

//父類 AbstractBootstrap 方法
 public B group(EventLoopGroup group) {
        if (group == null) {
            throw new NullPointerException("group");
        }
        if (this.group != null) {
            throw new IllegalStateException("group set already");
        }
        this.group = group;   //初始化父線程組 parent
        return (B) this;
    }

channel(創建指定channel)


//初始化工廠獲取channel
 public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));  //由工程創建
    }

//初始化工廠
  public B channelFactory(ChannelFactory<? extends C> channelFactory) {
        if (channelFactory == null) {
            throw new NullPointerException("channelFactory");
        }
        if (this.channelFactory != null) {
            throw new IllegalStateException("channelFactory set already");
        }

        this.channelFactory = channelFactory;
        return (B) this;
    }

    //ReflectiveChannelFactory 工廠獲取channel方法
    public T newChannel() {
        try {
            return clazz.newInstance();   //jdk反射獲取
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + clazz, t);
        }
    }

option(設置參數)

//可選參數設置
 public <T> B option(ChannelOption<T> option, T value) {
        if (option == null) {
            throw new NullPointerException("option");
        }
        //設置的參數值爲null 則移除
        if (value == null) {
            synchronized (options) {
                options.remove(option);
            }
        } else {
            //保存到參數集合
            synchronized (options) {
                options.put(option, value);
            }
        }
        return (B) this;
    }

childHandler(配置io處理事件)

//初始化io處理事件
 /**
     * Set the {@link ChannelHandler} which is used to serve the request for the {@link Channel}'s.
     */
public ServerBootstrap childHandler(ChannelHandler childHandler) {
        if (childHandler == null) {
            throw new NullPointerException("childHandler");
        }
        this.childHandler = childHandler;
        return this;
    }

bind(開啓服務類)

//綁定端口
 public ChannelFuture bind(SocketAddress localAddress) {
        validate();   //參數校驗 是否先實現初始化
        if (localAddress == null) {
            throw new NullPointerException("localAddress");
        }
        return doBind(localAddress);
    }

// 真正的開啓服務
 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.executor = channel.eventLoop();
                    }
                    doBind0(regFuture, channel, localAddress, promise);
                }
            });
            return promise;
        }

initAndRegister
//
 final ChannelFuture initAndRegister() {
        final Channel channel = channelFactory().newChannel();  // 由前面初始化的channel反射工廠獲取channel(NioServerSocketChannel)
        try {
            init(channel);
        } catch (Throwable t) {
            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);
        }

        ChannelFuture regFuture = group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        return regFuture;
    }
init
  @Override
    void init(Channel channel) throws Exception {
        final Map<ChannelOption<?>, Object> options = options();  //獲取前面添加的可選參數集合
        synchronized (options) {
            channel.config().setOptions(options);  //設置對應參數
        }
        //同options
        final Map<AttributeKey<?>, Object> attrs = attrs();
        synchronized (attrs) {
            for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
                @SuppressWarnings("unchecked")
                AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
                channel.attr(key).set(e.getValue());
            }
        }
        //將AbstractBootstrap 註冊handler 添加到NioServerSocketChannel中
        ChannelPipeline p = channel.pipeline();  // NioServerSocketChannel創建時 AbstractBootstrap 中DefaultChannelPipeline
        if (handler() != null) {
            p.addLast(handler());
        }
        //TODO 
        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()));
        }
        //添加用於服務啓動的io事件ServerBootstrapAcceptor
        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(new ServerBootstrapAcceptor(
                        currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
            }
        });
    }

register

// eventLoop 爲parentLoop 即 boss
 public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            if (eventLoop == null) {
                throw new NullPointerException("eventLoop");
            }
            if (promise == null) {
                throw new NullPointerException("promise");
            }
            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;
            }

            // It's necessary to reuse the wrapped eventloop object. Otherwise the user will end up with multiple
            // objects that do not share a common state.
            if (AbstractChannel.this.eventLoop == null) {
                AbstractChannel.this.eventLoop = new PausableChannelEventLoop(eventLoop);
            } else {
                AbstractChannel.this.eventLoop.unwrapped = eventLoop;
            }
            // 判斷是否爲 eventloop 線程模式
            //將NioServerSocketChannel 註冊 Selector(eventLoop)
            if (eventLoop.inEventLoop()) {
                register0(promise);  
            } else {
                try {
                //用任務隊列形式
                    eventLoop.execute(new OneTimeTask() {
                        @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);
                }
            }
        }
    服務端啓動成功,執行NioEventLoop run 方法。
      1.輪訓selectedKeys
      2.接受請求客戶端
      3. pipeline.fireChannelRead由head.read - 》 ServerBootStrap channelRead - 》 將socktChannel 事件加入到pipeline,並加入註冊監聽就緒位。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章