分类:
2008-09-08 18:23:06
调优背景
HBCZT信息中心使用IBM X3662003运行其基于J2EE1.4技术的应用系统。另外运行一个基于COM技术的数据采集应用程序。该程序客户端读入用户填写的xls格式表格文件信息,并通过该程序将XLS内容封装成为XML并打包ZIP后发送到数据采集程序的端,服务器端接受到文件后,对该ZIP包进行解包、并对解包后的XML信息进行解析、使用SQL逐条将记录插入到数据库中。数据库连接池已经设置为20,但批量数据插入数据库的时候(数据量至少500000条记录,一般情况5000000条记录)导致数据库异常缓慢。客户希望找到系统瓶颈,并提出相应性能调优建议。
1、总体思路
硬件调优、操作系统调优,数据库调优 略!我们假设都已经是最佳状态。由于本人负责WebLogic部分的调优,所以以下思路与内容均为WebLogic方面。特此说明
J2EE应用架构环境下的系统调优,首先我们一般会从应用程序出发,去审核代码,做到代码级的优化,然后再调整应用服务器(BEA WebLogic8.1)和数据库 (9i)的参数,最后当然是调整操作系统和网络的性能(包括硬件升级)。这是一种MDA的先进做法。诚然,在这样一个政务项目中,不可能完全按照这个思路来做,我们把目标首先定位在应用系统所在的应用服务器(BEA WebLogic8.1)上,通过对BEA WebLogic8.1的参数进行设置,使WebLogic8.1能够在最优化的环境中去运行其系统,然后对ORACLE数据的参数进行优化设置,最后进行性能测试再找出导致性能瓶颈所在的SQL代码或JAVA程序,考量其修改的可行性,并进行最终问题优先级认定,与瓶颈模块进行协商解决性能问题。当然,一般情况下我见过的案例都是出现了性能问题后才想到调优,而且一般都是先进行系统参数调整,实在解决不了才会对代码进行检查.实际上,我们应当将代码级的调优放在应用设计时来做,测试生产时修改代码将是一件极其痛苦的事情。
下表为一般性J2EE性能调优的参照情况一览表,供参考。
毛病 |
描述 |
症状 |
原因或治法 |
线性内存泄漏
|
每单位(每事务、每用户等)泄漏造成内存随着时间或负载线性增长。这会随着时间或负载增长降低系统性能。只有重启才有可能恢复。 |
随着时间越来越慢 随着负载越来越慢 |
虽然可能有多种外部原因,但最典型的是与资源泄漏有关(例如,每单位数据的链表,或者没有回收的回收/增长缓冲区)。 |
指数方式内存泄漏
|
双倍增长策略的泄漏造成系统内存消耗表现为时间的指数曲线 |
随着时间越来越慢 随着负载越来越慢 |
通常是由于向集合(Vector,HashMap) 中加入永远不删除的元素造成的。 |
糟糕的编码:无限循环
|
线程在 while(true) 语句以及类似的语句里阻塞。 |
可以预见的锁定 |
您需要对循环进行大刀阔斧的删剪。 |
资源泄漏
|
JDBC 语句,CICS 事务网关连接,以及类似的东西被泄漏了,造成对 桥接层和后端系统的影响。 |
随着时间越来越慢 可以预见的锁定 突然混乱 |
通常情况下,这是由于遗漏了 finally 块,或者更简单点,就是忘记用 close() 关闭代表外部资源的对象所造成的。 |
外部瓶颈问题
|
后端或者其他外部系统(如鉴权)越来越慢,同样减缓了 J2EE 应用服务器和应用程序 |
持续缓慢 随着负载越来越慢 |
咨询专家(负责的第三方或者系统管理员),获取解决外部瓶颈问题的方法。 |
外部系统
|
J2EE 应用程序通过太大或太多的请求滥用后端系统。 |
持续缓慢 随着负载越来越慢 |
清除冗余的工作请求 ,成批处理相似的工作请求,把大的请求分解成若干个更小的请求,调整工作请求或后端系统(例如,公共查询关键字的索引)等。 |
糟糕的编码:CPU密集的组件
|
这是 J2EE 世界中常见的感冒。一些糟糕的代码或大量代码之间一次糟糕的交互,就挂起了 CPU,把吞吐速度减慢到爬行的速度。 |
持续缓慢 随着负载越来越慢 |
典型的解决方案就是数据高速缓存或者性能计数。 |
中间层问题
|
实现得很糟糕的桥接层(JDBC 驱动程序,到传统系统的 CORBA 连接),由于对数据和请求不断的排列、解除排列,从而把所有通过它的流量减慢到爬行速度。这个毛病在早期阶段很容易与外部瓶颈混淆。 |
持续缓慢 随着负载越来越慢 |
检查桥接层和外部系统的版本兼容性。如果有可能,评估不同的桥接供应商。如果重新规划架构,有可能完全不需要桥接。 |
内部资源瓶颈:过度使用或分配不足 |
内部资源(线程、放入池的对象)变得稀缺。是在正确使用的情况下加大负载时出现过度使用还是因为泄漏? |
随着负载越来越慢 零星的挂起或异常错误 |
分配不足:根据预期的最大负载提高池的最大尺寸。过度使用:请参阅外部系统的过度使用。 |
不停止的重试 |
这包括对失败请求连续的(或者在极端情况下无休止的)重试。 |
可以预见的锁定 突然混乱 |
可能就是后端系统完全宕机。在这里,可用性监控会有帮助,或者就是把尝试与成功分开。 |
线程:阻塞点 |
线程在过于积极的同步点上备份,造成交通阻塞。 |
随着负载越来越慢 零星的挂起或异常错误 可以预见的锁定 突然混乱 |
可能同步是不必要的(只要重新设计),或者比较外在的锁定策略(例如,读/写锁)也许会有帮助。 |
线程:死锁/活动锁 |
最普遍,这是您基本的“获得顺序”的问题。 |
突然混乱 |
处理选项包括:主锁,确定的获得顺序,以及银行家算法。 |
[1]