IO-NIO-Netty

IO模型中,一個連接來了,會創(chuàng)建一個線程,對應一個while死循環(huán),死循環(huán)的目的就是不斷監(jiān)測這個連接上是否有數(shù)據(jù)可以讀。在大多數(shù)情況下,1萬個連接里面同一時刻只有少量的連接有數(shù)據(jù)可讀,因此,很多while死循環(huán)都白白浪費掉了,因為讀不出數(shù)據(jù)。數(shù)據(jù)讀寫是以字節(jié)流為單位的。

NIO模型中,這么多while死循環(huán)轉(zhuǎn)換為一個死循環(huán),這個死循環(huán)由一個線程控制,那么NIO又是如何做到一個線程一個while死循環(huán)就能監(jiān)測1萬個連接是否有數(shù)據(jù)可讀的呢?

這就是NIO模型中Selector的作用,一個連接來了之后,不會創(chuàng)建一個while死循環(huán)去監(jiān)聽是否有數(shù)據(jù)可讀,而是直接把這條連接注冊到Selector上。然后,通過檢查這個Selector,就可以批量監(jiān)測出有數(shù)據(jù)可讀的連接,進而讀取數(shù)據(jù)。

通常:

NIO模型中會有兩個線程,每個線程都綁定一個輪詢器Selector。serverSelector負責輪詢是否有新連接,clientSelector負責輪詢連接是否有數(shù)據(jù)可讀。

服務端監(jiān)測到新連接之后,不再創(chuàng)建一個新線程,而是直接將新連接綁定到clientSelector上,這樣就不用IO模型中的1萬個while循環(huán)死等。

clientSelector被一個while死循環(huán)包裹著,如果在某一時刻有多個連接有數(shù)據(jù)可讀,那么通過clientSelector.select(1)方法可以輪詢出來,進而批量處理。

數(shù)據(jù)的讀寫是面向Buffer的。

直接基于JDK原生NIO來進行網(wǎng)絡開發(fā)十分復雜而且很容易出bug,Netty封裝了NIO,不用再寫一大堆復雜代碼了。

使用JDK原生NIO需要了解太多概念,編程復雜,一不小心就Bug橫飛。

Netty底層IO模型隨意切換,而這一切只需要做微小的改動,改改參數(shù),Netty可以直接從NIO模型變身為IO模型。

Netty自帶的拆包/粘包、異常檢測等機制讓你從NIO的繁重細節(jié)中脫離出來,只需要關(guān)心業(yè)務邏輯即可。

Netty解決了JDK很多包括空輪詢在內(nèi)的Bug。

Netty底層對線程、Selector做了很多細小的優(yōu)化,精心設(shè)計的Reactor線程模型可以做到非常高效的并發(fā)處理。

自帶各種協(xié)議棧,讓你處理任何一種通用協(xié)議都幾乎不用親自動手。

Netty社區(qū)活躍,遇到問題隨時郵件列表或者Issue。

Netty已經(jīng)歷各大RPC框架、消息中間件、分布式通信中間件線上的廣泛驗證,健壯性無比強大。

用Netty來實現(xiàn)一個簡單的通信demo

Maven依賴

<dependency>

? ? ? ? <groupId>io.netty</groupId>

? ? ? ? <artifactId>netty-all</artifactId>

? ? ? ? <version>4.1.6.Final</version>

</dependency>


服務端:

public static void main(String[] args) {

? ? ? ? ServerBootstrap serverBootstrap =new ServerBootstrap();

NioEventLoopGroup boss =new NioEventLoopGroup();

NioEventLoopGroup worker =new NioEventLoopGroup();

serverBootstrap

? ? ? ? ? ? ? ? .group(boss,worker)

.channel(NioServerSocketChannel.class)

.childHandler(new ChannelInitializer() {

@Override

? ? ? ? ? ? ? ? ? ? protected void initChannel(NioSocketChannel ch) {

ch.pipeline().addLast(new StringDecoder());

ch.pipeline().addLast(new SimpleChannelInboundHandler() {

@Override

? ? ? ? ? ? ? ? ? ? ? ? ? ? protected void channelRead0(ChannelHandlerContext ctx,String msg) {

System.out.println(msg);

}

});

}

})

.bind(8000);

}

客戶端:

public static void main(String[] args)throws InterruptedException {

Bootstrap bootstrap =new Bootstrap();

NioEventLoopGroup group =new NioEventLoopGroup();

bootstrap.group(group)

.channel(NioSocketChannel.class)

.handler(new ChannelInitializer() {

@Override

? ? ? ? ? ? ? ? protected void initChannel(Channel ch) {

ch.pipeline().addLast(new StringEncoder());

}

});

Channel channel =bootstrap.connect("127.0.0.1",8000).channel();

channel.close();

while (true) {

channel.writeAndFlush(new Date() +": hello world!");

Thread.sleep(2000);

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容