emarket
亢龙有诲
CJSDN高级会员
发贴: 460
积分: 82
|
于 2003-03-09 17:50
从一个失败的project中来的教训, 1. 不要在 jsp or servlet中轻易开线程(尤其在流量大的情况下)。 2. 在流量大的情况下,不要使用runtime.exec()开进程。
(笔者原文发表在ustc bbs上) 这两天,我一直被别人写的一个程序困扰,(这是一个设计缺陷,不是一个软件bug, 所以我们失败了) 先说说我遇到的情况吧: 一个servelt 创建一个objectA, 然后调用objectA.method()去做些事 这个objectA.method()会开N个(N由用户指定)线程,这N个每个线程会开 一个进程(Runtime.Exec())调用一段perl的程序,然后从inputstream中读出 结果分析,然后显示在jsp页面上。
这是一个典型的anti-pattern得设计,为此 我们可能已经失去了客户,公司的管理层正在和他们谈判:)。
先说说我们的问题吧,由于一个用户可以fire N个线程,所以一个用户的一个 request就变成的N个等效的request。 所以从log文件中得到的用户数量并不大, 但实际上是要乘以N的。而且n可以由用户指定(有个最大值N),于是,在用户数量并不大的情况下,系统 资源就会被耗尽而且出现的很多所谓的僵尸进程(因为process通信的问题)。
下面是我做的分析 1. servlet或jsp中搞多线程 虽然多线程模型可以提高效率,但也要具体情况具体分析,如果你只有一个cpu 而你开了很多线程去读文件(或类似的serialation操作)对你性能不会有什么显著的 提高。而且在servlet和jsp中开多线程一定要注意,不要万不得已,千万别这么做, 因为你要保证24*7的性能,就必须是container可控,像这样在servlet中开线程是不可控 的。而且也要考虑到多线程是否对你有所帮助,例如我有一个cpu,10个文件,我开了10个 线程去读那10个文件,和一个线程读10次,性能应该是差不多的。
教训:不要在servelet或者,jsp中玩多线程。因为他们本身已经是多线成的了,而且很难 控制。例如你有一个jsp要显示10个文件的内容,你开了10个线程去读。不如写一个jsp读 一个文件,然后再另一个jsp中<jsp:include>那个文件10次。多线程不是在所有地方都有 效率的。另外可以考虑一下EJB的模型,毕竟他是container可控的对象。
2. 在server端开process去执行另外一个程序例如perl. 有人认为Runtime.exec()和Process是java的一个缺陷[1] 虽然[1]可以在一定程度上解决我们的问题,但是在大流量 的server端,没法保证inputstream不over flow, 也没法保证在子process退出 之前,server就一定可以把数据读完(流量很大的情况),不要相信java 的waitfor或者是destroy。于是就会出现所谓 的僵尸进程,或者死掉的java线程。
教训:在server端尽量不要搞java和其他语言通信的东西 如果非通不可,应该考虑是否可以用corba或者JCA(manageable)来稿, 在server端应该尽量避免使用runtime.exec()去开进程(尤其在大流量的时候) 如果实在要使用,可以考虑里提到的jconfig[2], 毕竟java 的process对象太弱了。如果是牛人可以考虑实现自己的native process和java 通信。
这是一个失败的教训,或许对大家有用,以后别这样设计.尤其是legacy system. j2ee提供了很好的模型,例如EJB, JCA。 不要自己咕哝一套模型。 欢迎讨论你的教训:)
参考文献: 1。(http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html) 2。(http://www.tolstoy.com/samizdat/jconfig.html)
|