谢谢二位的答复和建议,受益良多!

除了我们以上谈到的这些考虑的因素,还需要考虑什么?我们能不能做一些归纳呢?

Designing Your Application for Best Performance

原文出处:http://e-docs.bea.com/wls/docs70/jdbc/performance.html

Most performance gains or losses in a database application is not determined by the application language, but by how the application is designed. The number and location of clients, size and structure of DBMS tables and indexes, and the number and types of queries all affect application performance.

The following are general hints that apply to all DBMSs. It is also important to be familiar with the performance documentation of the specific DBMS that you use in your application.

1. Process as Much Data as Possible Inside the Database

Most serious performance problems in DBMS applications come from moving raw data around needlessly, whether it is across the network or just in and out of cache in the DBMS. A good method for minimizing this waste is to put your logic where the data is―in the DBMS, not in the client ―even if the client is running on the same box as the DBMS. In fact, for some DBMSs a fat client and a fat DBMS sharing one CPU is a performance disaster.

Most DBMSs provide stored procedures, an ideal tool for putting your logic where your data is. There is a significant difference in performance between a client that calls a stored procedure to update 10 rows, and another client that fetches those rows, alters them, and sends update statements to save the changes to the DBMS.

Also review the DBMS documentation on managing cache memory in the DBMS. Some DBMSs (Sybase, for example) provide the means to partition the virtual memory allotted to the DBMS, and to guarantee certain objects exclusive use of some fixed areas of cache. This means that an important table or index can be read once from disk and remain available to all clients without having to access the disk again.

2. Use Built-in DBMS Set-based Processing

SQL is a set processing language. DBMSs are designed from the ground up to do set-based processing. Accessing a database one row at a time is, without exception, slower than set-based processing and, on some DBMSs is poorly implemented. For example, it will always be faster to update each of four tables one at a time for all the 100 employees represented in the tables than to alter each table 100 times, once for each employee.

Many complicated processes that were originally thought too complex to do any other way but row-at-a-time have been rewritten using set-based processing, resulting in improved performance. For example, a major payroll application was converted from a huge slow COBOL application to four stored procedures running in series, and what took hours on a multi-CPU machine now takes fifteen minutes with many fewer resources used.

3. Make Your Queries Smart

Frequently customers ask how to tell how many rows will be coming back in a given result set. The only way to find out without fetching all the rows is by issuing the same query using the count keyword:

SELECT count(*) from myTable, yourTable where ...

This returns the number of rows the original query would have returned, assuming no change in relevant data. The actual count may change when the query is issued if other DBMS activity has occurred that alters the relevant data.

Be aware, however, that this is a resource-intensive operation. Depending on the original query, the DBMS may perform nearly as much work to count the rows as it will to send them.

Make your application queries as specific as possible about what data it actually wants. For example, tailor your application to select into temporary tables, returning only the count, and then sending a refined second query to return only a subset of the rows in the temporary table.

Learning to select only the data you really want at the client is crucial. Some applications ported from ISAM (a pre-relational database architecture) will unnecessarily send a query selecting all the rows in a table when only the first few rows are required. Some applications use a 'sort by' clause to get the rows they want to come back first. Database queries like this cause unnecessary degradation of performance.

Proper use of SQL can avoid these performance problems. For example, if you only want data about the top three earners on the payroll, the proper way to make this query is with a correlated subquery. Table 3-1 shows the entire table returned by the SQL statement

select * from payroll


Table 3-1 Full Results Returned

Name
Salary

Joe
10

Mikes
20

Sam
30

Tom
40

Jan
50

Ann
60

Sue
70

Hal
80

May
80


A correlated subquery

select p.name, p.salary from payroll p
where 3 >= (select count(*) from payroll pp
where pp.salary >= p.salary);
returns a much smaller result, shown in Table 3-2.

Table 3-2 Results from Subquery

Name
Salary

Sue
70

Hal
80

May
80


This query returns only three rows, with the name and salary of the top three earners. It scans through the payroll table, and for every row, it goes through the whole payroll table again in an inner loop to see how many salaries are higher than the current row of the outer scan. This may look complicated, but DBMSs are designed to use SQL efficiently for this type of operation.

4. Make Transactions Single-batch

Whenever possible, collect a set of data operations and submit an update transaction in one statement in the form:

BEGIN TRANSACTION

UPDATE TABLE1...

INSERT INTO TABLE2

DELETE TABLE3

COMMIT

This approach results in better performance than using separate statements and commits. Even with conditional logic and temporary tables in the batch, it is preferable because the DBMS obtains all the locks necessary on the various rows and tables, and uses and releases them in one step. Using separate statements and commits results in many more client-to-DBMS transmissions and holds the locks in the DBMS for much longer. These locks will block out other clients from accessing this data, and, depending on whether different updates can alter tables in different orders, may cause deadlocks.

Warning: If any individual statement in the preceding transaction fails, due, for instance, to violating a unique key constraint, you should put in conditional SQL logic to detect statement failure and to roll back the transaction rather than commit. If, in the preceding example, the insert failed, most DBMSs return an error message about the failed insert, but behave as if you got the message between the second and third statement, and decided to commit anyway! Microsoft SQL Server offers a connection option enabled by executing the SQL set xact_abort on, which automatically rolls back the transaction if any statement fails.

5. Never Have a DBMS Transaction Span User Input

If an application sends a 'BEGIN TRAN' and some SQL that locks rows or tables for an update, do not write your application so that it must wait on the user to press a key before committing the transaction. That user may go to lunch first and lock up a whole DBMS table until the user returns.

If you require user input to form or complete a transaction, use optimistic locking. Briefly, optimistic locking employs timestamps and triggers in queries and updates. Queries select data with timestamp values and prepare a transaction based on that data, without locking the data in a transaction.

When an update transaction is finally defined by the user input, it is sent as a single submission that includes timestamped safeguards to make sure the data is the same as originally fetched. A successful transaction automatically updates the relevant timestamps for changed data. If an interceding update from another client has altered data on which the current transaction is based, the timestamps change, and the current transaction is rejected. Most of the time, no relevant data has been changed so transactions usually succeed. When a transaction fails, the application can refetch the updated data to present to the user to reform the transaction if desired.

6. Use In-place Updates

Changing a data row in place is much faster than moving a row, which may be required if the update requires more space than the table design can accommodate. If you design your rows to have the space they need initially, updates will be faster, although the table may require more disk space. Because disk space is cheap, using a little more of it can be a worthwhile investment to improve performance.

7. Keep Operational Data Sets Small

Some applications store operational data in the same table as historical data. Over time and with accumulation of this historical data, all operational queries have to read through lots of useless (on a day-to-day basis) data to get to the more current data. Move non-current data to other tables and do joins to these tables for the rarer historical queries. If this can't be done, index and cluster your table so that the most frequently used data is logically and physically localized.

8. Use Pipelining and Parallelism

DBMSs are designed to work best when very busy with lots of different things to do. The worst way to use a DBMS is as dumb file storage for one big single-threaded application. If you can design your application and data to support lots of parallel processes working on easily distinguished subsets of the work, your application will be much faster. If there are multiple steps to processing, try to design your application so that subsequent steps can start working on the portion of data that any prior process has finished, instead of having to wait until the prior process is complete. This may not always be possible, but you can dramatically improve performance by designing your program with this in mind.

可以参考jive ent的配置啊。呵呵,据说每天可以应付百万点击。
我记忆中那边的人建议:

更高档机器:比如sun 3800/4500级别。
好的数据库设计,且数据库集群。
快速的jvm
快速的AppServer
好的网络负载平衡设备。

至于代码优化么。。。。嘿嘿,建议听banq大哥上课咯。。。。

请教一下weblogic专家:
在deploy时,遇到以下错误是什么原因。我用的是weblogic7+jbuilder8,编译的工程是jbuilder自带的例子employee.jds。


D:\bea\jdk131_03\bin\javaw -classpath D:\bea\weblogic700\server\lib\weblogic.jar;D:\JBuilder8\lib\jdsserver.jar;D:\bea\weblogic700\server\lib\weblogic_sp.jar;D:\bea\weblogic700\server\lib\webservices.jar; weblogic.Deployer -user system -adminurl http://huangqi:7001 -password weblogic -activate -name TestEntMod -upload -source D:/jbproject/TestEntProject/TestEntMod.jar -targets myserver
Operation started, waiting for notifications...
...
TaskID Action Status Target Type Application Source
10 Activate Failed myserver Server TestEntMod D:\bea\user_projects\mydomain\myserver\upload\TestEntMod\TestEntMod.jar
Exception:weblogic.management.ApplicationException: activate failed forTestEntMod
Module: TestEntMod Error: Exception activating module: EJBModule(TestEntMod,status=PREPARED)
Unable to deploy EJB: Employee from TestEntMod.jar:
weblogic.ejb20.WLDeploymentException: The DataSource with the JNDI name: DataSource could not be located. Please ensure that the DataSource has been deployed successfully and that the JNDI name in your EJB Deployment descriptor is correct.
at weblogic.ejb20.cmp.rdbms.RDBMSPersistenceManager.setup(RDBMSPersistenceManager.java:130)
at weblogic.ejb20.manager.BaseEntityManager.setupPM(BaseEntityManager.java:214)
at weblogic.ejb20.manager.BaseEntityManager.setup(BaseEntityManager.java:186)
at weblogic.ejb20.manager.DBManager.setup(DBManager.java:161)
at weblogic.ejb20.deployer.ClientDrivenBeanInfoImpl.activate(ClientDrivenBeanInfoImpl.java:936)
at weblogic.ejb20.deployer.EJBDeployer.activate(EJBDeployer.java:1302)
at weblogic.ejb20.deployer.EJBModule.activate(EJBModule.java:342)
at weblogic.j2ee.J2EEApplicationContainer.activateModule(J2EEApplicationContainer.java:1534)
at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:991)
at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:978)
at weblogic.management.deploy.slave.SlaveDeployer.processPrepareTask(SlaveDeployer.java:1104)
at weblogic.management.deploy.slave.SlaveDeployer.prepareUpdate(SlaveDeployer.java:724)
at weblogic.drs.internal.SlaveCallbackHandler$1.execute(SlaveCallbackHandler.java:24)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:152)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:133)

我的经验:
假设以jdbc的查询速度为基数1。
1、ejb查询起码速度是6。
2、OR/mapping查询技术速度为2-3。取决于object的cache技术。
3、要用connection pool。
4、分页要用。你会发现速度主要是由数据库查询时间+显示时间构成。

目前我们在开发国税的项目,基于第一轮测试的结果,我想谈谈我的看法:
1、数据库方面
(1)硬件修改
采用磁盘阵列和裸设备会使性能大幅度提高,这种提高是数据库调整和优化所无法取代的,可以说硬件修改取得的效果比软件修改要好的多。
建议:可以联系到SUN或Intel的测试实验室中进行测试,他们提供很好的硬件设备并可以指导相应的数据库调优,然后把数据提供给客户,让他们决定采用什么设备。
(2)库调优
① 裸设备,数据库直接与磁盘设备交互,省略了中间的文件系统,速度加快。当然在磁盘阵列下效果更好
② 对表进行分区等,可参考《oracle性能挑优》一书,8i的,但很有启发。
③ 合理地使用SGA
④ 第三方软件的使用,建议Quest,非常全面的一套软件。

(2)weblogic方面
我刚参加工作7个多月,这些日子以来都是和weblogic打交道,6.x和7.x都用过,7.x速度没有6.x快,可能是因为东西复杂了,启动慢一些,但在性能上更稳定。
可以修改的参数
① 修改为startweblogic.cmd,增加绑定的内存数
② 通过控制台或直接修改config.xml,加大并行线程数和开放的sockets数,6.x下最大值为99个
③ 将log的回显设置为error级别,如果为debug等,则在回显信息到控制台也会站用时间和系统资源。在UNIX(Solaris)系统下,可以通过观察cpu的柱状图,如果黄色的部分过多,说明回显多,必须要调整。
(3)应用程序编写方面
① 采用session+DAO,我不是很赞成。
我们在测试时,使用的是weblogic6.x,测试软件为LoadRunner7.02,weblogic6.x不支持对stateful sessionbean 的并发访问,当一个stateful sessionbean在一个过程中时,另一个请求申请该stateful sessionbean,weblogic6.x提示该错误。只有修改jar包中weglogic-ejb-jar.xml中的相应项,填写<allow-concurrent--> true</allow-concurrent-- >,对不起,最后一个参数想不起了,可以参考〈weblogic宝典〉。
② Ormap的使用。
封装与数据库的接口,作成数据窗口(DataWindow),将数据库中的表与实体bean一一对应,在xml文件中指出,是比较好的方法,安全性高性能好。我们目前就是采用这种方法。可以参考ekernel产品等。
③ 与oracle的连接池,当然要使用jdbc:oracle:thin:@ip:1521:sid了,这是比较好的选择,
④ 工具开发可以考虑jb8等,很不错。

小妹说的不好,这些都是这几个月来所的,希望对您有帮助,如果有不对的地方,请见谅

十分感谢朋友们的大力帮助!WebLogic目前在国内应用的越来越广泛,相信朋友们今后工作会经常遇到相关问题。一个好的系统无非就是要做到可靠、高效和安全,而实际工作中我们往往顾此失彼,所以将一个方案研究的透彻一些,挖掘出方案中每个步骤的潜力将对我们大有益处。

对于wangbaolei朋友的建议我十分感谢。当然基于客观条件的限制,有一些试验我们这里进行不了,但是关于
――――――――
① 采用session+DAO,我不是很赞成。
我们在测试时,使用的是weblogic6.x,测试软件为LoadRunner7.02,weblogic6.x不支持对stateful sessionbean 的并发访问,当一个stateful sessionbean在一个过程中时,另一个请求申请该stateful sessionbean,weblogic6.x提示该错误。只有修改jar包中weglogic-ejb-jar.xml中的相应项,填写 true,对不起,最后一个参数想不起了,可以参考〈weblogic宝典〉。
――――――――
的问题正是我们遇到过的,当进行压力测试一段时间后系统提示BEAN被删除,我们的解决办法是在weglogic-ejb-jar.xml里设置该bean的最大连接池数目。不过由于我们的开发经验还不够多,还需要研究。

关于WebLogic的修改对我们很有帮助,今天刚刚和BEA的工程师通了电话,他们提出的意见也是如此,但没有你说的全面。

总之,对所有参与的朋友致万二分的感谢,希望我们能把这个话题深入下去,大家把自己开发类似的J2EE的经验共享出来,共同提高。

wangbaolei:

我想了一下,在实际应用中会出现stateful sessionbean 的并发访问吗?似乎只存在于实验中?

另外,我们在写EJB代码中遇到一个奇怪的问题,即servlet调用Entity Bean的creat()向数据库(Oracle 8.17)里增加一条记录时,在JBUILDRE 7中测试通过,但是发布到WebLogic 7后,运行报错,提示无此方法――

Root cause of ServletException
java.lang.NoSuchMethodError


但是将Integer型参数去掉后(即插入三个字段的数据),servlet调用成功,数据成功插入。什么原因呢?

Home接口如下

public interface HJXXHome extends EJBHome {
public HJXXRemote create(String zSQBH, String zHJBH, String zHZMC, int zLSH) throws CreateException, RemoteException;
public HJXXRemote findByPrimaryKey(String zHJBH) throws FinderException, RemoteException;
}


Remote接口如下――

public interface HJXXRemote extends EJBObject {
public void setZSQBH(String zSQBH) throws RemoteException;
public String getZSQBH() throws RemoteException;
// public void setZHJBH(String zHJBH) throws RemoteException;
public String getZHJBH() throws RemoteException;
public void setZHZMC(String zHZMC) throws RemoteException;
public String getZHZMC() throws RemoteException;
public void setZLSH(int zLSH) throws RemoteException;
public int getZLSH() throws RemoteException;
}

Bean如下――

abstract public class HJXXBean implements EntityBean {
protected EntityContext entityContext;
public HJXXBean() {
}
public String ejbCreate(String zSQBH, String zHJBH, String zHZMC, int zLSH) throws CreateException {
setZSQBH(zSQBH);
setZHJBH(zHJBH);
setZHZMC(zHZMC);
setZLSH(zLSH);
return null;
}
public void ejbPostCreate(String zSQBH, String zHJBH, String zHZMC, int zLSH) throws CreateException {
/**@todo Complete this method*/
}
……
}

Servlet代码如下――

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.naming.*;
import java.util.*;
import java.lang.reflect.*;
import javax.rmi.PortableRemoteObject;
import com.bigchina.util.*;
import com.bigchina.system.*;
import ejb.bigchina.mzweb.sqjmda.*;

public class editHJXX extends HttpServlet {
Context ctx = null;
HJXXHome Home = null;
static final private String REDIRECT_PAGE = "/jsp/editclient.jsp"; //编辑页面
static final private String LIST_PAGE = "jsp/listclient.jsp"; //列表显示页面
private Context getInitialContext() throws Exception {
String url = "t3://locasthost:7001";
String user = null;
String password = null;
Properties properties = null;
try {
properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
properties.put(Context.PROVIDER_URL, url);
return new InitialContext(properties);
} catch(Exception e) {
throw e;
}
}
public void init() throws ServletException {
try {
System.out.println("--------ok1-------");//已经通过
ctx = getInitialContext();
System.out.println("--------ok2-------");//已经通过
Home = (HJXXHome)PortableRemoteObject.narrow(ctx.lookup("HJXXHome"),HJXXHome.class);
System.out.println("--------ok3-------");//已经通过
} catch(Exception e) {
e.printStackTrace();
}
}

/**
* @Create Date:(2003-02-19)<br>
* @Create Author:zhanpeng<br>
* @param: request - the previous page's HttpServletRequest
* @param: response - this page's HttpServletResponse<br>
* @throws ServletException
* @throws IOException
* <b>Description:</b>处理editclient.jsp页面请求
*/
public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {

try {
System.out.println("-----调用保存方法之前----");//已经通过
editAdd(request, response);
System.out.println("-----调用保存方法之后----");//=======没有通过========
} catch (Exception e) {
e.printStackTrace();
}
}

//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}

//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}

/**
* @Create Date:(2002-09-24)<br>
* @Create Author:ankai<br>
* @param HttpServletRequest request
* @param HttpServletResponse response
* @exception throws Exception<br>
* <b>Description:</b>处理添加页面请求,进行添加操作
*/
private void editAdd(HttpServletRequest request, HttpServletResponse response) throws Exception {
String messageContent = "";
String type = "";
String zSQBH = ParamUtils.getParameter(request,"zsqbh");
String zHJBH = ParamUtils.getParameter(request,"zhjbh");
String zlsh = ParamUtils.getParameter(request,"zlsh");
//int zLSH = Integer.parseInt(zlsh);
int zLSH=0;
String zHZMC = ParamUtils.getParameter(request,"zhzmc");
try {
System.out.println("remote");
zSQBH="1101";
zHJBH="1101";
zHZMC="1101ak";
zLSH=1101;
//Home.findByPrimaryKey("b");
System.out.println("after find");
Home.create(zSQBH,zHJBH,zHZMC,zLSH);//=======没有通过========
} catch(Exception e) {
System.out.println("Home.create方法错误:"+e.getMessage());
e.printStackTrace();
}
}
//Clean up resources
public void destroy() {
}
}

在Jbuilder里的测试客户端程序代码,在这里通过――

import ejb.bigchina.mzweb.sqjmda.*;
import javax.naming.*;
import java.util.Properties;
import javax.rmi.PortableRemoteObject;

public class HJXXTestClient {
private HJXXHome hJXXHome = null;

//Construct the EJB test client
public HJXXTestClient() {
try {
//get naming context
Context ctx = getInitialContext();

//look up jndi name
Object ref = ctx.lookup("HJXXRemote");

//cast to Home interface
hJXXHome = (HJXXHome) PortableRemoteObject.narrow(ref, HJXXHome.class);
}
catch(Exception e) {
e.printStackTrace();
}
}

private Context getInitialContext() throws Exception {
String url = "t3://zp:7001";
String user = null;
String password = null;
Properties properties = null;
try {
properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
properties.put(Context.PROVIDER_URL, url);
if (user != null) {
properties.put(Context.SECURITY_PRINCIPAL, user);
properties.put(Context.SECURITY_CREDENTIALS, password == null ? "" : password);
}

return new InitialContext(properties);
}
catch(Exception e) {
System.out.println("Unable to connect to WebLogic server at " + url);
System.out.println("Please make sure that the server is running.");
throw e;
}
}

//----------------------------------------------------------------------------
// Utility Methods
//----------------------------------------------------------------------------

public HJXXHome getHome() {
return hJXXHome;
}
//Main method

public static void main(String[] args) {
HJXXTestClient client = new HJXXTestClient();
// Use the getHome() method of the client object to call Home interface
// methods that will return a Remote interface reference. Then
// use that Remote interface reference to access the EJB.
try {
Context ctx = client.getInitialContext();
HJXXHome Home = (HJXXHome)PortableRemoteObject.narrow(ctx.lookup("HJXXRemote"),HJXXHome.class);
Home.create("a","b","c",1);
} catch(Exception e) {
e.printStackTrace();
}
}
}

以上就是我们碰到的奇怪的问题,大家能帮忙解决吗?

不能使用基本数据类型int, 必须使用Integer对象.

另外建议不要用中文拼音缩写做对象名和method名, 会给以后维护带来很大的麻烦.

顺便问一下怎么修改config.xml文件和weblogic.sh文件
多谢!

看了大家的讨论,得益很多。我也碰到这个问题,除了几位高手提出的方法外,能不能在weblogic和数据库之间再增加一层中间件产品,负责事务处理和数据库访问。因为tuxdo是应用很久的产品,有很多大型应用都采用了这个产品,但客户端使用的是c编写。通过bea的文档,知道tuxdo提供jolt和weblogic互联,能否利用它来提高j2ee应用的效率。我正在做这个试验,因为初次使用bea的产品,调试很不顺利,还没有得出结果。请问大家这个方法是否可行?

大约2年前做过类似的应用,随便说说,很长时间不碰ejb/weblogic了,有些东西可能已经变化了,说错了别怪
1。cluster,碰巧在6.1上做过这个cluster,不太复杂,基本上在开发阶段可以不用考虑这个问题,只要保证你对应用资源的访问是通过JNDI的方式既可。做cluster还有一个主要原因不是性能,而是为了容错,在一台机
死掉的情况下可以继续使用另外一台机。不过weblogic的load balance算法是否不够合理,印象当中不能做到很好的负载均衡,以前参加hp的培训
老师特别指出这个缺陷,呵呵。有个道友说不支持singleton模式,这是错误的,准确的说法是不应该使用static的变量,(因为cluster或者ejb用多个jvm实现的缘故),TSS上有个一模式叫做jndi singletion就是介绍少使用jndi的方式来实现,我当初用类似的方法实现算好器
2。ejb的使用,实际我个人认为,你们的应用如果只是单存的查询,
根本可以不使用ejb,速度还会更开,对了,你们什么公司,告诉我简写好不好。这个系统我以前公司也做过。用resin ,再用servlet+jsp的方式,性能应该比用weblogic + ejb好,成本也会低些。或者用海獭,那个据说比weblogic快一个数量级。
你们的应用只是查询的话,session bean+dao应该是比较理想的方式,不过有这些地方要注意
・。使用oracle的话,一定要注意jdbc,一定要用oracle自己的jdbc而且还必须是817以后的。当初使用816碰到一个莫名其妙的问题,最后在oracle网站上才查明原因,17以前的版本都不行。我很早以前就做个测试
所谓oci比thin的速度快的说法不成立,其实两者都是用socket,很难说谁效率高,何况oci的方式还多了一层。不过我感觉oci的方式更安全,因为以前在数据库里跟踪,发现jdbc方式的连接看不到来源,说明jdbc thin的方式省掉一些东西。
・对查询操作,直接用jdbc read的方式比较高效率,但是对transaction的使用要注意,另外一个是datasource的获取,因为jndi的lookup是比较慢的如果每次为了得到conneciton都要去lookup datasource,这个效率会很低,你可以试验一下,很多人不太注意这一点。
・连接的关闭问题,都是老生长谈了,一定要保证statement, resultset,connection都是关闭的,我最早就不太注意关闭statement,结果问题一大堆。当然,这和jdbc地实现有一定关系。
・sql语句的优化,这点8i以前做得很不好,不会想sql server那样自动优化,现在不知道怎么样了,差别很远。
・访问方式,通过sevlet访问ejb, 不用使用remote接口,如果用的是ejb1.1的方式,我记得在6.1上可以不用narrow 直接转换,性能和local 差不多(记得可能不确切了,当初无意发现的)。
・session bean,其实像你们这样的应用,基本可以不用stateful的,都是只读查询,要状态做什么?有无状态,性能差很远。stateful session bean + dao,cache也用不到多少,还要考虑兵法,应该比servlet + dao差很多吧。

3.最重要的一点就是缓存,对于这种类型的应用,用不用缓存差别巨大。
可缓存的内容很多,实现方式也比较多。最简单的机制是对query的缓存
相同的sql语句,相同的参数就进行缓存,不做重复的查询,简单,效果也不错。还有页面的,如果你们没有使用mvc的方式,直接用的jsp页面,有现成的一些缓存机制可以用,比如那个oscache(好像是),性能可以改善一个数量级。
4。weblogic的设置方面不太清楚,你提的有几个,我还没听说过,落后了,赫赫。该有的问题,好像文档里都有,bea的工程师也不是都有经验,以前很多问题都是自己搞定的,不要太相信bea的人。他们好像每个人都背了几句经典答案,说来说去都是那些。
5。使用bea的新版的专用jvm性能据说很不错,可以试试。
对了,不用或少用http session的原因是什么和你说的主题有什么关系?

总的来说我觉得这类型的应用很难算高负荷的,用好数据库(软硬件都下点功夫),选择合理的模式,一般都没问题。甚至全部用开源的产品也能实现。


1)当然我遇到了这样的问题,我曾协助我们公司工作流系统的测试,他们有一个stateful ejb。我们要模仿现实生活中多用户访问工作流的现象(比如多个用户同时发出文书申请的请求)。我用loadrunner模拟并发,wls提示错误。解决方法要么是修改配置牺牲性能,要么是修改代码但时间又不允许。

你另外说的ejb的nosuchmethoderror是个经常出现的问题,最近在我制作版本时,也经常出现,另许多同组的开发人员都很头痛,你的这个应该很好解决,为什么不使用jb7的跟踪功能调试呢。

找到出问题的句子。
我们的j2ee项目831个模块,每个模块在单元测试时都是这样调试的,

具体做法为在jb中配置server;在run配置中新建一个,选择debug,然后配置参数,设置断点就可以了。

因为最近实在太忙了,要build,要写测试用例,还要配置管理,等周末我在家里调调,这个问题挺有趣的。

建议不要用entity bean,而用DAO模式。
数据库连接方面用weblogic的连接池和用jca