打算到上海浙江一帶去放松,解決工作上的壓力?,F在是去不成了,國慶4天假,廣州不是放松的好地方。白云山還算可以一去,只好改去珠海玩兩天,吃點海鮮補償補償了
posted @
2005-10-01 12:59 ceaboat 閱讀(416) |
評論 (0) |
編輯 收藏
WASD支持熱啟動,修改代碼保存服務器進行實時更新,CachedRowSet crs = new CachedRowSetImpl();緩存數據集出異常。服務器熱啟動與緩存機制之間有沖突。
posted @
2005-10-01 12:54 ceaboat 閱讀(436) |
評論 (0) |
編輯 收藏
??????????????????????????????????????????????????????????測試源代碼
CapabilityForConnection?主運行程序,讀取配置文件init.properties、reference.properties初始化參數。調用POOLTEST(一次完整的測試用例),計算其平均時間與使用連接數
package?com.cea.repository.test;
import?org.apache.commons.logging.LogFactory;
import?org.apache.commons.logging.Log;
import?java.util.Properties;
import?java.io.FileInputStream;
import?java.io.InputStream;
public?class?CapabilityForConnection?{
????private?static?Log?log?=?LogFactory.getLog(CapabilityForConnection.class);
????/**
?????*?計算一次測試所消耗的時間
?????*/
????public?static?long?times?=?0;
????/**
?????*?連接數
?????*/
????public?static?long?psize?=?0;
????public?static?void?main(String[]?args)?throws?Exception?{
????????/**
?????????*?運行的次數
?????????*/
????????int?size?=?1;
????????/**
?????????*?見POOLTEST說明
?????????*/
????????int?execsum?=?0;
????????/**
?????????*?見POOLTEST說明
?????????*/
????????int?opencon?=?0;
????????/**
?????????*?execsum對應properties的命名
?????????*/
????????String?execs?=?null;
????????/**
?????????*?opencon對應properties的命名
?????????*/
????????String?openc?=?null;
????????long?sumtime?=?0;
????????Properties?prop?=?initProperty("reference.properties");
????????Properties?init?=?initProperty("init.properties");
????????if?(init.size()?>?0)?{
????????????Object?o?=?init.get("init");
????????????size?=?Integer.parseInt(o.toString());
????????????execs?=?init.get("name0").toString();
????????????openc?=?init.get("name1").toString();
????????}
????????for?(int?i?=?0;?i?<?prop.size()?/?2;?i++)?{
????????????execsum?=?Integer.parseInt(prop.getProperty(execs?+?i).toString());
????????????opencon?=?Integer.parseInt(prop.getProperty(openc?+?i).toString());
????????????sumtime?=?0;
????????????psize?=?0;
????????????log.info("第"?+?(i?+?1)?+?"組數據:");
????????????log.info("并發應用數:"?+?execsum?+?"?模擬連接數:"?+?opencon);
????????????String[]?reference?=?{""?+?execsum,?""?+?opencon};
????????????for?(int?j?=?0;?j?<?size;?j++)?{
????????????????times?=?0;
????????????????PoolTest.main(reference);
????????????????sumtime?+=?times;
????????????}
????????????log.info("第"?+?(i?+?1)?+?"組數據共執行"?+?size?+?"次;平均耗時為:"?+
?????????????????????sumtime?/?(size?*?execsum)?+?"毫秒");
????????????log.info("平均使用"?+?psize?/?size?+?"個連接");
????????}
????}
????private?static?Properties?initProperty(String?filename)?throws?Exception?{
????????InputStream?is?=?new?FileInputStream(filename);
????????Properties?prop?=?new?Properties();
????????prop.load(is);
????????return?prop;
????}
}
POOLTEST計算一次完整過程耗時,統計消耗的連接
package?com.cea.repository.test;
import?com.cea.repository.test.testdata.MainExecute;
import?java.util.HashMap;
import?java.util.Map;
import?com.cea.repository.connection.PoolSupper;
import?org.apache.commons.logging.LogFactory;
import?org.apache.commons.logging.Log;
/**
?*
?*?
Title:?連接池性能測試
?*
?*?
Description:?測試不合理的利用連接對WEB應用所造成影響.
?*
?*?
Copyright:?Copyright?(c)?2005
?*
?*?
Company:?
?*
?*?@author?小舟
?*?@version?1.0
?*/
public?class?PoolTest?extends?Thread?{
????private?static?Log?log?=?LogFactory.getLog(PoolTest.class);
????/**
?????*?并發執行MainExecute的數量
?????*/
????private?static?int?EXECUTESUM?=?35;
????/**
?????*?一次MainExecute執行所請求的連接數
?????*/
????public?static?int?CONNECTIONS?=?3;
????/**
?????*?記錄所使用的連接
?????*/
????public?static?Map?poolTestMap?=?new?HashMap();
????/**
?????*?第sum次執行MainExecute所需要的時間
?????*/
????public?int?sum?=?0;
????public?void?run()?{
????????try?{
????????????long?s?=?System.currentTimeMillis();
????????????com.cea.repository.test.testdata.MainExecute.main(null);
????????????long?t?=?System.currentTimeMillis()?-?s;
????????????CapabilityForConnection.times?+=t;
//????????????if(CapabilityForConnection.times?//????????????????CapabilityForConnection.times?=?t;
//????????????}
//????????????log.info("time"?+?(++sum)?+?":"?+
//???????????????????????????????(System.currentTimeMillis()?-?s));
????????}?catch?(Exception?ex)?{
????????}
????}
????public?static?void?main(String[]?args)?throws?Exception?{
????????if(args!=?null?&&?args.length>1){
????????????EXECUTESUM?=?Integer.parseInt(args[0]);
????????????CONNECTIONS?=?Integer.parseInt(args[1]);
????????}
????????PoolSupper.initPool();
????????startExec(EXECUTESUM);
????????//設定足夠長的時間等待所有程序執行完,得到準確的并發執行所消耗的時間
????????try?{
????????????Thread.sleep(6000);
????????}?catch?(InterruptedException?ex)?{
????????????ex.printStackTrace();
????????}
????????log.info("運行平均耗時:"?+?CapabilityForConnection.times/EXECUTESUM);
????????//如果條件成立,證明連接沒有被回收,只要存在一個相同的,就證明連接被重復利用了
????????CapabilityForConnection.psize?+=poolTestMap.size();
????????if?(poolTestMap.size()?==?EXECUTESUM)?{
????????????log.info("不存在重復使用的連接,共創建"?+?poolTestMap.size()+?"個連接"?);
????????}?else?{
????????????log.info("共使用"?+?poolTestMap.size()+?"個連接"?);
????????}
????????clear();
????}
????private?static?void?startExec(int?EXECUTESUM)?{
????????int?i?=?0;
????????while?(i?<?EXECUTESUM)?{
????????????if?(i++?<?EXECUTESUM)?{
????????????????try?{
????????????????????new?PoolTest().start();
????????????????}?catch?(Exception?ex2)?{
????????????????}
????????????}
????????}
????}
????private?static?void?clear()?{
????????poolTestMap?=?new?HashMap();
????}
}
簡單的不能再簡單的測試代碼:
package?com.cea.repository.test.testdata;
import?com.cea.repository.connection.drive.ConnectionFactory;
import?java.sql.Connection;
import?java.sql.Statement;
import?java.sql.ResultSet;
import?java.sql.PreparedStatement;
import?java.util.HashMap;
import?java.util.Map;
import?java.util.List;
import?java.util.ArrayList;
import?com.cea.repository.test.PoolTest;
import?com.cea.repository.connection.poolpository.PoolFactory;
/**
?*?
?*?
Title:?
?*?
Description:?
?*?
Copyright:?Copyright?(c)?2004
?*?
Company:?cea
?*?@author?小舟
?*?@version?1.0
?*/
public?class?MainExecute?{
????public?static?void?main(String[]?args)?throws?Exception?{
???????testConnection();
????}
????static?void?testConnection()?throws?Exception?{
????????for?(int?i?=?0;?i?<?PoolTest.CONNECTIONS;?i++)?{
????????????Connection?con?=?PoolFactory.newInstance();
????????????//這里的改變直接影響連接的復用
????????????Thread.sleep(50);
????????????PoolTest.poolTestMap.put(con.toString(),?"");
????????????con.close();
????????}
????}
}
三個配置文件的內容:
init.properties文件
#運行的次數
init=5
#并發執行MainExecute的數量所匹配的名字
name0=execsum
#一次MainExecute執行所請求的連接數所匹配的名字
name1=opencon
reference.properties文件
#過濾數據
execsum0=10
opencon0=1
#第一次測試數據
execsum1=100
opencon1=6
#第二次測試數據
execsum2=85
opencon2=9
#第三次測試數據
execsum3=140
opencon3=3
最后一個是pool-config.xml數據源配置:
xml?version="1.0"?encoding="GB2312"?>
<DataResources>
??<ResourceParams?dateIndentity="boat1">
????<defaultAutoCommit>false< SPAN>defaultAutoCommit>
????<initialSize>30< SPAN>initialSize>
????<maxActive>40< SPAN>maxActive>
????<minIdle>0< SPAN>minIdle>
????<maxIdle>18< SPAN>maxIdle>
????<maxWait>10000< SPAN>maxWait>
????<username>forum< SPAN>username>
????<password>king< SPAN>password>
????<driverClassName>oracle.jdbc.driver.OracleDriver< SPAN>driverClassName>
????<url>jdbc:oracle:thin:@192.168.1.3:1521:gzest< SPAN>url>
????<removeAbandoned>true< SPAN>removeAbandoned>
????<removeAbandonedTimeout>10< SPAN>removeAbandonedTimeout>
????<logAbandoned>true< SPAN>logAbandoned>
??< SPAN>ResourceParams>
< SPAN>DataResources>

posted @
2005-09-26 22:36 ceaboat 閱讀(1652) |
評論 (0) |
編輯 收藏
影響性能的測試報告(數據庫版)
如需轉載,請與筆者聯系
前提:項目組里無用到SPRING進行事務的管理。項目里以功能劃分到每個人手里,
形成了BO,DAO,ACTION,VIEW都是單人負責。在DAO中每個動作都以
封閉式的形式存在。
問題:造成事務的不連貫性。功能是做出來了,性能問題遲早暴露。
測試:主要針對程序頻繁請求數據庫連接對WEB應用所造成影響做一個測試。
先做必要的說明,一步步引入正題,先從性能瓶頸開始:
所有的應用程序都存在性能瓶頸,為了提高應用程序的性能,就要盡可能的減少程序的瓶頸。以下是在JAVA程序中經常存在的性能瓶頸。

了解了這些瓶頸后,就可以有針對性的減少這些瓶頸,從而提高JAVA應用程序的性能
關于連接池的實現原理測試方案:
經過資料的收集與APACHE DBCP里連接池的查閱,對現有的連接池工作
原理有兩種方式:
1. 數據庫預先設置配置好的連接數。待得到用戶請求連接,傳出一個連接,而后為了保持供應數再提前創建連接,即提前預備連接數供請求。比如:
有5個通行道代表最大激活的連接數,最小2個閑置連接數。也就是說連接池里始終預備了2個可隨時提供的連接,連接的創建開銷是比較大的,連接池的存在就是了能夠最小化的解決創建所等待的時間。
1 O
2 O
3 *
4 *
5 *
如上圖,當1分配出去時由于池中連接數剩一個,為保持最小閑置,會自動創建一個新的連接以防止再次請求等待創建的時間。這樣確實減少了等待的時間,但是數據庫創建的開銷方面并未得到解決。如果把1-5比喻成汽車,那么這種情況下每量車都是一次性使用。1被請求后下一個連接將是6來接替。那么如何能夠重復利用1減少數據庫開銷。于是引出第二種方式。
2. 回收使用完后的連接,放回到池中進行循環利用。這么做必須能保證2點
一. 使連接能夠保持有效的回收。
二. 約束使用者使用釋放的動作,而不是直接把連接close.
本人使用的是APACHE DBCP里BasicDataSource的連接池基本實現,
經過代碼與測試結果顯示,其工作方式是基于二的。
請看測試用例
測試結果:
第2組數據:
并發應用數:100 模擬連接數:6
運行平均耗時:2956
共使用51個連接
運行平均耗時:3391
2共使用52個連接
運行平均耗時:2616
共使用47個連接
運行平均耗時:3377
共使用41個連接
運行平均耗時:3673
共使用46個連接
第2組數據共執行5次;平均耗時為:3229毫秒
平均使用47個連接
第3組數據:
并發應用數:85 模擬連接數:9
運行平均耗時:4830
共使用53個連接
運行平均耗時:3247
共使用49個連接
運行平均耗時:4116
共使用40個連接
運行平均耗時:4070
共使用43個連接
運行平均耗時:4053
共使用54個連接
第3組數據共執行5次;平均耗時為:4063毫秒
平均使用47個連接
第4組數據:
并發應用數:140 模擬連接數:3
運行平均耗時:2076
共使用47個連接
運行平均耗時:3104
共使用51個連接
運行平均耗時:2048
共使用43個連接
運行平均耗時:2421
共使用50個連接
運行平均耗時:2751
共使用50個連接
第4組數據共執行5次;平均耗時為:2480毫秒
平均使用48個連接
每次測試的結果都可能不同,但是所得到的結論是一致的。數據顯示不合理的請求使用連接嚴重的影響應用所能承受的并發數量,響應的時間也因此受到影響。
沒有把事務控制好,一般會出現以下的情況:
事務(){
流程1();
流程2();
}
可以看出流程1,2里都是單獨創建連接,并在自己的流程里完成操作。
如果在流程2里出現異常,那么流程1所做的操作是不可恢復的。
如果能控制在事務范圍內,如:
事務(){
Connection con;
流程1(con);
流程2(con);
con.close();
}
那么數據庫少提供一個連接,事務的完成性也得到體現。在并發數量大的時候,
效率上就有非常明顯的區別。
1. 盡量保持少的請求
如DAO中有update()方法,則應再擴展一個方法update(Connection conn)
在業務邏輯事務里調用update(Connection conn),一般情況下調用update()
2. 對于數據不變的情況采用緩存技術,或部分緩存技術。
可參照一些相關的開源的項目(JIVE)。
posted @
2005-09-25 17:21 ceaboat 閱讀(1663) |
評論 (4) |
編輯 收藏
把ent.slip放入\Borland\JBuilder2006\license里
posted @
2005-09-24 13:45 ceaboat 閱讀(811) |
評論 (2) |
編輯 收藏
1.運行環境:
JDK,ORACLE9i以上,CASTOR包。建議使用JBUILDE
工具進行開發
2.使用環境:
采用ORM(關系對象映射)操作數據庫數據,適用于Application與WEB方式下的開發。
3.功能:
提供查詢,更新,刪除,插入(沒實現主鍵自動生成),(分頁暫時沒實現)。4.使用步驟:
首先在數據庫建立一個cat表,字段為cat_id;name;sex;weight;類型1,4為數字型,2,
3為字符串型。
其次建立兩個配置文件(由自己定義文件名稱):
repository.xml配置信息:
<?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>
配置文件的設計說明如下:
TableDesc 表示一個表的聲明。
Execid 是類名一般情況下最好和表名一致(容易找到對應關系),但是不允許有下劃線出現。注意這個類名不是全路徑。
DentifyField 表中的主鍵,如果是復合主鍵則以逗號相隔開
Table 數據庫表名
<FieldDesc name="SEX" fieldType="java.lang.String" >
<title>SEX</title>
</FieldDesc>
這里是表中字段的描述,name是字段名。 fieldType 是數據庫字段對
應java中的類型,只有4中類型可填充:java.lang.String,
java.lang.Long, java.util.Date, java.lang.Double
title可要可不要.如果存在多個表,那么就在</TableDesc>和
</Repository>之間加入表描述。
pool-config.xml配置信息:
<?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>
把上述信息保存為XML文件。對這個文件不多做說明了。
確定兩個文件已經存在,接下來就是要創建表CAT。
還有表所對應的BEAN。
下面是我在Hibernate的一個例子中建立的VO。(借用)
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;
}
}
到此已經完成了該做的事了,下面是一個使用的例子。
l查詢方式:
例子:
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=’1’ ”);
while (Query.hasNext()) {
Object[] objects = Query.next();
Cat cat = (Cat) objects[0];
}
connectionManage.close();
}
說明:
在WEB中使用只需要在網站啟動時聲明一次即可。
{
//指明使用連接池
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 DataManage = new ConnectionManage();
激活要使用類(在配置中必須有Cat),類名為全路徑如果要使用多個對象,則對象間要用逗號相隔開
connectionManage.activity("com.cea.boat.dao.Cat cat");
這里只需要給出SQL查詢條件比如SQL中是select * from cat cat where cat.Catid=‘1’那么 select * from cat cat where 這里后臺已經幫你完成,你需要做的就是把條件完成,如果沒有條件則為空.
Query Query = connectionManage.createQuery(“cat. Catid=’1’ ”);
Query.hasNext()的作用相當于resultset.next()查看是否還存在記錄,Query.next()返回一個對象數組這里如果activity的是多個對象,那么objects里會順序的存儲相應的對象實例,使用的時候強制轉化就可以了。
while (Query.hasNext()) {
Object[] objects = Query.next();
Cat cat = (Cat) objects[0];
}
使用完畢,釋放使用的數據庫資源
connectionManage.close();
l新增方式:
由于沒有主鍵自動生成,因此主鍵暫時只能由自己來維護,要保證catid為111的在表里不存在,否則會出現異常。
Void testInsert() throws Exception{
Cat cat = new Cat();
cat. setCatId(“111”);
cat. SetSex(“F”);
cat. setName(“catm”);
ConnectionManage cm = new ConnectionManage();
cm.create(cat);
cm.commit();
cm.close();
}
l更新方式:
表里已經存在catid為111的貓,否則查不到這條記錄就更新不了信息
Void testUpdate() throws Exception{
Cat cat = new Cat();
cat. setCatId(“111”);
cat. SetSex(“F”);
cat. setName(“catmm”);
ConnectionManage cm = new ConnectionManage();
cm.update(cat);
cm.commit();
cm.close();
}
l刪除方式:
刪除方式比較簡單,只要給出對象,并且主鍵值不為空,就可以刪除表中記錄。
Void testDelete() throws Exception{
Cat cat = new Cat();
cat. setCatId(“111”);
ConnectionManage cm = new ConnectionManage();
cm.delete(cat);
cm.commit();
cm.close();
}
posted @
2005-09-15 23:41 ceaboat 閱讀(432) |
評論 (0) |
編輯 收藏