首頁 > 軟體

Netty啟動流程伺服器端channel初始化原始碼分析

2022-03-25 13:02:16

前文傳送門 Netty分散式server啟動流程

伺服器端channel初始化

回顧上一小節initAndRegister()方法

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        //建立channel
        channel = channelFactory.newChannel();
        //初始化channel
        init(channel);
    } catch (Throwable t) {
        //忽略非關鍵程式碼
    }
    ChannelFuture regFuture = config().group().register(channel);
    //忽略非關鍵程式碼
    return regFuture;
}

簡單回顧上一小節內容, 我們跟完了建立channel的步驟, 知道了Netty的NioServerSocketChannel和jdk的ServerSocketChannel之間的關係, NioServerSocketChannel和jdk的channel是組合關係, 在其父類別AbstractChannel中有jdk的channel的一個成員變數, 通過建立netty的channel為jdk的channel賦值

init(Channel)方法

我們繼續往下看init(Channel)方法

因為是ServerBootstrap物件呼叫的init()方法, 所以我們跟到ServerBootstrap類的init()方法中:

void init(Channel channel) throws Exception {
    //獲取使用者定義的選項(1)
    final Map<ChannelOption<?>, Object> options = options0();
    synchronized (options) {
        channel.config().setOptions(options);
    }

    //獲取使用者定義的屬性(2)
    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());
        }
    }
    //獲取channel的pipline(3)
    ChannelPipeline p = channel.pipeline();
    //work執行緒組(4)
    final EventLoopGroup currentChildGroup = childGroup;
    //使用者設定的Handler(5)
    final ChannelHandler currentChildHandler = childHandler;
    final Entry<ChannelOption<?>, Object>[] currentChildOptions;
    final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
    //選項轉化為Entry物件(6)
    synchronized (childOptions) { 
        currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
    }
    //屬性轉化為Entry物件(7)
    synchronized (childAttrs) { 
        currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
    }
    //新增伺服器端handler(8)
    p.addLast(new ChannelInitializer<Channel>() {
        //初始化channel
        @Override
        public void initChannel(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(
                            currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                }
            });
        }
    });
}

初看起來程式碼好長, 其實並不複雜, 這裡對每一步進行一個簡述:

步驟(1), (2)是獲取的使用者程式碼中定義的選項和屬性

步驟(3)是獲取channel的pipeline, 這個channel就是上一小節我們學習建立的NioServerSocketChannel, 我們知道每個channel都有個pipeline的屬性, 是AbstractChannel的成員變數, 而這裡的pipeline()就是獲取其與channel繫結的pipeline, 這個pipline, 會在後面的章節中講到

步驟(4)是獲取worker執行緒組, 我們知道這個worker執行緒組就是在使用者程式碼中建立的NioEventLoopGroup, 後來在ServerBootstrap的group()方法中賦值為ServerBootstrap的成員變數, 而這裡是獲取其成員變數, 並賦值到區域性變數currentChildGroup中, NioEventLoop相關知識會在後面的章節講到

步驟(6), (7)是將選項和屬性轉化成Entry物件

步驟(8)是新增伺服器端Handler, 是通過和channel繫結的pipeline呼叫addLast()方法進行新增, 傳入一個ChannelInitializer類的子類物件, 至於addLast方法是做什麼的, ChannelInitializer是做什麼的, 後緒章節都會給大家詳細剖析, 這裡不必深究

這一小節我們瞭解了有關channel初始化的過程, 我們目前只需瞭解其大概步驟, 有關addLast的邏輯會在後面的章節進行詳細剖析

以上就是Netty啟動流程伺服器端channel初始化原始碼分析的詳細內容,更多關於Netty啟動流程伺服器端channel初始化的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com