Netty介绍及实战(一)

一、Netty到底是什么?什么是多路复用?什么叫做零拷贝?

        Netty是一个NIO客户端服务器框架,可以快速、轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和简化了网络编程,避免了程序本身去处理断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流等操作,也避免了程序直接对NIO的操作。使我们更加专注于业务的实现。

二、性能方面有哪些优势

1.更高的吞吐量,更低的延迟
2.减少资源消耗
3.最小化不必要的内存拷贝

三 、IO与NIO的区别

step1.首先我们了解一下什么是阻塞和非阻塞

netty比java nio对比_非阻塞

阻塞:阻塞的例子包括RPC和web service的调用。

非阻塞:包含非阻塞的队列和非阻塞模式的websocket,还有一些非阻塞模式的数据库等。

我们根据上图(左)可以看到:阻塞模式是一个线程发出请求后,阻塞等待调用结果。

上图(右):当一个线程发出请求后,不需要等待返回结果,可以再次发送请求。

step2.我们接下来看一个网络模型示意图:

netty比java nio对比_多路复用_02

        我们有一个线程池去管理线程和不同的客户端进行通信,其中有两个线程在阻塞状态,一个线程在传输状态,当第四个客户端连接的时候,我们发现没有线程可以用了,我们把他放在队列里面,当第五个线程来了,发现队列也满了,那么我们就只能丢弃这个客户端的连接了。

那么我们传统的网络模式有哪些有劣势呢?

优点:因为线程是阻塞的,直到整条请求发送完毕,我们不需要处理报文的粘包、拆包等。

缺点:频繁的上下文切换 , cpu消耗过高。如果线程过多的话,会导致内存使用过高。

四 、多路复用与零拷贝

step1.我们看一下阻塞io和非阻塞io的工作模式

netty比java nio对比_java_03

 图左:一个线程对应一个socket连接。

 图右: 一个线程对应不同的buffer,然后再通过buffer和socket channel建立连接。

step2:什么是零拷贝?

netty比java nio对比_java_04

netty比java nio对比_netty比java nio对比_05

netty比java nio对比_netty比java nio对比_06

        上图1,2: 可以看到,如果我们想要发送/接收一个报文,首先需要把内核数据拷贝到缓冲区里面,再进行操作

        上图3: 可以看到线程直接去读取内核的数据,这样就减少了内核到buffer的拷贝操作,直接操作堆外内存。

为什么非要操作堆外内存呢?这里画个重点

       1.操作系统并不感知jvm堆内存,而且jvm的内存布局与操作系统分配的不一致,所以操作系统不会直接操作jvm堆内存来处理数据

        2.我们知道jvm有着强大的GC机制,这也就意味着同一个对象的内存地址会随时发生变化。由于JNI(java native interface) 在调用IO操作的C语言的类库时,规定写入时地址不能失效,所以我们无法直接使用jvm堆内存。

step3:什么是多路复用?

释义:多路指的是多个socket连接,复用指的是复用同一个线程。

netty比java nio对比_非阻塞_07

       上图可以看到,我们利用一个线程select去管理不同的channel,只有当channel中有读写操作,才真正调用ready的channel去进行实际的IO操作。

那多路复用模型的优势时什么呢?

       IO多路复用使得我们只需要建立一个线程去维护客户端不同的请求(channel),不需要为每一个channel创建一个独立的线程,大大降低了系统的资源开销。

下一篇文章会和大家分享,传统的NIO架构和我们Netty的架构的区别,本文如有错误,欢迎大家批评指出。