最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Netty分布式server啟動流程N(yùn)io創(chuàng)建源碼分析

 更新時(shí)間:2022年03月25日 10:03:43   作者:向南是個(gè)萬人迷  
這篇文章主要介紹了Netty分布式server啟動流程N(yùn)io創(chuàng)建源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前文傳送門 Netty分布式Server啟動流程服務(wù)端初始化源碼分析

NioServerSocketChannel創(chuàng)建

我們?nèi)绻煜io, 則對channel的概念則不會陌生, channel在相當(dāng)于一個(gè)通道, 用于數(shù)據(jù)的傳輸

Netty將jdk的channel進(jìn)行了包裝, 并為其擴(kuò)展了更多的功能

在netty中也分為服務(wù)端channel和客戶端channel, 在Nio模式下, 服務(wù)端channel對應(yīng)的類為NioServerSocketChannel, 包裝的jdk的ServerSocketChannel

客戶端channel對應(yīng)的類為NioSocketChannel, 所包裝的jdk的類為SocketChannel

繼承關(guān)系

最簡單的繼承關(guān)系如下(經(jīng)簡化):

我們繼續(xù)看第一小節(jié)demo:

//創(chuàng)建boss和worker線程(1)
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
//創(chuàng)建ServerBootstrap(2)
ServerBootstrap b = new ServerBootstrap();
//初始化boss和work線程化兩個(gè)線程(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();

綁定端口

我們繼續(xù)看第六步, 綁定端口:

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

在此, 我們看到綁定了8888端口

我們跟到bind(8888)方法中:

public ChannelFuture bind(int inetPort) {
    return bind(new InetSocketAddress(inetPort));
}

端口封裝成socket地址對象

繼續(xù)跟bind方法:

public ChannelFuture bind(SocketAddress localAddress) {
    validate();
    return doBind(localAddress);
}

validate()做了一些屬性驗(yàn)證

我們繼續(xù)跟到doBind(localAddress)方法:

private ChannelFuture doBind(final SocketAddress localAddress) {
    //初始化并注冊(1)
    final ChannelFuture regFuture = initAndRegister();
    //獲得channel(2)
    final Channel channel = regFuture.channel();
    if (regFuture.cause() != null) {
        return regFuture;
    }
    if (regFuture.isDone()) {
        ChannelPromise promise = channel.newPromise();
        //綁定(3) 
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        //去除非關(guān)鍵代碼
        return promise;
    }
}

去除了一些非關(guān)鍵的代碼, 重點(diǎn)關(guān)注注釋標(biāo)注的第一步, 初始化并注冊:

final ChannelFuture regFuture = initAndRegister();

跟進(jìn)initAndRegister()方法 創(chuàng)建channel

final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        //創(chuàng)建channel
        channel = channelFactory.newChannel();
        init(channel);
    } catch (Throwable t) {
        //忽略非關(guān)鍵代碼
    }
    ChannelFuture regFuture = config().group().register(channel);
    //忽略非關(guān)鍵代碼
    return regFuture;
}

關(guān)注添加注釋的步驟, 創(chuàng)建channel, 這一點(diǎn)也是我們這節(jié)需要講明白的內(nèi)容

看這一步:

channel = channelFactory.newChannel();

這里channelFactory調(diào)用了newChannel()的這個(gè)方法, 這個(gè)方法從名字就不難理解, 是新建一個(gè)channel, 回顧下上一小節(jié), 這個(gè)channelFactory是在哪里初始化呢?

根據(jù)上一小節(jié)代碼, channelFactory是在Bootstrap的channelFactory ()方法初始化的:

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

而這個(gè)方法又是channel()方法中調(diào)用的:

public B channel(Class&lt;? extends C&gt; channelClass) {
    return channelFactory(new ReflectiveChannelFactory&lt;C&gt;(channelClass));
}

這里傳入ReflectiveChannelFactory對象就是初始化的channelFactory對象

所以newChannel()是調(diào)用ReflectiveChannelFactory對象的newChannel方法

跟到ReflectiveChannelFactory對象的newChannel方法中:

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

我們看到這個(gè)clazz對象通過反射創(chuàng)建了channel, 這個(gè)clazz對象, 就是我們上一節(jié)提到過的, 初始化的NioServerSocketChannel的class對象

這里通過反射調(diào)用, 會創(chuàng)建一個(gè)NioServerSokectChannel

學(xué)習(xí)過nio的小伙伴都知道jdk的ServerSocketChannel, 用于接受鏈接事件, 而netty的NioServerSocketChannel是和jdk的channel有什么關(guān)系呢?

實(shí)際上netty的channel和jdk的channel的含義一樣, 也是一個(gè)通道, 只是netty為其做了擴(kuò)展, 而channel的事件處理, 也是通過jdk的channel去做的, 我們跟隨著NioServerSocketChannel的創(chuàng)建過程, 來了解他們之間的關(guān)聯(lián)關(guān)系

clazz.newInstance()通過反射創(chuàng)建一個(gè)NioServerSocketChannel對象, 首先會走到NioServerSocketChannel的構(gòu)造方法, 我們跟到他的構(gòu)造方法, 查看NioServerSocketChannel的創(chuàng)建過程

首先會調(diào)用它的無參構(gòu)造方法:

public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

我們看到這個(gè)構(gòu)造方法調(diào)用了另一個(gè)有參的構(gòu)造方法, 傳入?yún)?shù)是 newSocket(DEFAULT_SELECTOR_PROVIDER) 

我們首先看DEFAULT_SELECTOR_PROVIDER這個(gè)這變量:

private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

看到這初始化了一個(gè)SelectorProvider對象, 而這個(gè)對象是通過靜態(tài)方法provider()創(chuàng)建的, SelectorProvider對象可以用于創(chuàng)建jdk底層的ServerSocketChannel

我們繼續(xù)跟到newSocket(DEFAULT_SELECTOR_PROVIDER)中:

private static ServerSocketChannel newSocket(SelectorProvider provider) {
    return provider.openServerSocketChannel();
}

去掉try-catch塊, 發(fā)現(xiàn)這個(gè)方法是通過SelectorProvider對象的openServerSocketChannel()方法創(chuàng)建一個(gè)jdk底層的ServerSocketChannel, 至此我們可以知道, 與NioServerSokectChannel綁定的jdk底層的ServerSocketChannel就是這么創(chuàng)建的

父類的構(gòu)造方法

那么創(chuàng)建之后如何與netty的channel綁定?繼續(xù)跟代碼

跟到this(newSocket(DEFAULT_SELECTOR_PROVIDER))中:

public NioServerSocketChannel(ServerSocketChannel channel) {
    super(null, channel, SelectionKey.OP_ACCEPT);
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

我們看到這里調(diào)用了父類的構(gòu)造方法,繼續(xù)往里跟:

protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent, ch, readInterestOp);
}

這里調(diào)用了其父類AbstractNioMessageChannel類的構(gòu)造方法, AbstractNioMessageChannel這個(gè)類同學(xué)們請記住, 有關(guān)是NioServerSocketChannel的父類, 代表著服務(wù)端channel的相關(guān)屬性和操作, 之后有關(guān)服務(wù)端channel的一些事件會在這個(gè)類中完成

我們看到這個(gè)類的構(gòu)造方法中又調(diào)用了它的父類的構(gòu)造方法, 我們繼續(xù)跟:

protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent);
    //保存channel
    this.ch = ch;
    //綁定事件
    this.readInterestOp = readInterestOp;
    try {
        //設(shè)置為非阻塞
        ch.configureBlocking(false);
    } catch (IOException e) {
        //去掉非關(guān)鍵代碼
    }
}

這里又調(diào)用了其父類AbstractChannel的構(gòu)造方法, 跟進(jìn)去這個(gè)方法之前, 我們先往下看

首先看這一步:

this.ch = ch;

這步就是綁定jdk底層的ServerSocketChannel, 至此我們知道, jdk的channel和netty定義的channel是組合關(guān)系, netty的channel中有個(gè)jdk的channel的成員變量, 而這個(gè)成員變量就定義在AbstractNioChannel這個(gè)類當(dāng)中, 希望同學(xué)們將這個(gè)結(jié)論牢牢記住, 對以后的學(xué)習(xí)很有幫助

將jdk的channel設(shè)置為非阻塞模式

我們看到后面的這一步:

ch.configureBlocking(false);

這一步, 就是將jdk的channel設(shè)置為非阻塞模式, 這里熟悉Nio的同學(xué)應(yīng)該不會陌生, 這里不再贅述

 我們繼續(xù)跟到super(parent)中, 走到其父類AbstractChannel的構(gòu)造方法:

protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId();
    unsafe = newUnsafe();
    pipeline = newChannelPipeline();
}

首先看下這個(gè)parent, 這個(gè)parent是NioServerSocketChannel調(diào)用其父類構(gòu)造方法傳入的, 傳入的是null, 所以這一步AbstractChannel的屬性parent也是null, 這個(gè)parent, 我們之后再講客戶端channel的時(shí)候會講到

id = newId()是為每個(gè)channel創(chuàng)建一個(gè)唯一id

我們重點(diǎn)關(guān)注下后兩步:

unsafe = newUnsafe();
pipeline = newChannelPipeline();

這里初始化了兩個(gè)屬性unsafe, 和pipeline, 目前我們只需要知道這兩個(gè)屬性是在這里初始化的, 至于這兩個(gè)屬性的概念, 后面的章節(jié)會講到

以上就是創(chuàng)建NioServerSocketChannel的過程, 同學(xué)們可以課后跟進(jìn)源碼去熟悉鞏固

以上就是Netty分布式server啟動流程N(yùn)io創(chuàng)建源碼分析的詳細(xì)內(nèi)容,更多關(guān)于Netty分布式server啟動流程N(yùn)io創(chuàng)建的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • spring注解如何為bean指定InitMethod和DestroyMethod

    spring注解如何為bean指定InitMethod和DestroyMethod

    這篇文章主要介紹了spring注解如何為bean指定InitMethod和DestroyMethod,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • IDEA配置Gradle及Gradle安裝的實(shí)現(xiàn)步驟

    IDEA配置Gradle及Gradle安裝的實(shí)現(xiàn)步驟

    本文主要介紹了IDEA配置Gradle及Gradle安裝的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • java中volatile不能保證線程安全(實(shí)例講解)

    java中volatile不能保證線程安全(實(shí)例講解)

    下面小編就為大家?guī)硪黄猨ava中volatile不能保證線程安全(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Mybatis 將table表名作為參數(shù)傳入操作

    Mybatis 將table表名作為參數(shù)傳入操作

    這篇文章主要介紹了Mybatis 將table表名作為參數(shù)傳入操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • java如何在項(xiàng)目中實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出功能

    java如何在項(xiàng)目中實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出功能

    這篇文章主要介紹了java如何在項(xiàng)目中實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出功能的相關(guān)資料,EasyExcel是一個(gè)基于Apache?POI開發(fā)的開源Java庫,用于簡化Excel文件的讀寫操作,文中將用法介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • springboot啟動時(shí)如何指定spring.profiles.active

    springboot啟動時(shí)如何指定spring.profiles.active

    這篇文章主要介紹了springboot啟動時(shí)如何指定spring.profiles.active問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 淺談shiro的SecurityManager類結(jié)構(gòu)

    淺談shiro的SecurityManager類結(jié)構(gòu)

    下面小編就為大家?guī)硪黄獪\談shiro的SecurityManager類結(jié)構(gòu)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Mybatis一對多查詢列表屬性處理示例詳解

    Mybatis一對多查詢列表屬性處理示例詳解

    使用MyBatis進(jìn)行多表聯(lián)查的關(guān)鍵是構(gòu)建數(shù)據(jù)庫中表的字段和java中對象的屬性的映射關(guān)系,下面這篇文章主要給大家介紹了關(guān)于Mybatis一對多查詢列表屬性處理的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • JavaWeb實(shí)現(xiàn)文件上傳功能詳解

    JavaWeb實(shí)現(xiàn)文件上傳功能詳解

    這篇文章主要介紹了JavaWeb實(shí)現(xiàn)文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • springboot+redis實(shí)現(xiàn)微博熱搜排行榜的示例代碼

    springboot+redis實(shí)現(xiàn)微博熱搜排行榜的示例代碼

    本文主要介紹了springboot+redis實(shí)現(xiàn)微博熱搜排行榜的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05

最新評論

莱西市| 上栗县| 龙口市| 广元市| 剑阁县| 丘北县| 丹寨县| 抚远县| 山东省| 揭西县| 凤山市| 饶平县| 牡丹江市| 太谷县| 长岛县| 万安县| 醴陵市| 峨眉山市| 文化| 丹阳市| 德庆县| 封丘县| 电白县| 石嘴山市| 灵台县| 巍山| 平遥县| 登封市| 连云港市| 潼关县| 宜丰县| 普格县| 安阳市| 正定县| 宁远县| 鸡泽县| 开江县| 土默特左旗| 长沙县| 濮阳市| 化德县|