Monthly Archives: February 2010

基于MINA构建简单高性能的NIO应用-优化指南

本文为Sparkle发于《程序员》2008年2月刊的文章,与《程序员》的协议,可以在个人博客中发布,转载请保留出处。 优化指南 MINA默认配置的性能并不是很高的,部分原因是MINA目前还保留初期版本的架构,另外一个原因是因为JVM的发展。 首先我们关闭默认的ThreadModel设置 IoAcceptor acceptor = …; IoServiceConfig acceptorConfig = acceptor.getDefaultConfig(); acceptorConfig.setThreadModel(ThreadModel.MANUAL); ThreadModel是一个很简单的线程实现,用于IoService。但是它实在太弱,以至于在并发环境产生大量问题。在MINA 2.0中,ThreadModel直接被取消。你应该使用ExecutorFilter来实现线程。 然后我们增加I/O处理线程(Article by Sparkle) 每一个Acceptor/Connector都使用一个线程来处理连接,然后把连接发送给I/O processor进行读写操作,我们只可以修改I/O processor使用的线程数,用以下代码设置 IoAcceptor acceptor = new SocketAcceptor(Runtime.getRuntime().availableProcessors() + 1, Executors.newCachedThreadPool()); 当然是要将ExecutorFilter加入,上文已经很详细地描述了 acceptor.getDefaultConfig().getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()); 笔者在开发过程中,多次遇到OutOfMemoryError,经过研究之后才发现原因。MINA默认是使用direct memory实现ByteBuffer池的方案(以下简称direct buffer),通过JNI在内存开辟一段空间来使用,该方案在早期的MINA版本中是一个非常好的特性,那是因为MINA开发初期,JVM并没有现在的强大,带有池效果的direct buffer性能比较好。但是当我们使用-Xms -Xmx等指令增加JVM可使用的内存,那仅仅增加了堆的内存空间,而direct memory的空间并没有增加,导致MINA实际使用的时候经常出现OutOfMemoryError。如果你的确想使用direct memory,可以通过-XX:MaxDirectMemorySize选项来设置。不过笔者不建议这样做,因为最新的测试表明,在现代的JVM里面,direct … Continue reading

Posted in Java | Tagged , | 1 Comment

基于MINA构建简单高性能的NIO应用-MINA架构

本文为Sparkle发于《程序员》2008年2月刊的文章,与《程序员》的协议,可以在个人博客中发布,转载请保留出处。 MINA架构 这里,我借用了一张Trustin Lee在Asia 2006的ppt里面的图片来介绍MINA的架构。 (图略) Remote Peer就是客户端,而下方的框是MINA的主要结构,各个框之间的箭头代表数据流向。 大家可以对比刚刚的例子来看这个架构图,IoService就是整个MINA的入口,负责底层的IO操作,客户端发过来的消息就是由它处理。刚刚我们使用的IoAcceptor就是一个IoService,之所以抽象成IoService,是因为MINA用同样的架构来处理服务器和客户端编程,IoService的另一个子类就是IoConnector,用于客户端。不过根据笔者的使用经验,使用非阻塞的模型进行客户端编程非常的不方便,你最好寻求其他的阻塞通讯框架。 IoService把数据转化成一个一个的事件,传递给IoFilterChain。你可以加入一连串的IoFilter,进行各种功能。笔者的建议是将一些功能性的,业务不相关的代码,用IoFilter来实现,使得整个应用结构更清晰,也方便代码重用。(Article by Sparkle) 被IoFilter处理过的事件,发送给 IoHandler,然后我们在这里实现具体的业务逻辑。这个部分很简单,如果你有Swing的使用经验的话,你会发现它跟Swing的事件非常相像,你要做的事情,仅仅是重载你需要的方法,然后编写具体的业务功能。在这其中,最重要的一个方法就是messageReceived了。 值得留意的是一个IoSession的类,每一个IoSession实例代表这一个连接,我们需要对连接进行的任何操作都通过这个类来实现。 从IoHandler通过调用IoSession.write等方法向客户端发送的消息,会通过跟输入数据相反的次序依次传递,直至由IoService负责把数据发送给客户端。 这就已经是MINA的全部,是不是很简单。 接下来,我会详细介绍我们编写具体代码的时候主要涉及到的三个类,IoHandler、IoSession和IoFilter。 IoHandler public interface IoHandler { void sessionCreated(IoSession session) throws Exception; void sessionOpened(IoSession session) throws Exception; void sessionClosed(IoSession session) throws Exception; void sessionIdle(IoSession … Continue reading

Posted in Java | Tagged , | 4 Comments

基于MINA构建简单高性能的NIO应用-一个简单的例子

本文为Sparkle发于《程序员》2008年2月刊的文章,与《程序员》的协议,可以在个人博客中发布,转载请保留出处。 一个简单的例子 MINA使用非常简单,笔者以前做过一段时间传统的Java Socket开发,不过一直对Java NIO不是很理解,但是MINA很快就上手了,MINA封装了NIO繁琐的部分,使你可以更专注于业务功能实现。话不多说,让我们来看一个简单的例子,一个很常见的例子,时间服务器。(Article by Sparkle) 我们的实现目标是一个能响应多个客户端的请求,然后返回服务器当前的系统时间的功能。传统的Java Socket程序,我们需要每accept一个客户端连接,就创建一个新的线程来响应,这会令到系统整体负载能力有较大的限制,而且我们必须手工编写连接管理等代码。让我们来看看MINA是怎么处理的。 首先我们从官方网站下载MINA 1.1,这里我们假设JDK为1.5以上的版本,如果你使用的是JDK 1.4,请下载MINA 1.0,MINA 1.0跟1.1几乎一样,但是强烈建议使用JDK 1.5以上以获得更好的性能。 解开压缩包之后,能看见很多jar包,这里暂不介绍每个包的具体作用,可以把所有包都导入项目。值得留意的是MINA使用了一个slf4j的日志库,该日志库大有取缔common-logging之势。 public class TimeServer { public static void main(String[] args) throws IOException { IoAcceptor acceptor = new SocketAcceptor();   SocketAcceptorConfig cfg = new SocketAcceptorConfig(); cfg.getFilterChain().addLast( … Continue reading

Posted in Java | Tagged , | 1 Comment

基于MINA构建简单高性能的NIO应用-前言

本文为Sparkle发于《程序员》2008年2月刊的文章,与《程序员》的协议,可以在个人博客中发布,转载请保留出处。 前言 MINA是Trustin Lee最新制作的Java通讯框架。通讯框架的主要作用是封装底层IO操作,提供高级的操作API。比较出名的通讯框架有C++的ACE、Python的Twisted,而Java的通讯框架还有QuickServer、Netty2、Cindy、Grizzly等。 2004年6月,Trustin Lee发布了一个通讯框架Netty2,是Java界第一个事件模型架构的通讯框架,Cindy也从中借鉴了不少思想。由于Netty2的架构不是很好,Trustin Lee在2004年底加入Apache Directory组之后,重写了整个框架,取名为MINA。MINA是一个基于Java NIO的通讯框架,Java从1.4开始引入NIO,提供了一个非阻塞、高性能的IO底层。 目前使用MINA的产品并不是很多,比较出名的就有Apache Directory(作者就在为这个项目效力)、Openfire(Jive出品的一个XMPP产品)、red5(研究flash流媒体flv技术的朋友应该很清楚这个东西,adobe fms的竞争者,国内也有视频网站在使用)等等。 (Article by Sparkle) 笔者在07年初的时候,公司新项目需要用Java实现一个Socket Server,对比了Netty2、Cindy、QuickServer和MINA。当时Netty2已经停止开发,也找不到官方网站和代码,比较了另外三个框架之后,毅然选择了当时文档比较缺乏和使用群较少的MINA,一年以来的使用经验来看,感觉还是很不错的,MINA有着清晰的架构,很方便做自定义的扩充。在1.0发布之后,官方网站充实了很多,增加了不少文档,也听到越来越多的朋友开始使用MINA。后来专门针对JDK 1.5发布了1.1的版本,使用JDK内置的concurrent代替backport-util-concurrent。目前1.0和1.1同时存在,但已经不再增加新功能,仅仅发布bug fix的版本,新功能都在2.0中实现,2.0调整了架构,性能有更大的提升,目前还在开发中。 基本特性 通过Java NIO支持TCP和UDP协议,另外还支持RS232和VM内通讯。由于MINA有清晰的架构,你也能很简单地实现一个底层网络协议。目前不支持阻塞IO,似乎还没有计划支持,当然你可以在其之上实现一个阻塞的模型,不过按照笔者的经验来说,非阻塞IO更适合Server端编程。 一个类似ServletFilter的过滤器模型。这是笔者认为MINA的精髓所在,通过引入过滤器模型,可以将一些非业务的功能独立开来,层次更清晰,很有AOP的思想,可以很方便地进行日志、协议转换、压缩等等功能,还能在运行中动态增加或去掉功能。(Article by Sparkle) 可以直接使用底层的ByteBuffer,也可以使用用户定义的消息Object和编码方式。 高度可定制的线程模型,单线程、一个线程池,或者类似SEDA的多个线程池。 SSL支持,攻击防御和流量控制,mock测试友好,JMX支持,Spring集成,你还需要更多吗。 文章快速索引 前言 一个简单的例子 MINA架构 优化指南

Posted in Java | Tagged , | 1 Comment