一、Netty简介
Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。
Netty 是一个 NIO client-server(客户端服务器)框架,使用 Netty 可以快速开发网络应用,例如服务器和客户 端协议。 Netty 提供了一种新的方式来使开发网络应用程序,这种新的方式使得它很容易使用和有很强的扩展性。
Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
Netty 是一个广泛使用的 Java 网络编程框架。它活跃和成长于用户社区,像大型公司 Facebook 和 Instagram 以及流行 开源项目如 Infinispan, HornetQ, Vert.x, Apache Cassandra 和 Elasticsearch 等,都利用其强大的对于网络抽象的核心代码。
Hadoop的RPC框架avro使用Netty作为底层通信框架,很多其它业界主流的RPC框架 dubbo,也使用Netty来构建高性能的异步通信能力。
注意:网上很多资料说Netty是异步通信框架,应该是从编程模型的角度说的。java nio的io模型是同步非阻塞,这里的同步异步指的是真正io操作(数据内核态用户态的拷贝)是否需要用户进程参与。而说java nio提供了异步处理,这个异步应该是指编程模型上的异步。基于reactor模式的事件驱动,事件处理器的注册和处理器的执行是异步的。
Netty目前4.0的版本应该是“非阻塞”的“同步IO”(按照Unix IO模型定义)。之前曾经有版本支持“异步IO”(按照Unix IO模型定义),但是因为某些原因被后来版本移除了。不管Netty是“同步IO”还是“异步IO”(按照Unix IO模型定义),其实我们应用的层面是不需要区分的,因为这是框架底层封装处理。我们应该仅仅关心是我的业务客户端代码调用Netty的API时候客户端程序是否会停顿等待。
广义的异步,非阻塞,都可以直接理解为正在执行的线程“不停顿等待”.
作为普通应用开发者调用Netty的API,无非就是关心自己调用的API方法是否让自己的主线程停顿等待API执行结果,这种场景下是其实不需要考虑异步和非阻塞的区别的,叫异步也好,叫非阻塞也好。也就是广义的异步和非阻塞等同于”不停顿等待”。
首先,在Unix的IO模型里:异步I/O 是指用户程序发起IO请求后,不等待数据,同时操作系统内核负责I/O操作把数据从内核拷贝到用户程序的缓冲区后通知应用程序。数据拷贝是由操作系统内核完成,用户程序从一开始就没有等待数据,发起请求后不参与任何IO操作,等内核通知完成。
同步I/O 就是非异步IO的情况,也就是用户程序要参与把数据拷贝到程序缓冲区(例如java的InputStream读字节流过程)。
同步IO里的非阻塞 是指用户程序发起IO操作请求后不等待数据,而是调用会立即返回一个标志信息告知条件不满足,数据未准备好,从而用户请求程序继续执行其它任务。执行完其它任务,用户程序会主动轮询查看IO操作条件是否满足,如果满足,则用户程序亲自参与拷贝数据动作。
Unix IO模型的语境下,同步和异步的区别在于数据拷贝阶段是否需要完全由操作系统处理。阻塞和非阻塞操作是针对发起IO请求操作后是否有立刻返回一个标志信息而不让请求线程等待。基于这个语境,Netty目前的版本是没有把IO操作交过操作系统处理的,所以是属于同步的。对于网上大部分文章,如果别人说Netty是异步非阻塞,如果要深究,那真要看看Netty新的版本是否把IO操作交过操作系统处理,或者看看有否使用JDK1.7中的AIO API,否则他们说的异步其实是指客户端程序调用Netty的IO操作API“不停顿等待”。异步和非阻塞一样吗? (内容涉及BIO,NIO,AIO,Netty)
二、为什么要用Netty
不使用NIO的原因:
- NIO 的类库和 API 繁杂,使用麻烦,你需要熟练掌握 Selector、ServerSocketChannel 、SocketChannel、ByteBuffer 等。
- 使用 JAVA NIO 需要具备其他的额外技能做铺垫,例如熟悉 Java 多线程编程。这是因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的 NIO 程序。
- JAVA NIO 的 ByteBuffer 构造函数私有,无法扩展。Netty 提供了自己的 ByteBuffer 实现,通过简单 APIs 对其进行构造、使用和操作,一此解决 NIO 的一些限制。
- 可靠性能力补齐,工作量和难度都非常大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题。
- 跨平台与兼容性:NIO 算是底层的 APIs 需依赖系统的 IO APIs。但 Java NIO 发现在不同系统平台会出现问题。大量测试也耗不少时间;NIO2 只支持 JDK1.7+,而且没提供DatagramSocket,故 NIO2 不支持 UDP 协议。而 Netty 提供统一接口,同一语句无论在JDK6.X 还是 JDK7.X 都可运行,无需关心底层架构功能!
- JDK NIO 的 BUG,例如臭名昭著的epoll bug,它会导致 Selector 空轮询,最终导致CPU 100%。官方声称在 JDK 1.6 版本的update18 修复了该问题,但是直到 JDK 1.7版本该问题仍旧存在,只不过该 BUG 发生概率降低了一些而已,它并没有得到根本性解决。
用Netty的好处:
- API使用简单,开发门槛低。
- 功能强大,预置了多种编解码功能,支持多种协议开发。
- 定制能力强,可以通过ChannelHadler进行扩展。
- 性能高,对比其它NIO框架,Netty综合性能最优。
- 经历了大规模的应用验证。在互联网、大数据、网络游戏、企业应用、电信软件得到成功,很多著名的框架通信底层就用了Netty,比如Dubbo
- 稳定,修复了NIO出现的所有Bug。
- 切换IO和NIO,因为IO和NIO的API完全不同,相互切换非常困难。
三、Netty的版本
官网http://netty.io/ 最新版本如下:
不同版本的差异参考:https://stackoverflow.com/questions/30457648/different-netty-versions-and-their-purposes
3.x比较旧,5.x被废弃,主要选择是4.0和4.1。
3.x是过时的。我们维护它是因为一些用户仍然广泛使用它。
4是当前稳定版本。如果有疑问,请使用这个版本。
4.1是一个向后兼容的4版本。它添加了一些很酷的新特性,如HTTP / 2和异步DNS解析器。所以,当你的应用程序已经在4上运行时,你可能想要尝试4.1版本,你想试试新的特性。
《NETTY官方文档》4.0的新特性及注意点:http://ifeve.com/netty-4-0-new/
《NETTY官方文档》4.1的新特性及注意点:http://ifeve.com/new-and-noteworthy-in-4-1/