在开始之前,我先讲一个亲身经历的故事:曾经有两个项目组同时用到了NIO编程技术,一个项目组选择自己开发NIO服务端,直接使用JDK原生的API,结果两个多月过去了,他们的NIO服务端始终无法稳定,问题频出。由于NIO通信是它们的核心组件之一,因此项目的进度受到了严重的影响。另一个项目组直接使用Netty作为NIO服务端,业务的定制开发工作量非常小,测试表明,功能和性能都完全达标,项目组几乎没有在NIO服务端上花费额外的时间和精力,项目进展也非常顺利。

这两个项目组的不同遭遇告诉我们:开发出高质量的NIO程序并不是一件简单的事情,除去NIO固有的复杂性和BUG不谈,作为一个NIO服务端,需要能够处理网络的闪断、客户端的重复接入、客户端的安全认证、消息的编解码、半包读写等情况,如果你没有足够的NIO编程经验积累,一个NIO框架的稳定往往需要半年甚至更长的时间。更为糟糕的是,一旦在生产环境中发生问题,往往会导致跨节点的服务调用中断,严重的可能会导致整个集群环境都不可用,需要重启服务器,这种非正常停机会带来巨大的损失。

从可维护性角度看,由于NIO采用了异步非阻塞编程模型,而且是一个I/O线程处理多条链路,它的调试和跟踪非常麻烦,特别是生产环境中的问题,我们无法进行有效的调试和跟踪,往往只能靠一些日志来辅助分析,定位难度很大。

1不选择Java原生NIO编程的原因

现在我们总结一下为什么不建议开发者直接使用JDK的NIO类库进行开发,具体原因如下。

(1)NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。

(2)需要具备其他的额外技能做铺垫,例如熟悉Java多线程编程。这是因为NIO编程涉及到Reactor模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的NIO程序。

(3)可靠性能力补齐,工作量和难度都非常大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题,NIO编程的特点是功能开发相对容易,但是可靠性能力补齐的工作量和难度都非常大。

(4)JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU
100%。官方声称在JDK 1.6版本的update18修复了该问题,但是直到JDK 1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有得到根本性解决。该BUG以及与该BUG相关的问题单可以参见以下链接内容。

◎   
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933

◎   
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719

异常堆栈如下。

java.lang.Thread.State: RUNNABLE

 at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)

        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)

        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)

at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)

- locked <0x0000000750928190> (a sun.nio.ch.Util$2)

- locked <0x00000007509281a8> (a java.util.Collections$ UnmodifiableSet)

- locked <0x0000000750946098> (a sun.nio.ch.EPollSelectorImpl)

 at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)

at net.spy.memcached.MemcachedConnection.handleIO(Memcached Connection.java:217)

at net.spy.memcached.MemcachedConnection.run(MemcachedConnection. java:836)

由于上述原因,在大多数场景下,不建议大家直接使用JDK的NIO类库,除非你精通NIO编程或者有特殊的需求。在绝大多数的业务场景中,我们可以使用NIO框架Netty来进行NIO编程,它既可以作为客户端也可以作为服务端,同时支持UDP和异步文件传输,功能非常强大。

下个小节我们就看看为什么选择Netty作为基础通信框架。

2为什么选择Netty

Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是首屈一指的,它已经得到成百上千的商用项目验证,例如Hadoop的RPC框架Avro就使用了Netty作为底层通信框架,其他还有业界主流的RPC框架,也使用Netty来构建高性能的异步通信能力。

通过对Netty的分析,我们将它的优点总结如下。

◎   
API使用简单,开发门槛低;

◎   
功能强大,预置了多种编解码功能,支持多种主流协议;

◎   
定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;

◎   
性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优;

◎   
成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦恼;

◎   
社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会加入;

◎   
经历了大规模的商业应用考验,质量得到验证。Netty在互联网、大数据、网络游戏、企业应用、电信软件等众多行业已经得到了成功商用,证明它已经完全能够满足不同行业的商业应用了。

正是因为这些优点,Netty逐渐成为了Java NIO编程的首选框架。

为什么选择Netty作为基础通信框架?的更多相关文章

  1. 新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析

    1.引言 Netty 是一个广受欢迎的异步事件驱动的Java开源网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件 ...

  2. Netty高性能原理和框架架构解析

    1.引言 Netty 是一个广受欢迎的异步事件驱动的Java开源网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件 ...

  3. Java NIO通信框架在电信领域的实践

    [http://www.codeceo.com/article/java-nio-communication.html]   华为电信软件技术架构演进 Java NIO框架在技术变迁中起到的关键作用 ...

  4. Spark1.6之后为何使用Netty通信框架替代Akka

    解决方案: 一直以来,基于Akka实现的RPC通信框架是Spark引以为豪的主要特性,也是与Hadoop等分布式计算框架对比过程中一大亮点. 但是时代和技术都在演化,从Spark1.3.1版本开始,为 ...

  5. 基于Java Mina 和Netty 通信框架的JT/T809转发服务器设计

    Apache MINA 是 Apache 组织的一个开源项目,为开发高性能和高可用性的网络应用程序提供了非常便利的框架. 也是Java开发者的一个福利(.NET目前还没有类似封装的这么好的基础sock ...

  6. RPC框架motan: 通信框架netty( 1)

    服务器端编程都离不开底层的通信框架,在我们刚学习java的时候,主要接触都是Socket和ServerSocket 的阻塞编程,后来开始了解NIO,这种非阻塞的编程模式,它可以一个线程管理很多的Soc ...

  7. SpringBoot2+Netty打造通俗简版RPC通信框架(升级版)

    背景         上篇文章我简单的介绍了自己打造的通俗简版RPC通信框架,这篇是对简版的增强~         如果大家对此项目还感兴趣的话,可到码云上瞄瞄:Netty-RPC         上 ...

  8. SpringBoot2+Netty打造通俗简版RPC通信框架

    2019-07-19:完成基本RPC通信! 2019-07-22:优化此框架,实现单一长连接! 2019-07-24:继续优化此框架:1.增加服务提供注解(带版本号),然后利用Spring框架的在启动 ...

  9. 基于Java Mina 通信框架的JT/T809转发服务器设计

    Apache MINA 是 Apache 组织的一个开源项目,为开发高性能和高可用性的网络应用程序提供了非常便利的框架. 也是Java开发者的一个福利(.NET目前还没有类似封装的这么好的基础sock ...

随机推荐

  1. JavaScript转unix时间戳

    由于 unix 的时间戳是10位不带毫秒的,所以前端获取到时间戳之后需要做一下处理,才能获取正确的时间. // 假设这里是从服务端获取到的时间戳 var unixTime = data.time; / ...

  2. win10下配置php环境变量

    下载php,解压. 比如解压到E盘,目录为"E:\PHP". 打开php目录,复制一个php.ini-development文件,改名为php.ini. 打开php.ini,将 e ...

  3. The Go Programming Language. Notes.

    Contents Tutorial Hello, World Command-Line Arguments Finding Duplicate Lines A Web Server Loose End ...

  4. bzoj 3597: [Scoi2014]方伯伯运椰子 [01分数规划 消圈定理 spfa负环]

    3597: [Scoi2014]方伯伯运椰子 题意: from mhy12345 给你一个满流网络,对于每一条边,压缩容量1 需要费用ai,扩展容量1 需要bi, 当前容量上限ci,每单位通过该边花费 ...

  5. Android开发常用的插件及工具

    1.GitHub,这个不管是做安卓还是其他,只要是开发就必上的网站,也是天朝没有墙掉为数不多的网站 2.Stack OverFlow,这个和上面一样,国外非常著名的问答网站,在上面基本上很多问题都可以 ...

  6. Linux 常用命令 (common commands for linux)

    Linux 常用命令 (Common Commands For Linux) 1.声明,此文章仅写基于 Bash shell 常用的命令,如果遇上命令在使用过程中提示没有,可能随着更新,命令也被替换掉 ...

  7. ConcurrenHashMap源码分析(二)

    本篇博客的目录: 一:put方法源码 二:get方法源码 三:rehash的过程 四:总结 一:put方法的源码 首先,我们来看一下segment内部类中put方法的源码,这个方法它是segment片 ...

  8. PHP输出打印方法

    PHP这门语言灵活而充满众多的API和用法,然而在这个技术领域里却缺乏一些系统的总结归纳.或许这与PHP语言的诞生方式有关,衍生,快速变化,原始限制等等,诸多因素决定这门语言变得smarty,却没有人 ...

  9. mac 查看某个文件夹下所有隐藏文件(夹)的大小

    du -d 1 -h 对应Linux的命令是: du -ah --max-depth=1

  10. spark RDD,DataFrame,DataSet 介绍

    弹性分布式数据集(Resilient Distributed Dataset,RDD) RDD是Spark一开始就提供的主要API,从根本上来说,一个RDD就是你的数据的一个不可变的分布式元素集合,在 ...