日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Netty实战 IM即时通讯系统(四)服务端启动流程

發(fā)布時(shí)間:2024/4/30 windows 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty实战 IM即时通讯系统(四)服务端启动流程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

##

Netty實(shí)戰(zhàn) IM即時(shí)通訊系統(tǒng)(四)服務(wù)端啟動(dòng)流程

零、 目錄

  • IM系統(tǒng)簡介
    • Netty 簡介
    • Netty 環(huán)境配置
    • 服務(wù)端啟動(dòng)流程
    • 實(shí)戰(zhàn): 客戶端和服務(wù)端雙向通信
    • 數(shù)據(jù)傳輸載體ByteBuf介紹
    • 客戶端與服務(wù)端通信協(xié)議編解碼
    • 實(shí)現(xiàn)客戶端登錄
    • 實(shí)現(xiàn)客戶端與服務(wù)端收發(fā)消息
    • pipeline與channelHandler
    • 構(gòu)建客戶端與服務(wù)端pipeline
    • 拆包粘包理論與解決方案
    • channelHandler的生命周期
    • 使用channelHandler的熱插拔實(shí)現(xiàn)客戶端身份校驗(yàn)
    • 客戶端互聊原理與實(shí)現(xiàn)
    • 群聊的發(fā)起與通知
    • 群聊的成員管理(加入與退出,獲取成員列表)
    • 群聊消息的收發(fā)及Netty性能優(yōu)化
    • 心跳與空閑檢測
    • 總結(jié)
    • 擴(kuò)展

    ###四、 服務(wù)端啟動(dòng)流程

  • 服務(wù)端Demo

    public class NettyServer {public static void main(String[] args) {NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);NioEventLoopGroup workerGroup = new NioEventLoopGroup();ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {protected void initChannel(NioSocketChannel ch) {}});serverBootstrap.bind(8000);}}
  • 首先看到,我們創(chuàng)建了兩個(gè)NioEventLoopGroup ,這兩個(gè)對(duì)象可以看做是傳統(tǒng)IO線程的兩大線程組:
  • bossGroup: 表示監(jiān)聽端口 接收新連接的線程組 一般情況下 接口線程組配置一個(gè)線程即可 , NioEventLoopGroup 默認(rèn)的個(gè)數(shù)為 CPU核數(shù)*2
  • workerGroup: 表示處理每一條連接上的數(shù)據(jù)讀寫的線程組 , (這里不理解可以回顧上一小節(jié) 《Netty是什么》)
  • 用生活中的例子來講就是: 一個(gè)工廠要運(yùn)作 , 必然要有一個(gè)老板 負(fù)責(zé)在外面接活 ,然后有很多員工負(fù)責(zé)具體干活 , 老板們就是bossGroup 可以是1個(gè) 也可以使多個(gè) , 員工們就是worker . bossGroup就收連接 , 之后交給workerGroup 具體處理
  • 接下來我們創(chuàng)建了一個(gè)引導(dǎo)類 ServerBootStrap , 這個(gè)類將引導(dǎo)我們進(jìn)行服務(wù)端的啟動(dòng)工作。
  • 我們通過 serverBootstrap.group(bossGroup, workerGroup) 來給引導(dǎo)類配置兩大線程組 , 這個(gè)引導(dǎo)類的線程模型也就定型了
  • 然后我們指定服務(wù)端的IO模型為 NIO , 我們通過serverBootstrap.channel(NioServerSocketChannel.class) 來指定IO模型 , 當(dāng)然這里也可以有其他的選擇 , 如果你想指定IO 模型為 BIO , 那么這里配置OioServerSocketChannel.class類型即可 , 一般不會(huì)那么做 , 因?yàn)镹etty 的優(yōu)勢就在于NIO.
  • 接著我們調(diào)用childHandler()方法 , 給這個(gè)引導(dǎo)類創(chuàng)建一個(gè)ChannelInitializer , 這里主要就是定義每條連接的數(shù)據(jù)讀寫、業(yè)務(wù)處理邏輯 , 不理解沒關(guān)系 , 我們后面會(huì)詳細(xì)分析 。 ChannelInitializer 這個(gè)類中 我們注意到有一個(gè)泛型參數(shù)NioSocketChannel , 這個(gè)類就是Netty對(duì)NIO類型的連接的抽象 , 而我們前面NioServerSocketChannel也是對(duì)NIO類型的連接的抽象 , NioServerSocketChannel 和NioSocketChannel的概念相當(dāng)于BIO 模型中 ServerSocket 和Socket .
  • 到這里我們最小化參數(shù)配置就完成了 , 總結(jié)一下 , 想要啟動(dòng)一個(gè)Netty服務(wù)端 , 我們需要指定三個(gè)類屬性:線程模型、 IO模型、處理邏輯 , 有了這三者之后再調(diào)用 bind(8000) , 我們就可以在本地綁定一個(gè)8000端口啟動(dòng)起來 。

  • 自動(dòng)綁定遞增端口

  • 在上面代碼中我們直接綁定了8000端口 , 接下來我們實(shí)現(xiàn)一個(gè)稍微復(fù)雜的邏輯: 我們指定一個(gè)起始端口 , 比如:1000 , 然后判斷是否綁定成功 , 如果不成功就 綁定1001 , 直到成功為止。

  • serverBootStrap.bind() 這個(gè)方法時(shí)異步的 , 調(diào)用之后立即返回結(jié)果 , 但是并不知道是否綁定成功, 他的返回值是一個(gè)ChannelFuture , 我們可以給這個(gè)ChannelFuture 添加一個(gè)監(jiān)聽器 GenericFutureListener , 然后我們?cè)贕enericFutureListener 的operationComplete 方法里面 , 我們可以監(jiān)聽到端口是否綁定成功 , 接下來是檢測端口是否綁定成功的代碼:

    /**

    • 自動(dòng)遞增綁定有效端口

    • @author outman

    • */
      private static void bind(ServerBootstrap serverBootstrap, int port) {

      serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {

      @Overridepublic void operationComplete(Future<? super Void> future) throws Exception {if(future.isSuccess()) {System.out.println("成功綁定端口:"+port);}else {System.out.println("綁定端口失敗:"+ port);bind(serverBootstrap, port+1);}}

      });

    }
    執(zhí)行結(jié)果: (我的mysql 占用了3306端口 , 所以3306綁定失敗)
    綁定端口失敗:3306
    成功綁定端口:3307

  • 服務(wù)端啟動(dòng)相關(guān)的其他方法

  • handler(): handler() 方法可以和之前分析的childHandler() 對(duì)應(yīng)起來 ,childHandler() 用于指定處理新連接數(shù)據(jù)的業(yè)務(wù)邏輯 , handler用于指定服務(wù)端啟動(dòng)過程中的一些邏輯

    serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() {@Overrideprotected void initChannel(NioServerSocketChannel ch) throws Exception {System.out.println("服務(wù)端啟動(dòng)中..."); }});
  • attr(): attr()方法可以給服務(wù)端的channel , 也就是NioServerSocketChannel指定一些自定義屬性 , 然后我們可以通過channel.attr()取出這個(gè)屬性 , 比如 , 我們可以給服務(wù)端channel指定一個(gè)serverName 屬性 , 屬性值NettyServer , 其實(shí)說白了就是給NioServerSocketChannel維護(hù)了一個(gè)map:

    //設(shè)置服務(wù)端屬性serverBootstrap.attr(AttributeKey.newInstance("serverName"), "NettyServer");serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() {@Overrideprotected void initChannel(NioServerSocketChannel channel) throws Exception {// 取出服務(wù)端屬性Attribute<Object> serverName = channel.attr(AttributeKey.valueOf("serverName") );System.out.println( serverName.get()+"服務(wù)端啟動(dòng)中..."); }});
  • childAttr() : 可以通過childAttr 給每一條連接設(shè)置自定義屬性

    //給連接設(shè)置自定義屬性serverBootstrap.childAttr(AttributeKey.newInstance("clientName"), "NettyClient");serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel childChannel) throws Exception {// 取出連接中的自定義屬性childChannel.attr(AttributeKey.valueOf("clientName"));}});
  • childOption(): childOption方法可以給每條連接設(shè)置一些TCP底層相關(guān)的屬性:

  • ChannelOption.SO_KEEPALIVE表示是否開啟TCP底層心跳機(jī)制,true為開啟

  • ChannelOption其他參數(shù)詳解: https://www.cnblogs.com/googlemeoften/p/6082785.html

    serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);serverBootstrap.childOption(ChannelOption.SO_BACKLOG, 10);
  • option(): 給服務(wù)端channel 設(shè)置一些屬性:

    serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024)//表示系統(tǒng)用于存放已經(jīng)完成三次握手的請(qǐng)求的隊(duì)列的最大長度 , 如果建立連接頻繁, 服務(wù)器處理創(chuàng)建新連接較慢, 可以適當(dāng)調(diào)大這個(gè)參數(shù)。
  • 總結(jié)

  • 本節(jié)中我們首先學(xué)習(xí)了Netty的服務(wù)端啟動(dòng)流程 , 一句話來說就是: 創(chuàng)建一個(gè)引導(dǎo)類 , 然后給他設(shè)置線程模型 , 然后設(shè)置IO 模型 , 設(shè)置連接之后數(shù)據(jù)的業(yè)務(wù)處理邏輯 , 最后綁定端口啟動(dòng)服務(wù)。
  • 然后我們學(xué)到了 引導(dǎo)類的bind 方法時(shí)異步的 , 我們可以通過這個(gè)異步機(jī)制來實(shí)現(xiàn)端口自動(dòng)遞增綁定 。
  • 最后我們討論了Netty服務(wù)端啟動(dòng)額外的參數(shù) , 主要包括給服務(wù)端Channel或者客戶端Channel設(shè)置屬性值 , 設(shè)置底層TCP參數(shù)。
  • 如果你覺得這里講解比較簡單 , 想要深入學(xué)習(xí) ,傳送門: https://coding.imooc.com/class/chapter/230.html#Anchor
  • 疑問:

  • 在傳統(tǒng)的BIO 模型中 , 每接收一個(gè)新連接 就會(huì)創(chuàng)建一個(gè)新的線程 , 如果使用Netty 指定IO模型為NIO 則每接收一個(gè)新連接則會(huì)復(fù)用之前的線程處理業(yè)務(wù)邏輯 , 疑問: 如果使用Netty指定IO 模型為BIO 那么會(huì)復(fù)用之前的線程還是會(huì)創(chuàng)建一個(gè)新的線程?
  • 總結(jié)

    以上是生活随笔為你收集整理的Netty实战 IM即时通讯系统(四)服务端启动流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。