BEA WebLogic平台下J2EE调优攻略----第一章 应用程序调优

第一章 应用程序调优
1.1.1 通用代码调优

1.1.2 减小没有必要的操作
  对象的创建是个很昂贵的工作,所以我们应当尽量减少对象的创建,在需要的时候声明它,初始化它,不要重复初始化一个对象,尽量能做到再使用,而用完后置null有利于垃圾收集。让类实现Cloneable接口,同时采用工厂模式,将减少类的创建,每次都是通过clone()方法来获得对象。另外使用接口也能减少类的创建。对于成员变量的初始化也应尽量避免, 特别是在一个类派生另一个类时。

  异常抛出对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为, fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。

  此外, 建议关闭Debug输出,尽量少用串行化、同步操作和耗时昂贵的服务(如Date())。

1.1.3 使用合适的类型

  当原始类型不能满足我们要求时,使用复杂类型。String和StringBuffer的区别自不必说了,是我们使用最多的类型,在涉及到字符运算时,强烈建议使用StringBuffer。在做String匹配时使用intern()代替equal()。

  带有final修饰符的类是不可派生的, 如果指定一个类为final,则该类所有的方法都是final。

  Java编译器会寻找机会内联所有的final方法,这将能够使性能平均提高50%。类的属性和方式使用final或者static修饰符也是有好处的。

  调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。所以尽量使用局部变量。

  ArrayList和Vector,HashMap和Hashtable是我们经常用到的类,前者不支持同步,后者支持同步,前者性能更好,大多数情况下选择前者。

1.1.4 尽量使用pool,buffer和cache
  使用pool、buffer和cache能大大提高系统的性能,这在J2EE的大部分技术中都是适用的。

  在WebLogic中就大量使用了池:JDBC Connection Pool、Socket Pool、Object Pool和Thread Pool。I/O操作中,buffer是必须的,特别是对大文件的操作,不然容易造成内存溢出。字节操作最快,所以尽可能采用write(byte []),Buffered FileOutputStream比Buffered FileWriter要快,因为FileWriter需要Unicode到Byte的转换。

  而后面讲到的JDBC、JSP、EJB和JMS我们都非常建议使用buffer和cache。为HttpServletResponse设置buffersize,使用wl-cache,缓存在JNDI树上获取的对象等等。

  此外,使用JDK 1.4的非阻塞I/O对性能也有很大提高。

1.2 JDBC代码调优
1.2.1 严格资源使用
  JDBC代码调优最大的原则就是使用WebLogic的连接池,而不是自己直连数据库。在我接触的很多自己实现连接池的项目中,大部分遇到死锁和连接泄漏的问题,最后得不得修改代码。而WebLogic提供了功能强大,性能良好的数据库连接池,我们要做的只是封装一个连接管理类,从JNDI树上获取数据源并缓存,得到连接,并提供一系列关闭数据库资源的方法。

  对任何资源使用的原则是用完即关,不管是数据库资源、上下文环境,还是文件。数据库资源的泄漏极易造成内存泄漏,乃至系统崩溃。在使用完数据库资源后依次关闭ResultSet,Statement和Connection,而在一个数据库连接多次进行数据库操作时要特别注意ResultSet和 Statement依次关闭。

try{
  //open connection
  pstmt =conn.prepareStatement(strSql1);
  pstmt.executeUpdate();
  pstmt.close();
  pstmt =conn.prepareStatement(strSql2);
  rs=pstmt.executeQuery();
  while (rs.next()){
  //process
 }
rs.close();
pstmt.close();
 }catch(Exception e){
  //close rs,psmt,con
}finally{
  //close rs,psmt,con
}

1.2.2 实用技巧
  在JDBC操作中还有一些小的技巧跟大家分享:由于获取连接时默认自动提交方式,使用connection.setAutoCommit (false)关闭自动提交,使用PreparedStatement,批量更新,业务复杂或者大数据量操作时使用存储过程,尽量使用RowSet,此外设置记录集读取缓存FetchSize和设置记录集读取方向FetchDirection对性能也有一定的提高。

1.2.3 优化SQL语句
  SQL语句的优化牵涉到很多数据库的知识,需要与索引配合,因此需要DBA对代码中的SQL进行检查测试。常见的,select *不提倡使用,效率极差,建议显式获取列,即使是所有字段也应罗列,而取总数时使用count(*),为提高cache的命中率,尽量做到SQL重用。对于大数据量的查询,可以充分利用Oracle数据库的特性,每次取出m-n行的数据,实现分页查询。另外,提高性能的好选择可能就是把所有的字符数据都保存为Unicode,Java以Unicode形式处理所有数据,因此,数据库驱动程序不必再执行转换过程。

1.3 Web代码调优
1.3.1 HttpSession的使用
  应用服务器保存很多会话时,容易造成内存不足,所以尽量减少session的使用,放置session
里的对象不应该是大对象,最好是简单小对象,实现串行化接口。当会话不再需要时,应当及时调用invalidate()方法清除会话。而当某个变量不需要时,及时调用removeAttribute()方法清除变量。请勿将EJB对象放置在session中。

1.3.2 JSP代码调优
  目前,在JSP页面中引入外部资源的方法主要有两种:include指令,以及include动作。 include指令:例如<%@ include file="copyright.html" %>,该指令在编译时引入指定的资源。在编译之前,带有include指令的页面和指定的资源被合并成一个文件。被引用的外部资源在编译时就确定,比运行时才确定资源更高效。
include动作:例如<jsp:include page="copyright.jsp" />。该动作引入指定页面执行后生成的结果。由于它在运行时完成,因此对输出结果的控制更加灵活。但是,只有当被引用的内容频繁地改变时,或者在对主页面的请求没有出现之前,被引用的页面无法确定时,使用include动作才合算。

  对于那些无需跟踪会话状态的jsp,关闭自动创建的会话可以节省一些资源。使用如下page指令: <%@ page session="false"%> ;尽量不要将JSP页面定义为单线程,应设置为<%@page isThreadSafe=”true”%>;在JSP页面最好使用输出缓存功能,如: <%@page buffer="32kb"%>;尽量用wl:cache定制标记来缓存静态或相对静态的内容,缓存jsp:include操作的结果能显著提高应用程序的运行性能。

1.3.3 Servlet代码调优
  Servlet代码调优比较简单:在Servlet之间跳转时,forward比sendRedirect更有效;设置 HttpServletResponse 缓冲区,如:response.setBufferSize(20000);在init()方法里缓存静态数据,而在destroy()中释放它;建议在 Servlet里使用ServletOutputStream输出图片等对象;避免在Servlet和Jsp中定界事务等。

1.4 JMS代码调优
1.4.1 注意必要的事项,避免使用不必要的特征
  JMS提供了强有力的消息处理机制,但是为了最大限度的提高JMS系统的性能,应避免使用不需要使用的特征,同时也要注意必要的事项。比如:尽量使用接收程序能直接使用的最简单、最小的消息类型;消息选择器要尽可能简单(最好不使用),尽量不要使用复杂的操作符,如like、in或者between 等,使用字符串数据类型的速度最慢;务必为特定的应用程序定义特定的JMS连接工厂,并且禁用默认的JMS连接工厂;不要在javax.*与 weblogic.*的名字空间中使用JNDI名称;尽量使用异步消费者,线程不必封锁以等待消息的到达;使用完JNDI树上的资源后注意关闭。

1.4.2 消息类型的选择
  标准JMS提供了五种消息类型,而TextMessage应用最为普遍, 当发送的消息是几种原始数据类型的集合体时,最好使用MapMessage消息类型,而不要使用ObjectMessage,以便减少不同系统间的耦合。此外消息是否使用压缩要慎重考虑,压缩未必能减少消息大小。如果生产者、消费者和目的地并置在同一WebLogic Server内部,通常不使用压缩。WebLogic特有的XMLMessage能为运行于消息主体之上的消息选择器提供内嵌式支持,而且易于数据交换。因此,建议应用程序之间传送消息使用XML消息格式,而应用程序内部间传送消息使用二进制消息格式。

1.4.3 确认方式的选择和JMS事务
  使用事务性会话时,尽量使用恰当的消息确认方式:如果需求允许,使用NO_ACKKNOWLEDGE;非持久的订阅者使用 DUPS_OK_ACKNOWLEDGE或者MULTICAST_NO_ACKNOWLEDGE。而使用JTA的UserTransaction,确认方式将被忽略。在使用JMS事务时,无效的消息会导致事务的回滚,以致消息重发这样的死循环。此时,可以将无效消息发送到错误消息队列,并提交JMS事务,这将确保消息不会再次传递。

1.5 EJB代码调优
1.5.1 有效使用设计模式
  GoF 的《设计模式》为我们实现高性能、易扩展的J2EE应用提供理论保障和技术支持。而EJB作为J2EE的核心组件和技术,善用设计模式对系统性能影响很大。Service Locator 和Value Object 已为我们所熟悉,Floyd Marinescu的《EJB Design Patterns》中的Session Fa?ade、Message Fa?ade、EJB Command和Data Transfer Object等设计模式更是为我们提供设计典范:缓存对EJBHome的访问;使用门面模式,不暴露Entity Bean,用Session Bean封装Entity Bean;如果可以异步处理,则用MDB代替Session Bean;封装业务逻辑在轻量级JavaBean中;使用值对象等简单对象传递数据;不直接使用get/set方法操作Entity Bean。当然过度使用模式或者牵强套用模式也是不提倡的,总的原则就是减少网络流量,改进事务管理。

1.5.2 使用EJB和WebLogic的特性
  使用EJB和WebLogic的新特性往往能提高性能。与EJB2.0特性相关的技巧有:一个Application中使用本地接口,对于 Entity Bean肯定使用本地接口,避免远程调用的开销;使用CMP管理关系,而不是BMP,EJB2.0中CMP的性能大大改善,性能和移植性都优于BMP;使用ejbSelect进行内部查询;使用home方法进行外部查询和批处理; 数据库驱动级联删除等。

  与WebLogic特性相关的技巧有:使用自动生成主键,WebLogic为Oracle和Sqlserver两种数据库的CMP提供了自动生成主键功能,节约了Entity Bean产生主键的时间,同时设key-cache-size不小于100;WebLogic管理事务性能更好,使用容器管理,而不是Bean管理事务;WebLogic提供了为CMP动态查询和批量插入功能,对性能也有很大帮助。

1.5.3 缓存资源
  对SLSB或者MDB来说,使用setMesssageDrivenContext ()或者ejbCreate()方法缓存特定资源,在ejbRemove()方法里释放; 对SLSB或者MDB来说,使用setSessionContext()或者ejbCreate()方法缓存特定资源,在ejbRemove()方法里释放;对Entity Bean来说,使用setEntityContext ()方法缓存特定资源,在unSetEntityContext ()方法里释放。

1.5.4 如何选择和使用Entity Bean
  1. 在设计EJB时,要适当考虑EJB的粒度, 细粒度的EJB在事务管理和资源管理的开销太大,尽量创建粗粒度的 EJB , 不要太粗,粗到能满足实际需求就可以;

  2. Entity Bean不是唯一方式,如果只有一个很小的数据子集被经常改变,建议采用JDO;

  3. 在操作大数据量的时候,直接采用JDBC比Entity Bean更有效;

  4. 避免采用返回很大数据组的finder方法,如 FindAll() 方法,因为它的实现代价太大;

  5. 考虑设置域组field groups,减少没有必要并昂贵的属性加载,如BLOB;

  6. 对于EJB1.1或者BMP,可以设置is-modified-method-name属性,根据isModified()的值来判断是否调用ejbStore()等方法,减少没有必要运算;

  7. 避免连接多个表创建BMP,可以使用视图,存储过程或者O/R Mapping等方式。

1.5.5 其他的一些小技巧
  1. 考虑使用 javax.ejb.SessionSynchronization 接口,提供在Rollback之后恢复数据的方法: afterBegin(), beforeCompletion(), afterCompletion();
  2. 使用完SFSB之后,调用remove()方法释放实例;
  3. 假如你不需要EJB服务的时候,建议使用普通Java类;
  4. 避免EJB之间相互调用;
  5. 使用多读模式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值