??xml version="1.0" encoding="utf-8" standalone="yes"?>
java.net http://www.java.net
Lomboz http://www.objectlearn.com/index.jsp (J2EE plugin for Eclipse)
htmlArea http://sourceforge.net/projects/itools-htmlarea/ (所见即所得的在线HTML~辑?
XmlBuddy http://www.xmlbuddy.com/ (XML Editor plugin for Eclipse)
JFreeChart http://www.jfree.org/ (用于生成图表的项?
EclipseME http://eclipseme.sourceforge.net/ (J2ME Developmnt Plugin for Eclipse)
mvnForum http://sourceforge.net/projects/mvnforum/ (论坛)
jChatBox http://www.javazoom.net/index.shtml (用servlet实现的WEB聊天引擎)
POI http://jakarta.apache.org/poi/index.html (用于处理Excel,WORD{文的目)
FileUpload http://jakarta.apache.org/commons/fileupload/ (用于处理HTTP文g上传得项?
PDFBox http://sourceforge.net/projects/pdfbox/ (处理PDF文的项?
Lucene http://jakarta.apache.org/lucene/index.html (搜烦引擎)
Digester http://jakarta.apache.org/commons/digester/ (处理XML信息的项?
DBCP http://jakarta.apache.org/commons/dbcp/ (数据库连接池)
AXIS http://ws.apache.org/axis/ (WebService 的实现框?
Jetspeed http://portals.apache.org/jetspeed-1/ (Portal)
HSQLDB http://sourceforge.net/projects/hsqldb/ (Im memory Database Engine)
CEWOLF http://sourceforge.net/projects/cewolf/ (一套标{ֺ实现Web报表,使用的是jFreeChart引擎)
Struts Menu http://sourceforge.net/projects/struts-menu/ (ZStruts的Web菜单目)
htmlparser http://sourceforge.net/projects/htmlparser/ (用于解析HTML信息的项?
Mondrian http://sourceforge.net/projects/mondrian/(Open Source OLAP Database)
ProGuard http://sourceforge.net/projects/proguard/(Java的淆器)
InfoGlue http://sourceforge.net/projects/infoglue/ (J2EE 内容理pȝ)
JPivot http://sourceforge.net/projects/jpivot/ (ZWEB的OLAP 展现)
http://java-source.net/
Title: q接池性能试
Description: 试不合理的利用q接对WEB应用所造成影响.
Copyright: Copyright (c) 2005
Company:
Title:
Description:
Copyright: Copyright (c) 2004
Company: cea
如需转蝲Q请?A href="mailto:cyicecream@163.com">W?/A>联系
前提Q项目组里无用到SPRINGq行事务的管理。项目里以功能划分到每个人手里,
形成?/SPAN>BOQ?/SPAN>DAOQ?/SPAN>ACTIONQ?/SPAN>VIEW都是单h负责。在DAO中每个动作都?/SPAN>
闭式的形式存在?/P>
问题Q造成事务的不q诏性。功能是做出来了Q性能问题q早暴露?/SPAN> 试Q主要针对程序频J请求数据库q接?/SPAN>WEB应用所造成影响做一个测试?/SPAN> 先做必要的说明,一步步引入正题Q先从性能瓉开始:
所有的应用E序都存在性能瓉Qؓ了提高应用程序的性能Q就要尽可能的减程序的瓉。以下是?SPAN lang=EN-US>JAVAE序中经常存在的性能瓉?o:p>
了解了这些瓶颈后Q就可以有针Ҏ的减少q些瓉Q从而提?SPAN lang=EN-US>JAVA应用E序的性能
关于q接池的实现原理试ҎQ?/SPAN>
l过资料的收集与APACHE DBCP里连接池的查阅,对现有的q接池工?/SPAN>
原理有两U方式:
1. 数据库预先设|配|好的连接数。待得到用户hq接Q传Z个连接,而后Z保持供应数再提前创徏q接Q即提前预备q接Ch。比如:
?/SPAN>5个通行道代表最大激zȝq接敎ͼ最?/SPAN>2个闲|连接数。也是说连接池里始l预备了2个可随时提供的连接,q接的创建开销是比较大的,q接池的存在是了能够最化的解军_建所{待的时间?/SPAN>
1 O
2 O
3 *
4 *
5 *
如上图,?/SPAN>1分配出去时由于池中连接数剩一个,Z持最闲|,会自动创Z个新的连接以防止再次h{待创徏的时间。这L实减了{待的时_但是数据库创建的开销斚wq未得到解决。如果把1-5比喻成汽车,那么q种情况下每量R都是一ơ性用?/SPAN>1被请求后下一个连接将?/SPAN>6来接ѝ那么如何能够重复利?/SPAN>1减少数据库开销。于是引出第二种方式?/SPAN>
2. 回收使用完后的连接,攑֛到池中进行@环利用。这么做必须能保?/SPAN>2?/SPAN>
一. 使连接能够保持有效的回收?/SPAN>
?/SPAN>. U束使用者用释攄动作Q而不是直接把q接close.
本h使用的是APACHE DBCP?/SPAN>BasicDataSource的连接池基本实现Q?/SPAN>
l过代码与测试结果显C,其工作方式是Z二的?/SPAN>
L试用例
试l果Q?/SPAN>
W?/SPAN>2l数?/SPAN>:
q发应用敎ͼ100 模拟q接敎ͼ6
q行q_耗时Q?/SPAN>2956
׃?/SPAN>51个连?/SPAN>
q行q_耗时Q?/SPAN>3391
2׃?/SPAN>52个连?/SPAN>
q行q_耗时Q?/SPAN>2616
׃?/SPAN>47个连?/SPAN>
q行q_耗时Q?/SPAN>3377
׃?/SPAN>41个连?/SPAN>
q行q_耗时Q?/SPAN>3673
׃?/SPAN>46个连?/SPAN>
W?/SPAN>2l数据共执行5?/SPAN>;q_耗时为:3229毫秒
q_使用47个连?/SPAN>
W?/SPAN>3l数?/SPAN>:
q发应用敎ͼ85 模拟q接敎ͼ9
q行q_耗时Q?/SPAN>4830
׃?/SPAN>53个连?/SPAN>
q行q_耗时Q?/SPAN>3247
׃?/SPAN>49个连?/SPAN>
q行q_耗时Q?/SPAN>4116
׃?/SPAN>40个连?/SPAN>
q行q_耗时Q?/SPAN>4070
׃?/SPAN>43个连?/SPAN>
q行q_耗时Q?/SPAN>4053
׃?/SPAN>54个连?/SPAN>
W?/SPAN>3l数据共执行5?/SPAN>;q_耗时为:4063毫秒
q_使用47个连?/SPAN>
W?/SPAN>4l数?/SPAN>:
q发应用敎ͼ140 模拟q接敎ͼ3
q行q_耗时Q?/SPAN>2076
׃?/SPAN>47个连?/SPAN>
q行q_耗时Q?/SPAN>3104
׃?/SPAN>51个连?/SPAN>
q行q_耗时Q?/SPAN>2048
׃?/SPAN>43个连?/SPAN>
q行q_耗时Q?/SPAN>2421
׃?/SPAN>50个连?/SPAN>
q行q_耗时Q?/SPAN>2751
׃?/SPAN>50个连?/SPAN>
W?/SPAN>4l数据共执行5?/SPAN>;q_耗时为:2480毫秒
q_使用48个连?/SPAN>
每次试的结果都可能不同Q但是所得到的结论是一致的。数据显CZ合理的请求用连接严重的影响应用所能承受的q发数量Q响应的旉也因此受到媄响?/SPAN>
没有把事务控制好Q一般会出现以下的情况:
事务(){
程1();
程2();
}
可以看出程1Q?/SPAN>2里都是单独创接,q在自己的流E里完成操作?/SPAN>
如果在流E?/SPAN>2里出现异常,那么程1所做的操作是不可恢复的?/SPAN>
如果能控制在事务范围内,如:
事务(){
Connection con;
程1(con);
程2(con);
con.close();
}
那么数据库少提供一个连接,事务的完成性也得到体现。在q发数量大的时候,
效率上就有非常明昄区别?BR>
1Q?SPAN style="FONT: 7pt 'Times New Roman'"> 量保持的h
?/SPAN>DAO中有update()ҎQ则应再扩展一个方?/SPAN>update(Connection conn)
在业务逻辑事务里调?/SPAN>update(Connection conn)Q一般情况下调用update()
2Q?SPAN style="FONT: 7pt 'Times New Roman'"> 对于数据不变的情况采用缓存技术,或部分缓存技术?/SPAN>
可参照一些相关的开源的目Q?/SPAN>JIVEQ?/SPAN>
3.功能Q?BR> 提供查询Q更斎ͼ删除Q插入(没实C键自动生成),(分页暂时没实??Q用步骤:
首先在数据库建立一个cat表,字段为cat_id;name;sex;weight;cd1Q?为数字型Q?Q?BR>3为字W串型?/FONT>
其次建立两个配置文gQ由自己定义文g名称Q:
repository.xml配置信息Q?BR><?xml version="1.0" encoding="UTF-8"?>
<Repository>
<TableDesc execid="CAT" identifyField="CAT_ID">
<table>CAT</table>
<condition />
<FieldDesc name="CAT_ID" fieldType="java.lang.String" >
<title>CAT_ID</title>
</FieldDesc>
<FieldDesc name="NAME" fieldType="java.lang.String" >
<title>NAME</title>
</FieldDesc>
<FieldDesc name="SEX" fieldType="java.lang.String" >
<title>SEX</title>
</FieldDesc>
<FieldDesc name="WEIGHT" fieldType="java.lang.Long" >
<title>WEIGHT</title>
</FieldDesc>
</TableDesc>
</Repository>
配置文g的设计说明如下:
TableDesc 表示一个表的声明?BR>Execid 是类名一般情况下最好和表名一_Ҏ扑ֈ对应关系Q,但是不允许有下划U出现。注意这个类名不是全路径?BR>DentifyField 表中的主?如果是复合主键则以逗号盔R开
Table 数据库表?BR><FieldDesc name="SEX" fieldType="java.lang.String" >
<title>SEX</title>
</FieldDesc>
q里是表中字D늚描述Qname是字D名?fieldType 是数据库字段?BR>应java中的cdQ只?中类型可填充Qjava.lang.String,
java.lang.Long, java.util.Date, java.lang.Double
title可要可不?如果存在多个表,那么在</TableDesc>?BR></Repository>之间加入表描q?/FONT>
pool-config.xml配置信息Q?BR><?xml version="1.0" encoding="GB2312"?>
<ResourceParams>
<maxActive>10</maxActive>
<maxIdle>5</maxIdle>
<maxWait>10000</maxWait>
<username>test</username>
<password>test</password>
<driverClassName>oracle.jdbc.driver.OracleDriver</driverClassName>
<url>jdbc:oracle:thin:@192.168.0.90:1521:forecast</url>
<removeAbandoned>true</removeAbandoned>
<removeAbandonedTimeout>60</removeAbandonedTimeout>
<logAbandoned>true</logAbandoned>
</ResourceParams>
把上qC息保存ؓXML文g。对q个文g不多做说明了?/FONT>
定两个文g已经存在Q接下来是要创CAT?BR>q有表所对应的BEAN?BR>下面是我在Hibernate的一个例子中建立的VO。(借用Q?BR>package com.cea.boat.dao;
import java.util.*;
public class Cat implements Cloneable {
//Declare Field
private java.lang.String catId;
private java.lang.String name;
private java.lang.String sex;
private java.lang.Long weight;
//Get Method
public java.lang.String getCatId() {
return catId;
}
public java.lang.String getName() {
return name;
}
public java.lang.String getSex() {
return sex;
}
public java.lang.Long getWeight() {
return weight;
}
//Set Method
public void setCatId(java.lang.String catId) {
this.catId=catId;
}
public void setName(java.lang.String name) {
this.name=name;
}
public void setSex(java.lang.String sex) {
this.sex=sex;
}
public void setWeight(java.lang.Long weight) {
this.weight=weight;
}
public Object clone() {
Object o = null;
try {
o = super.clone();
}
catch (CloneNotSupportedException ex) {
System.out.println(o);
}
return o;
}
public boolean equals(Object obj) {
Cat o = (Cat)obj;
boolean result = true
&& (catId == o.catId || catId.equals(o.catId))
&& (name == o.name || name.equals(o.name))
&& (sex == o.sex || sex.equals(o.sex))
&& (weight == o.weight || weight.equals(o.weight))
;
return result;
}
}
到此已经完成了该做的事了Q下面是一个用的例子?/FONT>
l查询方式Q?BR>例子Q?BR>Void testQuery() throws Exception{
{
System.setProperty(Const.RUN_KEY, Const.POOL_FACTORY_KEY);
System.setProperty(Const.CONFIG_PATH,
"E:/project/CEAConnection/pool-config.xml");
System.setProperty(Const.REPOSITORY_CONFIG_PATH,
"E:/project/CEAConnection/repository.xml");
}
ConnectionManage connectionManage = new ConnectionManage();
connectionManage.activity("com.cea.boat.dao.Cat cat");
Query Query=connectionManage.createQuery(“cat. Catid=???;
while (Query.hasNext()) {
Object[] objects = Query.next();
Cat cat = (Cat) objects[0];
}
connectionManage.close();
}
说明Q?BR>在WEB中用只需要在|站启动时声明一ơ即可?BR>{
//指明使用q接?BR>System.setProperty(Const.RUN_KEY, Const.POOL_FACTORY_KEY);
//q接池参数配|文?BR> System.setProperty(Const.CONFIG_PATH,
"E:/project/CEAConnection/pool-config.xml");
//配置文g指定
System.setProperty(Const.REPOSITORY_CONFIG_PATH,
"E:/project/CEAConnection/repository.xml");
}
声明一个连接管理者,理数据库资源,事务的v始,它的生命周期最好是在一个事务结束就完结Q当然你也可以在q个事务完结时l用q个实例Q来创徏下一个事务的开始。不如此使用?BR> ConnectionManage DataManage = new ConnectionManage();
Ȁz要使用c(在配|中必须有CatQ?cd为全路径如果要用多个对象,则对象间要用逗号盔R开
connectionManage.activity("com.cea.boat.dao.Cat cat");
q里只需要给出SQL查询条g比如SQL中是select * from cat cat where cat.Catid=?’那?select * from cat cat where q里后台已经帮你完成Q你需要做的就是把条g完成Q如果没有条件则为空.
Query Query = connectionManage.createQuery(“cat. Catid=???;
Query.hasNext()的作用相当于resultset.next()查看是否q存在记录,Query.next()q回一个对象数l这里如果activity的是多个对象Q那么objects里会序的存储相应的对象实例Q用的时候强制{化就可以了?BR>while (Query.hasNext()) {
Object[] objects = Query.next();
Cat cat = (Cat) objects[0];
}
使用完毕Q释放用的数据库资?BR> connectionManage.close();
l新增方式Q?BR> ׃没有主键自动生成Q因此主键暂时只能由自己来维护,要保证catid?11的在表里不存在,否则会出现异常?BR>Void testInsert() throws Exception{
Cat cat = new Cat();
cat. setCatId(?11?;
cat. SetSex(“F?;
cat. setName(“catm?;
ConnectionManage cm = new ConnectionManage();
cm.create(cat);
cm.commit();
cm.close();
}
l更新方式Q?BR>表里已经存在catid?11的猫Q否则查不到q条记录更C了信?BR>Void testUpdate() throws Exception{
Cat cat = new Cat();
cat. setCatId(?11?;
cat. SetSex(“F?;
cat. setName(“catmm?;
ConnectionManage cm = new ConnectionManage();
cm.update(cat);
cm.commit();
cm.close();
}
l删除方式Q?BR>删除方式比较单,只要l出对象Qƈ且主键g为空Q就可以删除表中记录?BR>Void testDelete() throws Exception{
Cat cat = new Cat();
cat. setCatId(?11?;
ConnectionManage cm = new ConnectionManage();
cm.delete(cat);
cm.commit();
cm.close();
}