IO-NIO-Netty

IO模型中,一个连接来了,会创建一个线程,对应一个while死循环,死循环的目的就是不断监测这个连接上是否有数据可以读。在大多数情况下,1万个连接里面同一时刻只有少量的连接有数据可读,因此,很多while死循环都白白浪费掉了,因为读不出数据。数据读写是以字节流为单位的。

NIO模型中,这么多while死循环转换为一个死循环,这个死循环由一个线程控制,那么NIO又是如何做到一个线程一个while死循环就能监测1万个连接是否有数据可读的呢?

这就是NIO模型中Selector的作用,一个连接来了之后,不会创建一个while死循环去监听是否有数据可读,而是直接把这条连接注册到Selector上。然后,通过检查这个Selector,就可以批量监测出有数据可读的连接,进而读取数据。

通常:

NIO模型中会有两个线程,每个线程都绑定一个轮询器Selector。serverSelector负责轮询是否有新连接,clientSelector负责轮询连接是否有数据可读。

服务端监测到新连接之后,不再创建一个新线程,而是直接将新连接绑定到clientSelector上,这样就不用IO模型中的1万个while循环死等。

clientSelector被一个while死循环包裹着,如果在某一时刻有多个连接有数据可读,那么通过clientSelector.select(1)方法可以轮询出来,进而批量处理。

数据的读写是面向Buffer的。

直接基于JDK原生NIO来进行网络开发十分复杂而且很容易出bug,Netty封装了NIO,不用再写一大堆复杂代码了。

使用JDK原生NIO需要了解太多概念,编程复杂,一不小心就Bug横飞。

Netty底层IO模型随意切换,而这一切只需要做微小的改动,改改参数,Netty可以直接从NIO模型变身为IO模型。

Netty自带的拆包/粘包、异常检测等机制让你从NIO的繁重细节中脱离出来,只需要关心业务逻辑即可。

Netty解决了JDK很多包括空轮询在内的Bug。

Netty底层对线程、Selector做了很多细小的优化,精心设计的Reactor线程模型可以做到非常高效的并发处理。

自带各种协议栈,让你处理任何一种通用协议都几乎不用亲自动手。

Netty社区活跃,遇到问题随时邮件列表或者Issue。

Netty已经历各大RPC框架、消息中间件、分布式通信中间件线上的广泛验证,健壮性无比强大。

用Netty来实现一个简单的通信demo

Maven依赖

        io.netty

        netty-all

        4.1.6.Final


服务端:

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);

}

}

你可能感兴趣的:(IO-NIO-Netty)