Netty源碼分析:ServerBootstrap

Netty源碼分析:ServerBootstrap

一般服務端的代碼如下所示:

    package com.wrh.server;

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;

    /**
     * Created by wuranghao on 2017/9/4.
     */
    public final class SimpleServer {

        public static void main(String[] args) throws Exception {
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .handler(new SimpleServerHandler())
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                            }
                        });

                ChannelFuture f = b.bind(8888).sync();

                f.channel().closeFuture().sync();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }

        private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                System.out.println("channelActive");
            }

            @Override
            public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
                System.out.println("channelRegistered");
            }

            @Override
            public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
                System.out.println("handlerAdded");
            }
        }
    }

在上篇博文(http://blog.csdn.net/u010412719/article/details/78006968)中 剖析瞭如下的兩行代碼內部的構造函數中幹了些什麼。

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

具體可以見上篇博文,對於如上的兩行代碼得到的結論是:

1、 如果不指定線程數,則線程數爲:CPU的核數*2

2、根據線程個數是否爲2的冪次方,採用不同策略初始化chooser

3、產生nThreads個NioEventLoop對象保存在children數組中。

可以理解NioEventLoop就是一個線程,線程NioEventLoop中裏面有如下幾個屬性:

1、NioEventLoopGroup (在父類SingleThreadEventExecutor中)

2、selector

3、provider

4、thread (在父類SingleThreadEventExecutor中)

更通俗點就是: NioEventLoopGroup就是一個線程池,NioEventLoop就是一個線程。NioEventLoopGroup線程池中有N個NioEventLoop線程。

ServerBootstrap類分析

本篇博文將分析如下幾行代碼裏面做了些什麼。

            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new SimpleServerHandler())
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                        }
                    });

ServerBootstrap類的繼承結構如下:

該類的參數,有必要列出:

    private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
    private volatile EventLoopGroup childGroup;
    private volatile ChannelHandler childHandler; 

其父類AbstractBootstrap的參數

    private volatile EventLoopGroup group;
    private volatile ChannelFactory<? extends C> channelFactory;
    private volatile SocketAddress localAddress;
    private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
    private volatile ChannelHandler handler;  

ServerBootstrap類的無參構造函數什麼都沒有做,這沒什麼好說的。下面主要看下這個鏈式設置相關的參數。

1)group(bossGroup, workerGroup):設置group

    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        super.group(parentGroup);
        if (childGroup == null) {
            throw new NullPointerException("childGroup");
        }
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        this.childGroup = childGroup;
        return this;
    } 

即將workerGroup保存在 ServerBootstrap對象的childGroup屬性上。 bossGroup保存在ServerBootstrap對象的group屬性上

2)channel(NioServerSocketChannel.class)

    public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new BootstrapChannelFactory<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;
    }   

函數功能:設置父類屬性channelFactory 爲: BootstrapChannelFactory類的對象。其中這裏BootstrapChannelFactory對象中包括一個clazz屬性爲:NioServerSocketChannel.class,從如下該類的構造函數中可以明顯的得到這一點。

    private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {
        private final Class<? extends T> clazz;

        BootstrapChannelFactory(Class<? extends T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public T newChannel() {
            try {
                return clazz.newInstance();
            } catch (Throwable t) {
                throw new ChannelException("Unable to create Channel from class " + clazz, t);
            }
        }

        @Override
        public String toString() {
            return StringUtil.simpleClassName(clazz) + ".class";
        }
    } 

3)handler(new SimpleServerHandler())

此方法的具體代碼如下:

    public B handler(ChannelHandler handler) {
        if (handler == null) {
            throw new NullPointerException("handler");
        }
        this.handler = handler;
        return (B) this;
    } 

函數功能:設置handler屬性,該屬性在其父類 AbstractBootstrap中。

注意:這裏的handler函數的入參類是我們自己提供的。如下,後面的博文中將會分析這個handler將會在哪裏以及何時被調用,這裏只需要記住這一點即可

        private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                System.out.println("channelActive");
            }

            @Override
            public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
                System.out.println("channelRegistered");
            }

            @Override
            public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
                System.out.println("handlerAdded");
            }
        }

4)childHandler

    public ServerBootstrap childHandler(ChannelHandler childHandler) {
        if (childHandler == null) {
            throw new NullPointerException("childHandler");
        }
        this.childHandler = childHandler;
        return this;
    } 

簡單來說就是將如下的childHandler設置在AbstractBootstrap的相應屬性上。

    childHandler = new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                        }
                    })  

總結

比較簡單哈,主要是將我們提供的參數設置到其相應的對象屬性中去了。 因爲後面會用到如下的幾個屬性,因此最好知道下,這些屬性是何時以及在那裏賦值的。以免分析到後面會很懵逼。

1、group:workerGroup保存在 ServerBootstrap對象的childGroup屬性上。 bossGroup保存在ServerBootstrap對象的group屬性上

2、channelFactory:BootstrapChannelFactory類的對象(clazz屬性爲:NioServerSocketChannel.class)

3、handler:SimpleServerHandler

4、childHandler

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章