Netty源碼分析第1章(Netty啟動流程)---->第1節: 服務端初始化


Netty源碼分析第一章:  Server啟動流程

 

概述:

        本章主要講解server啟動的關鍵步驟, 讀者只需要了解server啟動的大概邏輯, 知道關鍵的步驟在哪個類執行即可, 並不需要了解每一步的運作機制, 之后會對每個模塊進行深度分析

 

第一節:服務端初始化

 

首先看下在我們用戶代碼中netty的使用最簡單的一個demo:

 

//創建boss和worker線程(1)
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
//創建ServerBootstrap(2)
ServerBootstrap b = new ServerBootstrap();
//初始化boss和work線程化兩個線程(3)
b.group(bossGroup, workerGroup)
        //聲明NioServerSocketChannel(4)
        .channel(NioServerSocketChannel.class)
        //初始化客戶端Handler(5)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) {
                ch.pipeline().addLast(new StringDecoder());
                ch.pipeline().addLast(new StringEncoder());
                ch.pipeline().addLast(new ServerHandler());
            }
        });
//綁定端口(6)
ChannelFuture f = b.bind(8888).sync();
f.channel().closeFuture().sync();

 

相信這段代碼使用過netty的同學應該都不陌生.這里每一步都用了注釋和步驟序號進行標注, 為了方便學習過程中更容易的定位.每一步的講解, 盡量自己也去跟到源碼中, 這樣會有個更深刻的理解

第一步, 創建兩個線程組:

其中會調用NioEventLoopGroup()的構造方法, 其中的創建邏輯, 並不是這章的重點, 在這里大家只需要知道這里創建了兩個線程組

第二步, 創建ServerBootstrap, 我們發現, 這里創建只調用了其無參的構造方法, 原因很簡單, 就是參數太多, 盡量要用構造方法去初始化, 而是使用后面的build的方式

第三步, 初始化bosswork線程化兩個線程

 

我們跟到group方法中去看:

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { //設置線程池組
    super.group(parentGroup); this.childGroup = childGroup; return this; }

為了代碼可讀性, 去掉非關鍵代碼(以后不再贅述), 我們看到這里初始化了自家的屬性childGroup, 而這個屬性就是我們傳入的worker線程組, boss線程組則交給了其父類的group方法去做處理

 

我們點進去super.group(parentGroup), 進入到ServerBootstroop的父類AbstractBootstrapgroup()方法:

public B group(EventLoopGroup group) { this.group = group; return (B) this; }

看到在其父類初始化了boss線程

我們看到這個方法返回了this, 也就是ServerBootstroop自身, 這樣通過自身對象不斷的build進行屬性初始化, 之后的方法也是如此

至此, workerboss兩個線程組初始化完畢

 

回到最開始的第四步, 再點進到channel(ServerSocketChannel.class)方法當中, 我們看到AbsractServerBootstrapchannel(Class<? extends C> channelClass)方法:

public B channel(Class<? extends C> channelClass) { return channelFactory(new ReflectiveChannelFactory<C>(channelClass)); }

我們看到這個這返回的是channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法, 並且傳入一個ReflectiveChannelFactory對象的實例,

我們可以跟進去看下ReflectiveChannelFactory的構造方法:

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

這里初始化了一個成員變量clazz, 而這個clazz就是用戶代碼調用channel(NioServerSocketChannel.class)傳入的NioServerSocketChannelclass對象

 

回到channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法, 點進去, 我們看到:

public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) { return channelFactory((ChannelFactory<C>) channelFactory); }

繼續跟:

public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) { return channelFactory((ChannelFactory<C>) channelFactory); }

跟到最后:

public B channelFactory(ChannelFactory<? extends C> channelFactory) { this.channelFactory = channelFactory; return (B) this; }

這里初始化了channelFactory, 而這個channelFactory就是剛才創建的ReflectiveChannelFactory對象, 這里我們記住這個對象中初始化了我們的NioServerSocketclass對象

至此, 我們的ServerSocketChannelclass對象初始化完成

 

我們跟到最開始的第五步, 初始化客戶端Handler:

.childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new StringEncoder()); ch.pipeline().addLast(new ServerHandler()); } });

childHandler()方法比看起來比較復雜, 其實不難理解, 就是傳入ChannelInitializer類子類的一個對象(有關匿名內部類不知道的同學可以找下相關資料學習下), 也就是一個Handler, 這個Handler是做什么的, 目前不需要關心, 以后會講到, 這里我們只需知道這個方法傳入一個handler對象

 

我們點進childHandler這個方法:

public ServerBootstrap childHandler(ChannelHandler childHandler) { this.childHandler = childHandler; return this; }

發現同樣非常簡單的初始化了handler屬性

這一小節至此結束, 只是初始化了ServerBootstrap的各個屬性, 是不是非常簡單

 

我們可以看到, 通過對象build的方式, 可以初始化非常多的屬性, 並且代碼要比構造方法的方式可讀性要好的多, 同學們可以將這種思想用在自己的代碼當中...

 

上一節: 前言, 概述及目錄

下一節: NioServerSocketChannel的創建

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM