「蘑菇街技术」每个人都想听的技术解析--Netty

作者:一川
小编先说:这篇内容同样是来自于内部分享的总结 。 网络编程永远是java工程师心中的一座高山 , 而Netty却是照亮山路的明灯 。 大多数没有深入过网络编程的人都对Netty充满好奇 , 今天一起来看看 。 这篇文章也是近期这个领域下为数不多的精彩好文 。
Netty概览
Netty是由Trustin Lee在2004年发布的异步事件驱动的网络应用程序框架 , 作者是个80年的韩国人 , 同时也是Apache Mina的作者 。 Netty封装了网络编程的复杂性 , 其开箱即用的特性 , 可以让你方便、高效去实现自己HTTP服务器 , FTP服务器 , UDP服务器 , RPC服务器 , WebSocket服务器 。
Netty业界应用
随着Netty的勃勃发展 , 由Netty构建的应用如雨后春笋般不断涌出 , 目前Netty已经被广泛应用于rpc框架、大数据、服务发现、消息中间件等多个领域.如我司的Rpc框架Tesla以及服务发现Discover;阿里的Dubbo、RocketMQ;大数据领域的Spark、Hadoop;
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
Netty在蘑菇街的应用
实际不仅仅上述所说的应用 , 实际在我司在很多应用中都使用了Netty来实现应用的网络通讯层 , 使用一个Boss线程和若干个线程处理epoll的注册和读写事件 , 在读事件处理完毕后 , 交由后台的线程池处理;不仅如此 , 在很多时候 , 也会使用Netty中的工具来优化我们的应用性能 。
Netty详解
在这一部分 , 主要会从IO传输模型、数据协议、线程模型这三个部分对Netty进行讲解 , 顺带会讲一下责任链模式在Netty中的应用 。
IO传输模型
IO传输模型决定了我们以何种方式更加高效的将我们的数据在内核空间、用户空间、IO设备之间复制、转换、处理 。
首先我们来简单的介绍一下IO传输模型 , 从系统层面上来说 , Linux支持五种IO传输模型 , 包括同步阻塞、同步非阻塞、IO多路复用、信号IO、异步IO , 而为什么要弄这么多传输模型呢?其实本质都是为了减少CPU在IO调用上的时间消耗 , 由于IO操作大都由系统内核调用来完成的 , 系统调用又是通过cpu来调度的 , 而CPU的速度远远快于IO操作 , 这样就会导致cpu会经常处于等IO操作的状态 , 这样的话 , 就会很浪费CPU的资源 , 为了减少cpu在调用IO时候的消耗 , 逐渐发展出各种IO模型 。
接着我们再说一下Java中的BIO、NIO、AIO , Java中的BIO就是基于同步阻塞模型实现的 , 它的好处就是代码实现起来简单、直观 , 缺点也很明显IO效率存在瓶颈 。 具体原理如下图所示 , 用户进程发送请求给内核 , 然后由内核去进行通信 , 在内核准备好之前 , 线程是被挂起的 , 所以在等待返回数据、复制数据这两个阶段程序都是处于挂起状态;类比成client和Server模式 , 则其实现模式为一个连接一个线程 , 即客户端有连接请求时 , 服务端就需要启动一个线程进行处理 , 待操作系统返回结果;如果这个连接不做任何事情 , 会造成不必要的线程开销 , 当然这也可以通过线程池机制来改善;
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
Java中的NIO是基于Linux中的IO多路复用模型实现的 , 如下图所示 , 在发起请求时去反复检查数据是否已经准备好 , 把原来大块不能用的阻塞时间分成许多小阻塞 , 检查的时候会有一些阻塞 , 类似自旋 , 所以线程会不断有机会的去被执行这个检查有没有准备好数据的过程;类比成client和server模式 , 其实现的模式为一个请求一个线程 , 及客户端发送的连接请求 , 都会注册到多路复用器上 , 多路复用器轮询到连接有IO请求时 , 才启动一个线程进行处理 。 这里也能看出来NIO在等待返回数据是非阻塞的 。
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
Java中的AIO属于Linux中异步模型 , 是基于事件和回调机制来实现的 。 可以理解为应用操作直接返回而不会阻塞在那里 , 当后台处理完成 , 就会通知响应线程进行后续工作 。
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
为什么Netty不再支持BIO和AIO呢 , 而独取NIO这一瓢呢?BIO通过上述分析我们应该也能知道为啥 , 当我们在连接数高的情况下 , 会有性能瓶颈;那为什么AIO也被弃用了呢 , 这就需要追究到系统层面上了,被常作为服务器的Linux中的AIO系统不仅不成熟 , 而且性能相较于NIO提升也不明显 , 所以Netty开发者认为没有必要大费周章去维护这么一套东西 。