WebLogic优化经验谈.docx
- 文档编号:11093139
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:12
- 大小:32.99KB
WebLogic优化经验谈.docx
《WebLogic优化经验谈.docx》由会员分享,可在线阅读,更多相关《WebLogic优化经验谈.docx(12页珍藏版)》请在冰豆网上搜索。
WebLogic优化经验谈
WebLogic优化经验谈
本文从J2EE应用架构来分别剖析系统调优,首先我们一般会从应用程序出发,去审核代码,做到代码级的优化,然后再调整应用服务器(BEAWebLogic8.1)和数据库(Oracle9i)的参数,最后当然是调整操作系统和网络的性能(包括硬件升级)。
诚然,在我遇到的很多项目中,都是出现了性能问题后才想到调优,而且一般都是先进行系统参数调整,实在解决不了才会对代码进行检查.实际上,我们应当将代码级的调优放在应用设计时来做,测试生产时修改代码将是一件极其痛苦的事情。
第一章应用程序调优
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中就大量使用了池:
JDBCConnectionPool、SocketPool、ObjectPool和ThreadPool。
I/O操作中,buffer是必须的,特别是对大文件的操作,不然容易造成内存溢出。
字节操作最快,所以尽可能采用write(byte[]),BufferedFileOutputStream比BufferedFileWriter要快,因为FileWriter需要Unicode到Byte的转换。
而后面讲到的JDBC、JSP、EJB和JMS我们都非常建议使用buffer和cache。
为HttpServletResponse设置buffersize,使用wl-cache,缓存在JNDI树上获取的对象等等。
此外,使用JDK1.4的非阻塞I/O对性能也有很大提高。
1.2JDBC代码调优
1.2.1严格资源使用
JDBC代码调优最大的原则就是使用WebLogic的连接池,而不是自己直连数据库。
在我接触的很多自己实现连接池的项目中,大部分遇到死锁和连接泄漏的问题,最后得不得修改代码。
而WebLogic提供了功能强大,性能良好的数据库连接池,我们要做的只是封装一个连接管理类,从JNDI树上获取数据源并缓存,得到连接,并提供一系列关闭数据库资源的方法。
对任何资源使用的原则是用完即关,不管是数据库资源、上下文环境,还是文件。
数据库资源的泄漏极易造成内存泄漏,乃至系统崩溃。
在使用完数据库资源后依次关闭ResultSet,Statement和Connection,而在一个数据库连接多次进行数据库操作时要特别注意ResultSet和Statement依次关闭。
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.3Web代码调优
1.3.1HttpSession的使用
应用服务器保存很多会话时,容易造成内存不足,所以尽量减少session的使用,放置session
里的对象不应该是大对象,最好是简单小对象,实现串行化接口。
当会话不再需要时,应当及时调用invalidate()方法清除会话。
而当某个变量不需要时,及时调用removeAttribute()方法清除变量。
请勿将EJB对象放置在session中。
1.3.2JSP代码调优
目前,在JSP页面中引入外部资源的方法主要有两种:
include指令,以及include动作。
include指令:
例如<%@includefile="copyright.html"%>,该指令在编译时引入指定的资源。
在编译之前,带有include指令的页面和指定的资源被合并成一个文件。
被引用的外部资源在编译时就确定,比运行时才确定资源更高效。
include动作:
例如 includepage="copyright.jsp"/>。 该动作引入指定页面执行后生成的结果。 由于它在运行时完成,因此对输出结果的控制更加灵活。 但是,只有当被引用的内容频繁地改变时,或者在对主页面的请求没有出现之前,被引用的页面无法确定时,使用include动作才合算。 对于那些无需跟踪会话状态的jsp,关闭自动创建的会话可以节省一些资源。 使用如下page指令: <%@pagesession="false"%>;尽量不要将JSP页面定义为单线程,应设置为<%@pageisThreadSafe=”true”%>;在JSP页面最好使用输出缓存功能,如: <%@pagebuffer="32kb"%>;尽量用wl: cache定制标记来缓存静态或相对静态的内容,缓存jsp: include操作的结果能显著提高应用程序的运行性能。 1.3.3Servlet代码调优 Servlet代码调优比较简单: 在Servlet之间跳转时,forward比sendRedirect更有效;设置HttpServletResponse缓冲区,如: response.setBufferSize(20000);在init()方法里缓存静态数据,而在destroy()中释放它;建议在Servlet里使用ServletOutputStream输出图片等对象;避免在Servlet和Jsp中定界事务等。 1.4JMS代码调优 1.4.1注意必要的事项,避免使用不必要的特征 JMS提供了强有力的消息处理机制,但是为了最大限度的提高JMS系统的性能,应避免使用不需要使用的特征,同时也要注意必要的事项。 比如: 尽量使用接收程序能直接使用的最简单、最小的消息类型;消息选择器要尽可能简单(最好不使用),尽量不要使用复杂的操作符,如like、in或者between等,使用字符串数据类型的速度最慢;务必为特定的应用程序定义特定的JMS连接工厂,并且禁用默认的JMS连接工厂;不要在javax.*与weblogic.*的名字空间中使用JNDI名称;尽量使用异步消费者,线程不必封锁以等待消息的到达;使用完JNDI树上的资源后注意关闭。 1.4.2消息类型的选择 标准JMS提供了五种消息类型,而TextMessage应用最为普遍,当发送的消息是几种原始数据类型的集合体时,最好使用MapMessage消息类型,而不要使用ObjectMessage,以便减少不同系统间的耦合。 此外消息是否使用压缩要慎重考虑,压缩未必能减少消息大小。 如果生产者、消费者和目的地并置在同一WebLogicServer内部,通常不使用压缩。 WebLogic特有的XMLMessage能为运行于消息主体之上的消息选择器提供内嵌式支持,而且易于数据交换。 因此,建议应用程序之间传送消息使用XML消息格式,而应用程序内部间传送消息使用二进制消息格式。 1.4.3确认方式的选择和JMS事务 使用事务性会话时,尽量使用恰当的消息确认方式: 如果需求允许,使用NO_ACKKNOWLEDGE;非持久的订阅者使用DUPS_OK_ACKNOWLEDGE或者MULTICAST_NO_ACKNOWLEDGE。 而使用JTA的UserTransaction,确认方式将被忽略。 在使用JMS事务时,无效的消息会导致事务的回滚,以致消息重发这样的死循环。 此时,可以将无效消息发送到错误消息队列,并提交JMS事务,这将确保消息不会再次传递。 1.5EJB代码调优 1.5.1有效使用设计模式 GoF的《设计模式》为我们实现高性能、易扩展的J2EE应用提供理论保障和技术支持。 而EJB作为J2EE的核心组件和技术,善用设计模式对系统性能影响很大。 ServiceLocator和ValueObject已为我们所熟悉,FloydMarinescu的《EJBDesignPatterns》中的SessionFa? ade、MessageFa? ade、EJBCommand和DataTransferObject等设计模式更是为我们提供设计典范: 缓存对EJBHome的访问;使用门面模式,不暴露EntityBean,用SessionBean封装EntityBean;如果可以异步处理,则用MDB代替SessionBean;封装业务逻辑在轻量级JavaBean中;使用值对象等简单对象传递数据;不直接使用get/set方法操作EntityBean。 当然过度使用模式或者牵强套用模式也是不提倡的,总的原则就是减少网络流量,改进事务管理。 1.5.2使用EJB和WebLogic的特性 使用EJB和WebLogic的新特性往往能提高性能。 与EJB2.0特性相关的技巧有: 一个Application中使用本地接口,对于EntityBean肯定使用本地接口,避免远程调用的开销;使用CMP管理关系,而不是BMP,EJB2.0中CMP的性能大大改善,性能和移植性都优于BMP;使用ejbSelect进行内部查询;使用home方法进行外部查询和批处理;数据库驱动级联删除等。 与WebLogic特性相关的技巧有: 使用自动生成主键,WebLogic为Oracle和Sqlserver两种数据库的CMP提供了自动生成主键功能,节约了EntityBean产生主键的时间,同时设key-cache-size不小于100;WebLogic管理事务性能更好,使用容器管理,而不是Bean管理事务;WebLogic提供了为CMP动态查询和批量插入功能,对性能也有很大帮助。 1.5.3缓存资源 对SLSB或者MDB来说,使用setMesssageDrivenContext()或者ejbCreate()方法缓存特定资源,在ejbRemove()方法里释放;对SLSB或者MDB来说,使用setSessionContext()或者ejbCreate()方法缓存特定资源,在ejbRemove()方法里释放;对EntityBean来说,使用setEntityContext()方法缓存特定资源,在unSetEntityContext()方法里释放。 1.5.4如何选择和使用EntityBean 1.在设计EJB时,要适当考虑EJB的粒度,细粒度的EJB在事务管理和资源管理的开销太大,尽量创建粗粒度的EJB,不要太粗,粗到能满足实际需求就可以; 2.EntityBean不是唯一方式,如果只有一个很小的数据子集被经常改变,建议采用JDO; 3.在操作大数据量的时候,直接采用JDBC比EntityBean更有效; 4.避免采用返回很大数据组的finder方法,如FindAll()方法,因为它的实现代价太大; 5.考虑设置域组fieldgroups,减少没有必要并昂贵的属性加载,如BLOB; 6.对于EJB1.1或者BMP,可以设置is-modified-method-name属性,根据isModified()的值来判断是否调用ejbStore()等方法,减少没有必要运算; 7.避免连接多个表创建BMP,可以使用视图,存储过程或者O/RMapping等方式。 1.5.5其他的一些小技巧 1.考虑使用javax.ejb.SessionSynchronization接口,提供在Rollback之后恢复数据的方法: afterBegin(),beforeCompletion(),afterCompletion(); 2.使用完SFSB之后,调用remove()方法释放实例; 3.假如你不需要EJB服务的时候,建议使用普通Java类; 4.避免EJB之间相互调用; 5.使用多读模式。 第二章应用服务器调优 2.1JVM调优 2.1.1垃圾收集和堆大小 垃圾收集(GC)是指JVM释放Java堆中不再使用的对象所占用的内存的过程,而Java堆(Heap)是指Java应用程序对象生存的空间。 堆大小决定了GC的频度和时间。 堆越大,GC频度低,速度慢。 堆越小,GC频度高,速度快。 所以GC和堆大小是一组矛盾。 为了获取理想的Heap堆大小,需要使用-verbosegc参数(Sunjdk: -Xloggc: 分析GC的频度和时间,结合应用最大负载所需内存情况,得出堆的大小。 通常情况下,我们建议使用可用内存(除操作系统和其他应用程序占用之外的内存)70-80%,为避免堆大小调整引起的开销,设置内存堆的最小值等于最大值即: -Xms=-Xmx。 而为了防止内存溢出,建议在生产环境堆大小至少为256M(Platform至少512M),实际环境中512M~1G左右性能最佳,2G以上是不可取的,在调整内存时可能需要调整核心参数进程的允许最大内存数。 对于sun和hp的jvm,永久域太小(默认4M)也可能造成内存溢出,应增加参-XX: MaxPermSize=128m。 建议设置临时域-Xmn的大小为-Xmx的1/4~1/3,SurvivorRatio为8。 为了获得更好的性能,建议在启动文件设置WebLogic为产品模式,此时sun和hpjvmJIT引擎为-server,默认情况下打开JIT编译模式对性能也有帮助。 调整ChunkSize和ChunkPoolSize也可能对系统的吞吐量有提高。 此外还需关闭显示GC: -XX: +DisableExplicitGC。 当然在Intel平台上使用jRockit(使用参数-jrockit)无疑大大提高WebLogic性能。 2.1.2jRockit调优 jRockit支持四种垃圾收集器: 分代复制收集器、单空间并发收集器、分代并发收集器和并行收集器。 默认状态下,JRockit使用分代并发收集器。 要改变收集器,可使用-Xgc: 为得到更好的响应性能,应该使用并发垃圾回收器: -Xgc: gencon,可使用-Xms和-Xmx设置堆栈的初始大小和最大值,要设置护理域-Xns为-Xmx的10%。 而如果要得到更好的性能,应该选用并行垃圾回收器: -Xgc: parallel,由于并行垃圾回收器不使用nursery,不必设置-Xns。 如果你的线程大于100或者在linux平台下,可以尝试使用瘦线程模式: -Xthinthread,同时关闭NativeIO: -Xallocationtype: global。 jRockit还提供了强大的图形化监控工具JrockitManagementConsole。 2.2Server调优 WebLogicServer的核心组件由监听线程,套接字复用器和可执行线程的执行队列组成。 当服务器由监听线程接收到连接请求后,将对它的连接控制权交给等待接收请求的套接字复用器。 然后套接字复用器读取离开套接字的请求,并将此请求及相关安全信息或事务处理环境一起置入适当的执行队列中(一般为默认的执行队列)。 当有一个请求出现在执行队列中时,就会有一个空闲的执行线程从该队列中取走发来的该请求,并返回应答,然后等待下一次请求。 因此要提高WebLogic的性能,就必须从调整核心组件性能出发。 2.2.1尽量使用本地I/O库 WebLogicServer有两套套接字复用器: Java版和本地库。 采用小型本地库更有效,尽量激活EnableNativeIO(默认),此时UNIX默认使用CPUs+1个线程,Window下为双倍CPU。 如果系统不能加载本地库,将会抛出java.lang.UnsatisfiedLinkException,此时只能使用Java套接字复用器,可以调整socketreaders百分比,默认为33%。 该参数可以在ConsoleServerTuningConfiguration配置栏里设置。 2.2.2调整默认执行线程数 理想的默认执行线程数是由多方面的因素决定的,比如机器CPU性能、总线体系架构、I/O、操作系统的进程调度机制、JVM的线程调度机制。 WebLogic生产环境下默认的线程为25个,随着CPU个数的增加,WebLogic可以近乎线性地提高线程数。 线程数越多,花费在线程切换的时间也就越多,线程数越小,CPU可能无法得到充分利用。 为获取一个理想的线程数,需要经过反复的测试。 在测试中,可以以25*CPUs为基准进行调整。 当空闲线程较少,CPU利用率比较低时,可以适当增加线程数的大小(每五个递增)。 对于PCServer和Window2000,则最好每个CPU小于50个线程,以CPU利用率为90%左右为佳。 由于目前WebLogic执行线程没有缩小线程数的功能,所以应将参数ThreadsIncrease设置为0,同时不应改变优先级的大小。 2.2.3调整连接参数 WebLogicServer用AcceptBacklog参数规定服务器向操作系统请求的队列大小,默认值为50。 当系统重载负荷时,这个值可能过小,日志中报ConnectionRefused,导致有效连接请求遭到拒绝,此时可以提高AcceptBacklog25%直到连接拒绝错误消失。 对于Portal类型的应用,默认值往往是不够的。 LoginTimeout和SSLLoginTimeout参数表示普通连接和SSL连接的超时时间,如果客户连接被服务器中断或者SSL容量大,可以尝试增加该值。 这些参数可以在ConsoleServerTuningConfigration配置栏里找到。 2.2.4创建新的执行队列 创建新的执行队列有助于解决核心业务优先、避免交叉阻塞、死锁和长时间处理的业务等问题。 通常会将自己的执行队列和默认的执行队列设置不同的优先级,这里优先级不应设为9或者10。 定义一个新的执行队列很容易,利用ViewExcuteQueue选项中的ConfigureanewExcuteQueue链接即可定制新的执行队列。 创建新的执行队列后,用户需要为应用程序的J2EE组件配置分配策略,以便它可以找到新的队列。 举个例子: 要将servlet或jsp捆绑到一个特定的执行队列,必须替换web.xml文件项,将wl-dispatch-policy初始化参数设置为自己的执行队列名。 我们可以为一个jsp或者servlet乃至一个WEB应用设置自己的执行队列。 同时也可以为EJB设置自己的执行队列。 对于执行时间比较长的MDB,建议使用自己的执行队列。 2.3JDBC调优 2.3.1调整连接池配置 JDBCConnectionPool的调优受制于WebLogicServer线程数的设置和数据库进程数,游标的大小。 通常我们在一个线程中使用一个连接,所以连接数并不是越多越好,为避免两边的资源消耗,建议设置连接池的最大值等于或者略小于线程数。 同时为了减少新建连接的开销,将最小值和最大值设为一致。 增加StatementCacheSize对于大量使用PreparedStatement对象的应用程序很有帮助,WebLogic能够为每一个连接缓存这些对象,此值默认为10。 在保证数据库游标大小足够的前提下,可以根据需要提高StatementCacheSize。 比如当你设置连接数为25,CacheSize为10时,数据库可能需要打开25*10=250个游标。 不幸的是,当遇到与PreparedStatementCache有关的应用程序错误时,你需要将CacheSize设置为0。 尽管JDBCConnectionPool提供了很多高级参数,在开发模式下比较有用,但大部分在生产环境下不需调整。 这里建议最好不要设置测试表,同时TestReservedConnections和TestReleasedConnections也无需勾上。 当然如果你的数据库不稳定,时断时续,你就可能需要上述的参数打开。 最后提一下驱动程序类型的选择,以Oracle为例,Oracle提供thin驱动和oci驱动,从性能上来讲,oci驱动强于thin驱动,特别是大数据量的操作。 但在简单的数据库操作中,性能相差不大,随着thin驱动的不断改进,这一弱势将得到弥补。 而thin驱动的移植性明显强于oci驱动
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- WebLogic 优化 经验谈