一、操作系统调优
就 Linux 操作系统而言,为了获得最佳性能,推荐使用下列设置。
有关 Linux 调整的更多信息,需参考 Linux 供应商提供的文档。
对于操作系统的调优是需要考虑的一个方面,需要相关的人进行调整设置并测试,我这里没有做相关的预研。
一、WEBLOGIC调优
1. 调整Java虚拟机
(1) 选择合适的JVM
(2) 配置JVM垃圾回收堆
² 堆大小应设置为一个适当的值,从而使 VM 使用的最大内存量不超过可用物理 RAM 量。如果超过该值,则 OS 会开始分页,性能也会显著降低。VM 使用的内存始终多于堆大小。除了堆大小设置,还要分配内部 VM 功能、VM 之外的本地库和永久代内存(仅适用于 Sun VM:存储类和方法所需的内存)所需的内存。
² 使用分代式垃圾收集方案时,温床大小不应超过 Java 堆总大小的一半。通常情况下,堆大小的 25% 到 40% 就已足够。
² 在生产环境中,将最小堆大小和最大堆大小设置为同一值,可以避免浪费用于时常调整堆大小所需的 VM 资源。这也适用于新一代堆大小 (Sun) 或温床大小 (BEA Jrockit)。
将最小堆大小 (-Xms) 与最大堆大小 (-Xmx) 设置为相同的值,以便将垃圾收集的消耗降至最低,这是一条通用规则。 |
||
例如,从 java 命令行启动 WebLogic Server 实例时,可使用以下命令指定 HotSpot VM 堆大小值:
$ java -XX:NewSize=
建议省厅财政综合业务系统的设置:
$ java -XX:NewSize=
注:
² 需要区别的是对于JVM版本的不一样,其设置也不一。请参考以上的各参数说明来设置。
² 堆的大小一定要根据服务器硬件及实际用户访问量、系统资源利用情况、垃圾回收频率等因素综合考虑。
2. 配置产品模式
对于weblogic 有两种模式,分别为产品模式和开发模式,其主要区别在于发布部署方式和对线程数、连接池数的默认设置不一样。具体说明如下:
功能 |
开发模式 |
产品模式 |
部署 |
替换文件会自动更新 |
替换文件后不会自动更新 |
Execute Queues |
默认的执行线程为15 |
默认的执行线程为25 |
JDBC Connection Pool Capacity |
默认的容量为15 |
默认的容量为25 |
对于Execute Queues和JDBC Connection Pool Capacity如何设置一个合理的数值,需要根据实际环境测试进行调整。需要注意的是,这两个参数不是越大越好。
3. 调整性能相关的配置参数
(1) pageCheckSeconds
在weblogic中的默认设置是1, 表示WebLogic每一秒钟都针对每个JSP页面进行检查,看是否有新的版本。这在开发时是一个很好的设置,但是在生产中,如果系统有大量的JSP页面,这将会造成巨大的开销。
对于财政综合业务系统,需要把这个参数设置成“-1”。
在weblogic.xml 配置如下:
<jsp-descriptor>
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>-1</param-value>
</jsp-param>
</jsp-descriptor>
(2) servlet-reload-check-secs
在weblogic中的默认设置是1, 表示WebLogic每一秒钟都针对每个Servlet进行检查,看是否有新的版本。这在开发时是一个很好的设置,但是在生产中,如果系统有大量的servlet,这将会造成巨大的开销。
对于财政综合业务系统,需要把这个参数设置成“-1”。
在weblogic.xml 配置如下:
<container-descriptor>
<servlet-reload-check-secs>-1</servlet-reload-check-secs>
</container-descriptor>
二、WEB层
1. 修改JSP的<jsp:include> <%@include>
在我们的JSP框架里面,一个JSP需要通过<jsp:include><%@include>包含9个公用页面。其中有7个是<jsp:include>方式的,<jsp:include>这种方式对性能影响较大,然而<%@include>方式又只适合于包含静态页面。因此,在财政综合业务系统当中需要尽量的把没有用的的包含语句删除,提供JSP加载的性能。
需要删除的<jsp:include>有:
<jsp:include page="/WEB-INF/jsp/common/beforeHtml.jsp"></jsp:include>
<jsp:include page="/WEB-INF/jsp/common/bodyStart.jsp"></jsp:include>
<jsp:include page="/WEB-INF/jsp/common/bodyEnd.jsp"></jsp:include>
<jsp:include page="/WEB-INF/jsp/common/afterHtml.jsp"></jsp:include>
2. 去除innerHead.jsp的session刷新
在innerHead.jsp里写了相关刷新session 代码
<script language="javascript">
<!--
//this method refresh session for expire
function _refreshSessionForLongTime(){
var activeXObject = new ActiveXObject("Microsoft.XMLHTTP");
activeXObject.open("POST","<%=response.encodeURL("common/refreshSessionAction.do")%>",true);
activeXObject.send();
}
window.setInterval("_refreshSessionForLongTime()",25*60*1000);//25 minute
//-->
</script>
代码的功能是:每隔25分钟提交一个请求来刷新session 。然而问题是,财政综合业务系统的的页面结构由丰富的框架组成,操作一个功能就同时访问多个页面,并且所有的页面都包含了innerHead.jsp,也就是说,每个页面都会发出刷新session 的请求。这样就增加了对服务端的请求,同时降低性能。
修改的方法是:独立出一个refreshSession.jsp页面,在top框架的perspective_toolbar.jsp里包含,这样就实现了一个web窗口隔25分钟刷新一次session,防止过多的请求导致性能降低。
3. 去除innerHead.jsp的getOtherPropertyValueByUniquePropertyValue方法
innerHead.jsp有个getOtherPropertyValueByUniquePropertyValue方法,功能是根据某已知属性值获取同VO对象的其他属性值。 innerHead.jsp作为一个公共页面被所有的页面调用,并且该功能并没有在任何模块里用到,所以该功能的实现代码是冗余的,反而增加了页面解析后的文件大小,降低了性能。
4. 去除页面对selectBaseData.jsp的包含
selectBaseData.jsp 里封装了很多关于选择基础数据的目录树script接口。问题是每个相关页面都包含这个JSP,其所有的代码都作为包含JSP的一部分,然而它又非常的大,这就导致包含JSP增加了许多的冗余代码。应该改成selectBaseData.js ,每个页面调用这个JS文件为最佳。
5. 禁用Session
对于Session,应用服务器都将对其进行序列化,从而增加了系统的额外负担。如果你没有明确指定的话,每个JSP页面都会缺省地创建一个HttpSession。如果JSP页面不需要使用Session的话就用以下标识符来禁用它。
<%@ page session="false"%>
三、业务逻辑及数据操作层
1. 缓存数据权限相关的数据
数据权限的数据包括两类,一类是用户对应基础数据权限构造的目录树数据,一类是用户对应的基础数据权限数据。前者数据在生成的时候做了缓存处理,缓存期为半小时,当用户重新登入系统,缓存数据过期。后者数据没有对其进行缓存处理,因而在报表查询界面需要调用该接口,取出用户对应的基础数据权限,如果有九大基础数据,就要调用九次数据库查询,大大地增加了系统对访问数据库所带来的负担,因此现在对该接口进行缓存,缓存方案和前者一样。
2. 审批流接口优化
审批流接口是最大的性能瓶颈之一。其存在以下方面的问题。
(1) 执行一次相关审批流的查询要访问4次数据库,分别是生成查询的SQL、查询分页情况、查询审批流对应的业务单据号,根据业务单据号查询业务对象。
(2) 审批流查询要关联已启用的数据权限,而且数据权限表所拥有的数据量有100多万条。如果启用了9个数据权限,也就同时要遍历执行9次对数据权限的子查询,其带来的性能瓶颈可想而知。
(3) 为了要分页,所以必须要对审批流查询SQL执行两次,一次获取分页信息,一次返回查询结果。本来执行较慢的SQL还要执行两次,就更加增大了系统的负担。
(4) 得到相关的业务单据号以后,需要把业务单据组装成IN( )方式的子查询,如果一页查询数据量大,那查询速度明显降低。
目前已经优化的几点:
(1) 优化存储过程f_base_wk_get_task_sql的取单据项的部分。
(2) 优化存储过程f_base_wk_get_task_sql生成的查询SQL语句的查询条件。
原来的查询条件:
WHERE 1 = 1
and (A.ENTER_ID = I.ENTER_ID)
and 1 = 1
and A.ACCVOUCH_ID in
(select CHKPRO_CON_VOUID
from T_BASE_CHECKPROCESS_CONTROL
where instr(',3001,3011,3009,', ',' || CHKPOS_DEF_ID || ',') > 0
and CHKPRO_CON_VOUTYPE = '3002')
and a.ACCVOUCH_ID = z.CHKPRO_CON_VOUID
and z.CHKPRO_CON_VOUTYPE = '3002'
优化后的查询条件:
WHERE (A.ENTER_ID = I.ENTER_ID)
and 1 = 1
and A.ACCVOUCH_ID = z.chkpro_con_vouid
and CHKPRO_CON_VOUTYPE = '3002'
and instr(',3001,3011,3009,', ',' || CHKPOS_DEF_ID || ',') > 0
ORDER BY A.ACCVOUCH_ID
通过优化,比较其查询时间,大概减少了100毫秒。
对应审批流接口存在的问题还需要进一步的进行优化完善。审批流接口的性能关系到整个财政系统的性能,是其主要的性能瓶颈。所以在后期主要性能优化的工作重点就是优化审批流接口,解决其主要存在的影响性能的问题。
3. 代码质量相关
(1) 不要用”+”对String对象进行连接,一定要用StringBuffer。
(2) 当某对象使用之后,要手工的设置为NULL。
(3) 不要用System.out.println() 输出调试信息,要用Log4j相关接口。
(4) 尽量不要用in( )的方式查询数据库。
(5) 同时对多条数据对象进行操作,要用批量处理的接口(包括批量添加、修改、删除等)。
(6) 能查询一次得到结果的就查询一次,不要在循环体内调有查询语句。尽量地较少数据库的访问次数。
对应代码质量方面的性能瓶颈,需要专门排查并修改完善。
五、系统部署
1. 启用报表分机部署
目前的报表跟业务系统之间是部署在同一个应用服务器中的,往往因为报表的查询占用了应用服务器相当多的内存及CPU资源,导致业务系统与报表查询系统互相制约。经过对Weblogic性能监控发现,查询报表的同时,其占用的内存资源马上到了最大值,其占用的CPU资源也同样上升到峰值。
优化的方案是:把报表查询系统和业务系统在部署上分离出来,防止因为报表的性能造成业务系统运行的性能。
2. 启用预编译功能
因为系统经常性的发布补丁,发布补丁之后必须要清除Weblogic对JSP编译之后的缓存,访问某JSP之前要对该JSP编译,所以第一次访问的速度不容乐观。目前的解决方法是手工访问所有页面,这必然存在很多的问题:
(1) 由于个人疏忽或是偷懒现象造成不可能每个页面都能访问到。
(2) 访问页面的同时,有可能用户也在访问,这样对用户来说还是第一次访问。
(3) 在集群环境下需要对每一个节点进行手工访问才可。访问的次数随着节点数成倍增加,浪费了大量的人力。
优化的方案是:使用编译工具来实现预编译,编译的方法可参考weblogic相关文档。
六、方案补充说明
性能问题牵涉面非常的广,很多情况下并不出在环境上,跟本身的程序代码的实现方式,算法密切相关。如何编写质量高的代码,如何让算法最优,如何尽量地减少访问数据库的次数,如何优化访问数据库的SQl等,这些才是关键。它们是导致性能问题的主要瓶颈,只有保证了这些因素的最优化,然后再调整weblogic应用服务、操作系统、数据库等性能才能起到很好的效果。
对于财政综合业务系统的性能优化需要做好如下相关工作:
(1) 排查出存在性能瓶颈的代码并优化完善。
(2) 优化完善审批流及数据权限接口。
(3) 优化查询的SQL。
(4) 启用报表分机部署。(需要相关的测试工作)
(5) 启用系统预编译。(需要技术实现预研)
(6) 对于Weblogic执行线程数、连接池数,JVM参数,操作系统参数等的调整需要根据系统实际运行环境来。
对于以上几点的优化工作,需要领导协调好各项目组的资源,统一规划,制定好相关的工作计划。