请教:tomcat并发性问题.

手上一套系统是用简单的jsp+servlet+javabean+oracle的系统,
环境是apache2.0+tomcat4.1+oracle8i
用户量是比较多的需要支持在500左右,
由于查询的数据量比较大,
一般是在几亿条中通过一定条件,聚组,排序生成几百条数据(sql语句速度
比较慢,sqlplus测试,优化也做了很多)
当用户并发请求多的时候,系统的链接池(用改造后的jive链接池)就被占光,系统就处于僵死状态.
做过很多改进但效果也不是很理想.
不知道大家有什么好的建议,十分感谢,由于做这方面的开发不久,还请大家
多多指教.

你这个问题和我在回“为什么要用EJB”的情况类似了。

为什么有的系统直接使用Tomcat的连接池就可以了呢?因为这个系统2/3操作都是数据库操作,没有在内存中的运算,而数据库连接池基本缓解提升系统方面的性能。

如果这样的系统日益复杂,要么自己做缓存,要么使用EJB了。

你这个案例就是明显需要优化逻辑运算的JavaBeans,不要把系统压力都通过数据库访问来解决,这样的系统和以前数据库系统没有什么区别了。

谢谢,现在改造架构可能已经来不及,代价也比较大.
还有个问题,系统僵死一段时间后,链接会慢慢释放,系统还能恢复运行.
也初步想了个方法,就是提供两套数据链接池(一部分提供给小型快速的操作,一部分提供给大数据查询),但效果也不是很明显.
不知道tomcat在一台服务器上可不可做动态均衡.

>系统僵死一段时间后,链接会慢慢释放,系统还能恢复运行
垃圾回收在运行。

tomcat有平衡的,但效果不明显,有很多问题。

考虑一下查询业务的响应时间,分三部份看
java代码 + 与DB建立连接的时间 + SQL查询时间
忙到系统僵死,那么单个的响应至少秒级以上。java代码的时间可以不计,采用了连接池,与DB建连接的时间也可不计,出问题就只可能在SQL查询上。

从你的这句话看:"一般是在几亿条中通过一定条件,聚组,排序生成几百条数据"

你这里说的“一定条件,聚组,排序”是指一条SQL中完成的情况吧,如果不是一条你就变成一条。
这里的问题不在连接池,不在缓存,所以你提的“两套数据链接池(一部分提供给小型快速的操作,一部分提供给大数据查询)”也会不明显。
另外我可以明确告诉你一点,这里cmp对你没帮助,几亿中抽出的结果是没任何缓存意义的。

我相信你的tomcat服务器的cpu的使用率也不高,相反,你的DB服务器的CPU在忙不过来,你去查一下看看。

解决DB上的问题,用下面的一些方法:
1. 由一个表变成多个表,比方变成A200401,A200402。。。,然后在查之前,在java函数中依条件判断一下要调哪几个表,再查DB
2. SQL语句的优化,比方where子句,过滤最多的条件放在最前。
3. DB做机群,小型快速的操作涉及的表 大数据查询涉及的表放不同的表空间和不同机器上。做oracle机群网上资料多的是

谢谢楼上的指教.
数据库方面的优化,也做了不少
可惜的目标集也就是原始数据很大,即使分表存放单个表也是比较大,
而且联合的效率比放在一起还要差.
瓶颈也正如你所说是在执行sql上,但是web这东西很讨厌
用户看不到结果还喜欢拼命点,虽然请求也锁定,但是并发的时候也有此问题.当时唯一能再改善的策略就是做内存数据库.

同时我们也检测到即使tomcat僵死的时候,oracle还是在正常运行,只是有一些进程是bufferbuzy的.
唉想不到好办法了.

系统几乎没有什么大的业务逻辑,感觉用不上ejb,缓存机制也没什么用.

假如你可以在前端^分大Y料存取 和 小Y料存取
我建h可以裼 Datasource
每建立自己的 connection pooling
小Y料建立比^多 自然不榇筚Y料的 connection 被
而е麓蠹叶o法使用

在我_l系y的^念中
哆@N大量Y料碓
通常是另外一台 database 砉芸
@幼 db loading 档
也可以提N效能

如果你ο到y架o法袢∽更的手段 不具溆 application server
不裼 hibernate 砣〈愕 jdbc access
或是自己撰相P的 cache C制
不^前提是 RAM 要虼 否t也是R上消耗殆M

500 user concurrnets 算是很少了
Y料再怎N大 都不是太大的}
而是你如何去{配控制每次出的n案大小
裼梅猪 或是一些技巧肀苊

至於 tomcat 僵死
我猜是因 request ^多
不^你可以加大 tomcat 的 jvm 的绦 memory
假O server 是 2Gb 的 ram
你可以更改 java -Xmx 2048 -Xms 1024 ....

我认为,不从系统设计等方面切入修改,单靠提高硬件或周边性能,效果不大,也不是根本之道。

因为J2EE的集群目前都是针对EJB服务器的,而你的业务核心和数据库访问都是在Web层,所以,通用的J2EE集群对你无能为力,也就是说,无法通过简单地增加服务器就能提供性能。

Jive这方面做了探索,在其3.1等版本中,使用了大概叫tango的商业分布式缓存系统,所谓分布式缓存系统,就是可以在多台机器上实现缓存,使用这个缓存系统好处:可以增加多台服务器;也提高单台机器性能。

因为无法知道你这个系统的设计,不能给出具体之道,但是<b>引入Cache缓存机制是根本之道,单纯依赖数据库层提升不是永久之道</b>,将那些反复读取的数据放在内存中,Web层其实是一个大的线程池,你还需要为每个线程分配一个缓存对象。


这点我想请教一下banq兄..
什么时候用ejb的cache会有明显的效益?
应该是stateful session bean或是entity bean吧?
若是他的state的需求不是很高
或有甚者.. 根本把logic摆在ejb中也只是一个stateless session bean
那cache所提高的效能应该有限的吧?
不知道我的想法是不是正确的 ^_^?

现在我不清楚楼主的应用程式的类型是什么
但是与其想尽办法做查询资料的效率调校
还不如想说有什么方法可以避开资料的查询...
如果有些查询的资料是变动性不大
但是重复浏览性很多
(如新闻网站)
那可以把这些资料直接转成静态网页
或是大部分相同 少部分不同的话
(如portal)
可以转成velocity的template
并不是所有资料都要向资料库去要资料的
可以用一些小技巧大大的改进效能

而ejb的cache是以物件为对象的
但是还有另一种cache是以document为对象的
我刚刚提到的都是
希望可以给你另一个方向

我感觉像这种大规模查询的瓶颈就在数据库,cache解决不了什么问题,而且hit率也不会很高

还是通过优化数据库,将查询的数据放到一个独立数据库中,oracle不是有一种建库类型叫“数据仓库”吗?不知道这个会不会专门针对查询进行优化?
创建表分区,合适的地方建立索引。还有starfeng 提到的建立数据库集群(这个我也不懂)

想起还有一个:oracle查询很占临时分区,看看临时分区是不是太小了?

首先,系统架构都变的话,动的就不是小手术了。人力成本不可能接受
再者,改了架构是不是就能有改进,未知数。

ejb是有用,但有用他的地方,要是什么地方都他最大,我们做设计就不用这么麻烦,sun公司也不必又弄ejb3.0又弄jsp2.0。
cache是有用,但cache还有个命中率的问题。没有cache,那么cache的命中率当然是0,如果加上cache,但cache的命中率只有1%,那还不如不用。因为,cache的同步涉及的问题就不是一点点,处理起来也是要时间,当然,更要内存。

再回到你的问题:
操作:几亿条中,经一些条件,选出几百条。
问题:访问一多,web服务器的链接池占光,系统僵死
对吧,是这个问题

这里有一点点,我还有点不清楚,“僵死”,具体指的是什么
对于其它的不带DB查询的jsp也“僵死”了?还是说,只是那些带查询的死了。我想你说的应该是后者吧。
补充问一下,你的Web服务器和DB服务器是分开的吧,如果在一台机器上,想想应是不会有人这么做,我有些太多心。

好,怎么处理呢
首先,不太可能的方法:
EJB不太可能,原因很简单,cache命中率,
有人也许会说,银行呢,那用户还不多啊,ejb运用常见例子啊,不过,要注意一点是,那里主要体现了事务,另外一点是数据持久。当然最后一点,也有与cache相关的:用户进行一系列业务操作,他要重得用到那几个数据实体,虽然第一次业务操作的cache命中率几乎为0,但随后的几次就100%了!当然提速。
但,上面的一切说话,在你这里不通用。你这里就是一个查询,就是因为这个查询,在很多用户同事来访问时,服务器“僵死”

那么,要怎么做呢,我觉得你可以从以下方面着手:
一是对于用户重复点击的处理。
二是tomcat连接池的配置。

关于一:
你只要在那几个会涉及大量数据查询的jsp引入一些判断,比方,同一个人在5秒之内不许连续查。在session中加个变量记录下时间就可以了,查询前做一下判断,就可以做到防止重复点击,实现很简单是吧:)
关于二:
要用两套连接池,一个给大量数据查询的用,这个连接池你就要限制严格些,比方,将最大连接数就设为5,最多5个人同时查。
与此同时,你的那几个涉及大量数据查询的jsp页面也要改动一点点代码。另外还要注意的就是,改动的代码中要注意到这样一个问题:如果你的jsp在取连接池没有取到连接时,jsp要立即结束运行,注意是立即,不要因为在等着连接池给你连接而挂在那里,千万要注意!!!不然,WEB服务器也会因为挂的线程变多而“僵死”。
另一个供数据量少查询用,连接池就可设多些,可以设50或100,就看你oracle的能力了。

这样做以后,可能依然会有一个问题:大量数据查询的jsp,会经常出现查不到,这时,如果用户还不能接受,那么你要将这几亿数据的表单独放一DB服务器,甚至做集群了。
但从你们的业务看应该不会到做集群的地步。我觉得你们的DB,还是做得不够优化。
为什么呢,因为,像计费系统,里面的表数据相对一般业务可以算是很大了。几亿数据的查询都不会到做集群的地步。
我建议,在oracle配置方面、SQL的优化、表索引这些方面,你们还是要再考虑一下。

我上帖曾提过一下表的拆分,效果应该是比较明显的,只是拆分要注意是根椐查询条件的设定做表的拆分,拆得不好等于没拆,但我不知你们的实际查询业务是怎么个样子,在表拆分后相应的逻辑语句,查询语句是怎么个改法。所以不好下结论。

集群的原理:最完美的是基于分布式计处技术的方法实现,最简单的,多机并联,数据同步。

存在锁,数据的查询隔离级别查询时应该降低

项目到了这个阶段,想大改框架估计人力、时间都不允许,个人认为几位提的有些道理,将大查询和小查询分开,划分优先级,在分配连接时大的查询多等等没关系,小范围的查询相应的时间不能太慢,不能有系统级别的无法响应,对于cache而言,要看具体情况而定。对于几亿条记录的查询,光靠数据库的优化确实有些难为他了,虽然会起挺大的作用。

另外,在oracle 9i中,数据分区对性能会有比较大的提高,