tapestry1122 写道
baitian 写道
ZHH2009 写道
cutesource 写道
ZHH2009 写道
用NIO写网络框架没啥搞头了,要练练手可以,拿到正式产品中使用是要很多时间磨炼的,
还不如用现有成熟的网络框架,如Netty、grizzly,
至于Tomcat和Jetty中的网络层相对于Netty、grizzly这种,就好比是业余和专家级的区别,Mina现在也是干不过Netty的了,虽然早期都是出自Trustin Lee之手。
所以,我是建议你多花点时间认真仔细研究Netty的每行源代码反而得到的收获会更多。
Netty确实不太熟悉,但从mina的roadmap(http://mina.apache.org/road-map.html)发现,mina的作者就是开发Netty2的,后来弃Netty而转向推出Mina,所以我误以为Mina是Netty的升级版本,既然兄台严重推荐,我得好好学习一下
Trustin Lee这家伙确实很神经,先是开发Netty2,然后它把代码转到了Apache,并改名为Mina,
之后去了Jboss,又不管Mina了,又开始搞Netty3,包名也换成了org.jboss.netty,并且内部架构变动也很大。
现在最新版本是3.2系列,代码又从jboss迁移到github托管了。
不管他多折腾,总之Netty3.2的代码写的还是很漂亮的,性能比Mina和Tomcat和Jetty都好。
这位兄弟可否具体讲一讲为什么Netty3.2的代码性能比Mina和Tomcat和Jetty都好?
javaeye会员xmemcached作者dennis-zane曾经写文章分析过的
哈哈,baitian 的问题问得真是。。。
要是你在公开场合问Trustin Lee,估计他会笑而不语,
嘿嘿,因为这是人家最“珍贵”的东西吗。
当然,我不是他,但是这问题确实很难回答,最直接的办法就是看性能测试报告,
Netty的网站上提供了几个报告了,有Trustin Lee自己的测试,还有其他人的测试,
特别是Plurk的案例,这个案例就是关注Netty能支撑多少并发链接数的(而且是长链接),
楼主的需求其实跟Plurk有点类似,请看这里: http://www.jboss.org/netty/performance.html
如果想知道源代码实现细节的差异,这个更难,比如你想知道Netty比Mina性能好的原因是什么,
你不光要知道Mina的所有实现细节,也同样要知道所有Netty的实现细节,
因为性能好坏是一个框架的整体表现形为,不局限于某个类、某个方法。
不过,为了削除某些人又怀疑我来JavaEye扯大炮了,我最好还是花1小时来码一下字,
我不了解Mina的所有实现细节,所以我只说我认为Netty做得好的地方(这些地方或许就是拉开性能差距的地方)。
NIO框架其实内部的核心实现都差不多, 比如在Server端通常开有Acceptor和Poller线程,
Acceptor负责接收请求,得到一个Socket后把它包装一下,比如放到一个Task中,然后再把Task加到一个Queue,
Poller说白了就是在不停的执行一个循环,在这个循环中处理各种Task,Task除了Acceptor新注册的任务外,当然还有读和写。
NIO框架性能表现得好与坏,更多的是作者在一些细节方面的处理,
比如在读写字节时尽量减少来回copy,这方面一些成熟的框架都做得很好了,
比如Tomcat、Jetty、Netty在从Socket中读取字节时一般都自已实现了一套Buffer类来对字节数组进行操作,
而不是直接使用java.nio中的Buffer类,
如果想从Buffer中抽取一个片段(比如在http协议解析中,一个请求行有method,uri,http-version),
只要把offset和片段length记下来就行了。
另一个就是并发问题了,尽量减少不必要的同步,
比如像上面的Queue就是一个很关键的地方,这个地方一般会有三种线程在对它操作,
1. Acceptor把接收到的Socket包装成Task加到Queue(执行Queue.offer)
2. 应用线程要写数据,所以WriteTask也会加到Queue(执行Queue.offer)
3. Poller从Queue中取出Task来执行(执行Queue.poll)
所以这个Queue的实现就很重要了,
Netty的聪明之处在于,它没有使用java.util.concurrent中的Queue实现(比如ArrayBlockingQueue或ConcurrentLinkedQueue),
而是使用Doug Lea大神在jdk1.7中才加入的jsr166y.LinkedTransferQueue,
在Netty中变成了org.jboss.netty.util.internal.LinkedTransferQueue,这两个类有一点点差异,
我无法确认是Trustin Lee自己修改的,还是用了不同版本。
jsr166y.LinkedTransferQueue威力不容忽视,Tomcat、Jetty、Mina都没使用,
如果你刚好又用过BoneCP(一个JDBC数据库链接池框架),它也用了jsr166y.LinkedTransferQueue来对链接进行offer和poll操作,
BoneCP的测试报告出来了(http://jolbox.com/),比DBCP、C3P0快20多倍。
除此之外,Netty的Poller实际上就是org.jboss.netty.channel.socket.nio.NioWorker,
默认情况下,NioWorker的个数是CPU个数的两倍,
并且Netty在NioWorker中建立了两个LinkedTransferQueue,
一个是registerTaskQueue,另一个是writeTaskQueue,
registerTaskQueue给Acceptor、Poller线程用,writeTaskQueue给应用线程和Poller线程用,
这一划分一定程度上减少了并发粒度,起码不用三种线程都挤到一个Queue上。
另一方面,writeTaskQueue是同时给多个应用线程使用的,
应用线程想往Channel中写数据时,这个Channel内部又有一个LinkedTransferQueue( 叫writeBuffer) 用来存放数据,
然后再把这个LinkedTransferQueue间接包装成一个writeTask放入writeTaskQueue,
而不是像传统做法那样每次写数据都直接放到writeTaskQueue,
因为Poller线程在写 应用线程A 放入的数据时,如果所有应用线程共用一个LinkedTransferQueue,
应用线程B必需跟 Poller线程 和 应用线程A 竞争同一个LinkedTransferQueue,
与其这样,还不如为应用线程B单独开一个LinkedTransferQueue,当Poller线程还没处理到应用B的数据时,
应用线程B自己去折腾自己的LinkedTransferQueue好了,
等Poller线程处理完应用A的数据后,再处理应用B的数据。
这种做法也是为了减少并发粒度,因为应用A和应用B的数据没有关联,所以没必要全放入一个Queue,
这样应用线程A和应用线程B在写数据时不会存在竞争。
具体实现更漂亮,有兴趣请看NioWorker和NioSocketChannel的源代码,
网上有另一种说法(至于谁说,我不点名了,大家都懂的)
写道
MINA使用系列I/O线程处理读和写,这是很多典型NIO框架的手法。但是Netty要比MINA聪明得多,当发送Queue中是空的,Netty将直接发送数据,不再例行公事放入Queue中,如果发送Queue不是空的,Netty将这个数据放入队列,这时类似MINA做法。所以,Netty要快些
我对种说法的评价是: 说了等于没说,兄弟还需努力。
最后,再说一下Netty的一个缺点,
大家看到这,发现我都没有提到读数据的情况,Netty读数据也是用Poller线程在读,
不管Acceptor放入多少个Socket,全是Poller线程在一个个地读,
把读到的数据放到Buffer后会触发MessageEvent事件(Netty是一个纯正的事件驱动框架,这是Tomcat、Jetty这类业余选手望尘莫及的),
此时会调用ChannelUpstreamHandler这类处理器的messageReceived方法,
messageReceived方法中的代码通常是业务相关的,但是执行messageReceived方法的线程却是Poller线程,
所以只要在messageReceived这种地方出现问题,比如有个Thead.sleep调用或者出现无限循环,
那么此时Netty跟死了没分别,Poller线程无法往下走了,所有Task都没法处理了。
相关推荐
Utah Java User Group(犹他州Java用户组)可能在其中讨论了NIO的基本概念,如选择器(Selectors)、通道(Channels)和缓冲区(Buffers),这些都是NIO的关键组件。选择器允许单线程处理多个通道,极大地提高了并发性能;...
根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...
标题 "IBM的NIO教程" 暗示了...虽然提供的CHM文件可能包含了更详细的IBM特性和案例,但没有实际访问权限,我们只能依赖公开的通用知识来讨论NIO。如果能获取到这个文件,将有助于深入理解IBM NIO的具体实现和优化策略。
下面我们将详细讨论这些组件以及如何在实际编程中使用它们。 1. **通道(Channel)**:Java NIO提供了一些通道实现,如FileChannel、SocketChannel和ServerSocketChannel等。FileChannel用于文件操作,...
7. 高并发场景下的应用:讨论NIO在处理大量并发连接时的策略,如线程池的使用和连接管理。 8. 实战案例:提供实际的NIO和Socket编程示例,帮助读者将理论知识应用于实践。 通过阅读《NIO与Socket编程技术指南》,...
标签中的"源码"可能意味着博客中会深入到NIO的内部实现,讨论相关类和方法的工作原理,这对于理解NIO机制及其性能优化至关重要。而"工具"可能是指博主介绍了一些辅助开发NIO应用的库或框架,例如Netty,它是一个基于...
Java NIO(New Input/Output)是Java提供的一种新的输入输出处理机制,...对于完整的NIO知识体系,开发者还需要参考Java官方文档中的其他部分,以及可能的第三方教材和专业社区讨论,以便能够深入理解和掌握Java NIO。
2. **NIO的优势**:对比传统I/O,讨论NIO如何提高并发性能,特别是在处理大量连接的服务器场景下。 3. **服务器模型**:介绍基于NIO的服务器实现,例如“非阻塞服务器”,其中服务器线程不会因为等待客户端的响应而...
书的目录包括引言、组织结构、目标读者、软件和版本、本书中的约定、如何联系我们、致谢,以及后续章节对各个主题的详细讨论,如NIO的介绍、基本概念、缓冲区、通道、选择器、字符集处理、文件操作和正则表达式的...
在标题中提到的“java-nio.rar_java nio_nio 对象实例化”,我们可以理解为这个压缩包中包含了关于Java NIO对象实例化的具体示例或教程。下面我们将详细讨论NIO中的核心对象及其实例化方法。 1. **通道(Channel)*...
本文主要简单介绍NIO的基本原理,在下一篇文章中,将结合Reactor模式和著名线程大师Doug Lea的一篇文章深入讨论。 NIO主要原理和适用。 NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的...
标题“ffc.zip_FileCopy_NIO_java nio”表明我们将讨论如何使用Java NIO进行快速的文件复制,特别是针对文本文件的情况。 在Java的传统IO模型中,我们通常使用`InputStream`和`OutputStream`进行数据读写,这种方式...
首先,我们来讨论基于Java IO的文件分割器。Java IO API是Java早期就引入的I/O处理机制,主要用于读写文件、处理流等操作。在这个版本中,文件分割器可能使用了`BufferedReader`或`DataInputStream`来读取源文件,...
接下来,我们讨论NIO(Non-blocking Input/Output),它是Java 1.4引入的一种新的I/O模型,与传统的阻塞I/O(BIO)相比,NIO具有更高的并发性能。在BIO中,每个连接都需要一个线程来处理,当连接数量增多时,线程...
Java.nio,全称为Java Non-blocking Input/...而压缩包中的"thread"、"noblock"、"block"可能分别对应于线程管理、非阻塞I/O和阻塞I/O的相关示例或讨论,进一步深入研究这些内容,有助于深化对Java.nio的理解和应用。
此外,可能会讨论到套接字选项,如设置超时、接收和发送缓冲区大小等,这些都对网络性能有显著影响。 总之,Java NIO流和通道的使用能显著提升Java应用的I/O性能,尤其在处理高并发和大数据量的场景下。通过本教程...
服务端程序基于javaNIO,客户端程序基于旧IO,读完<<javaNIO>>后,导入eclipse即可运行,支持多人在线聊天,上下线通知.PS:非GUI程序,毕竟javaSwing用的少,不懂的地方大家可以一起讨论,评论必回!