1.Netty基本-io模式埠胖,線程模型间聊,Reactor模式都啥呀族购?

關于IO模式,線程模型陵珍?

Java的io模型分為三種寝杖,(BIO,NIO,AIO),Netty現(xiàn)在主要推薦的(NIO),剩下的兩個曾經(jīng)實現(xiàn)互纯,現(xiàn)在不推薦使用瑟幕。IO模型于線程模型之間的關系,如下表:

BIO NIO AIO
Thread-Per-Connection Reactor Proactor


  • Thread-Per-Connection :一個客戶端對應一個線程處理 >業(yè)務邏輯>留潦。
  • Reactor只盹,因為是多路復用,所以有一個select選擇器兔院,可以注冊事件和獲取相應事件殖卑,則其核心流程:注冊感興趣的事件 -> 掃描是否有感興趣的事件發(fā)生 -> 事件發(fā)生之后做出相應的邏輯處理。具體不同注冊的事件如下表:
client/server SocketChannel/ServerSocketCannel OP_ACCEPT OP_CONNECT OP_WRITE OP_READ
client SocketChannel - 1 1 1
server ServerSocketChannel 1 - - -
server SocketChannel - - 1 1
  • Proactor【現(xiàn)在還不知道】

還是說說Reactor把坊萝,畢竟是Netty總結:

Reactor開發(fā)模式有三種:

具體可以從線程種類(線程的工作不同分為不同的種類如:++處理連接請求的線程++孵稽,++處理業(yè)務邏輯的線程++==自己瞎理解的==),線程數(shù)量兩個維度來展開十偶。Reactor的三種模型設計:

Reactor單線程模式

線程不分種類菩鲜,線程數(shù)量一個。即:一個線程搞定客戶端的連接請求和客戶端的讀寫惦积。
NIO代碼實現(xiàn):

/**
   * 順便說下 OP_WRITE 的情況接校。
   * 在寫數(shù)據(jù)到 SocketChannel 之前,沒必要先調用 key.isWritable()狮崩,而是應該在調用 channel.write(buffer) 的時候蛛勉,
   * 如果返回值是 0 或者和實際的緩存區(qū)大小不一致的值,這個時候才去注冊監(jiān)聽 OP_WRITE 事件厉亏,因為此時往往是由于數(shù)據(jù)接收方的問題或網(wǎng)絡問題導致寫操作掛起了董习。
   * @throws IOException
   */
  @Test
  public void server() throws IOException {
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    //配置非阻塞
    serverSocketChannel.configureBlocking(false);

    //綁定
    serverSocketChannel.bind(new InetSocketAddress(9898));

    //選擇器,綁定選擇器爱只,和選擇的事件
    Selector selector = Selector.open();
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    //輪詢獲取選擇器上已經(jīng)準備就緒的事件>0有一個key準備就緒
    while (selector.select() > 0) {
      //獲取當前選擇器中所有注冊的已經(jīng)就緒的監(jiān)聽事件
      Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
      while (iterator.hasNext()) {
        SelectionKey key = iterator.next();
        if (key.isAcceptable()) {
          //接收狀態(tài)就緒
          SocketChannel socketChannel = serverSocketChannel.accept();
          socketChannel.configureBlocking(false);

          //可以給這個channel關聯(lián)一個buffer
          //socketChannel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(1024));
          socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
        //1--------------------------------
          //讀就緒狀態(tài)的通道
          SocketChannel socketChannel = (SocketChannel) key.channel();

          //讀取數(shù)據(jù)
          ByteBuffer buffer = ByteBuffer.allocate(1024);
          int len = 0;
          while ((len = socketChannel.read(buffer)) != 0) {
            if (len == -1) {
              System.out.println("-1");
              //key.interestOps(key.interestOps() & ~SelectionKey.OP_READ); 與 key.cancel();同意皿淋,不刪除就一直響應可讀事件招刹。輸出-1
              key.cancel();
              break;
            }
            buffer.flip();
            System.out.println(new String(buffer.array(), 0, len));
            buffer.clear();
          }
          //2---------------------------------
          
        }
        //取消選擇鍵SelectionKey
        iterator.remove();
      }

    }
    serverSocketChannel.close();
  }

Netty中代碼體現(xiàn):部分

NioEventLoopGroup eventGroup = new NioEventLoopGroup(1);
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(eventGroup);

出現(xiàn)的問題:業(yè)務處理很慢的情況下,連接請求進來可能超時處理不到窝趣。

非主從Reactor多線程模式

一個線程處理鏈接請求和讀寫請求疯暑,只不過這里的讀寫的邏輯處理方法其他線程中去處理了。

  • Nio代碼哑舒,在上面代碼修改妇拯,把//1---- //2---這部分邏輯放在其他線程中處理就可以了。

  • Netty中代碼體現(xiàn):

NioEventLoopGroup eventGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(eventGroup);

主從Reactor多線程模式

從這里開起區(qū)分線程種類了:一類線程處理連接請求,一類是處理讀寫請求的洗鸵。

  • NIO中代碼實現(xiàn):
    實現(xiàn)思路:首先開兩個及其以上Selector越锈,其中一個serverSocketChannel注冊OP_ACCEPT,剩下的socketChannel的OP_WRITE和OP_READ事件膘滨,每個Selector在不同的線程中輪訓遍歷準備好的事件甘凭。

  • Netty中代碼體現(xiàn):

NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup,workGroup);

其中關于處理連接請求的線程數(shù)的問題?如果服務端只開了一個端口的話火邓,處理連接請求的線程用一個就可以了丹弱,所以上面的Nio代碼實現(xiàn)思路中默認只開一個端口。只用一個線程輪訓一個Selector就可以了铲咨,所以在Netty中NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);可以直接寫入1躲胳,不寫開一個端口其實也只是用到了一個線程。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末纤勒,一起剝皮案震驚了整個濱河市坯苹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摇天,老刑警劉巖北滥,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闸翅,居然都是意外死亡再芋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門坚冀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來济赎,“玉大人,你說我怎么就攤上這事记某∷狙担” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵液南,是天一觀的道長。 經(jīng)常有香客問我滑凉,道長统扳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任吹由,我火速辦了婚禮,結果婚禮上朱嘴,老公的妹妹穿的比我還像新娘倾鲫。我一直安慰自己,他們只是感情好萍嬉,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著玫荣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪大诸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天贯卦,我揣著相機與錄音资柔,去河邊找鬼。 笑死贿堰,一個胖子當著我的面吹牛,可吹牛的內容都是我干的羹与。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼纵搁,長吁一口氣:“原來是場噩夢啊……” “哼往踢!你這毒婦竟也來了?” 一聲冷哼從身側響起峻呕,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘦癌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讯私,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡西傀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年楞黄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鬼廓。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尤慰,靈堂內的尸體忽然破棺而出雷蹂,到底是詐尸還是另有隱情伟端,我是刑警寧澤匪煌,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站萎庭,受9級特大地震影響霜医,放射性物質發(fā)生泄漏。R本人自食惡果不足惜驳规,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一肴敛、第九天 我趴在偏房一處隱蔽的房頂上張望吗购。 院中可真熱鬧医男,春花似錦捻勉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禽捆。三九已至,卻和暖如春胚想,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浊服。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工胚吁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愁憔,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓吨掌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窿侈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內容