1. 概述
本次的性能优化主要是针对windows平台开展优化。
建议:如果系统可以替换成64位的系统,最好安装64位系统。这样可以避免jdk在32位条件下的内存使用限制。
2. 系统运行环境
2.1. 应用系统环境
应用系统环境是指具体部署的应用的一些优化配置措施:
1、 检查proxool.xml配置
属性名 |
描述 |
初始值 |
最终值 |
house-keeping-sleep-time |
保留线程处于睡眠状态的最长时间 |
90000 |
90000 |
simultaneous-build-throttle |
可一次建立的最大连接数 |
10 |
200 |
prototype-count |
连接池中可用的连接数量 |
5 |
5 |
maximum-connection-count |
最大的数据库连接数 |
30 |
400 |
minimum-connection-count |
最小的数据库连接数 |
10 |
10 |
2、 禁用平台提供的日志记录功能
3. tomcat应用服务器
1、tomcat启动参数优化,检查是否设置java_opts,参数是否起作用
2、对tomcat容器自身参数的优化,通过调整参数达到性能优化。
属性名 |
描述 |
初始值 |
最终值 |
maxThread |
可创建的最大的线程数,每一个线程处理一个请求 |
|
|
minSpareThreads |
最小备用线程数,tomcat启动时的初始化的线程数 |
|
|
maxSpareThread |
最大备用线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程; |
|
|
acceptCount |
指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,就是被排队的请求数,超过这个数的请求将拒绝连接 |
|
|
disableUploadTimeout |
上传时是否使用超时机制 |
|
|
enableLookup |
禁用反查域名,为了提高处理能力,应设置为false |
|
|
connnectionTimeout |
网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒 |
|
|
keepAliveTimeout |
长连接最大保持时间(毫秒)。此处为15秒 |
|
|
maxKeepAliveRequests |
最大长连接个数(1表示禁用,-1表示不限制个数,默认100个。一般设置在100~200之间) |
|
|
参考配置如下:
4. 前台代码优化
该步骤未优化到温州项目上,可以作为备选方案。
4.1. 压缩请求响应数据,节约网络带宽
前面介绍的压缩是去除脚本的注释和换行,这只是初步的压缩。而现在的主流浏览器都支持GZIP压缩,通过设置GZIP压缩,可以减小HTTP响应页面数据的大小可以节省HTTP响应时间。从HTTP/1.1开始,大部分浏览器都默认支持HTTP请求中有Accept-Encoding文件头的压缩格式,如:Accept-Encoding: GZIP, DEFAULT。如果服务器在请求的文件头中检测到上面的Accept-Encoding: GZIP,,就会以客户端列出的方式压缩响应传输的内容。然后Web服务器把压缩方式通过响应文件头中的Content-Encoding来返回给浏览器。GZIP大概可以减少70%的响应数据大小。GZIP可以对多种格式的数据进行压缩。
GZIP压缩的实现方式有多种,有些服务器支持GZIP压缩,可以通过简单的配置实现数据的压缩,也可以通过自己写一个过滤器,在web.xml注册,拦截响应的请求。
Ø 在tomcat服务器的server.xml文件中配置GZIP压缩
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla,traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,application/json" /> |
Ø 下面简要介绍拦截器实现GZIP压缩,主要代码如下:
/** * 判断浏览器是否支持GZIP * @param request * @return */ private static boolean isGZipEncoding(HttpServletRequest request){ boolean flag=false; String encoding=request.getHeader("Accept-Encoding"); if(encoding!=null&&encoding.indexOf("gzip")!=-1){ flag=true; } return flag; } /** * Gzip压缩过滤的实现方法 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse resp = (HttpServletResponse) response; HttpServletRequest req=(HttpServletRequest)request; //如果请求的浏览器支持压缩算法,则对response的数据进行压缩,否则不压缩 if(isGZipEncoding(req)){ Wrapper wrapper = new Wrapper(resp); chain.doFilter(request, wrapper); //压缩响应的数据 byte[] gzipData = gzip(wrapper.getResponseData()); resp.addHeader("Content-Encoding", "gzip"); resp.setContentLength(gzipData.length); ServletOutputStream output = response.getOutputStream(); output.write(gzipData); output.flush(); } else { chain.doFilter(request, response); } } |
Web.xml配置如下:
<filter> <filter-name>ecsideExport</filter-name> <filter-class>com.linewell.ucap.filter.GZipFilter</filter-class> </filter> <filter-mapping> <filter-name>ecsideExport</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ecsideExport</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ecsideExport</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping> |
压缩的效果如下图:
5. java代码优化
5.1. 原理
1) 使用PreparedStatement代替Statement。
Ø 推荐的写法:
Ø 不推荐的写法:
Ø 原因分析:
第一种方法使用的是预编译语句,每一种数据库都会尽最大努力对预编译语句提供最大的性能优化。因为预编译语句有可能被重复调用,所以数据库本身会对使用频繁的预编译语句进行缓存,下次调用时只要传入参数,预编译语句就能执行,而不需重新编译。而第二种方法,每次都需要对sql语句重新编译,然后才能执行。相比之下,显然第一种方法的效率更高。
ps:使用PreparedStatement还可以防止sql注入,提高应用程序的安全性。不过这不属于本次性能专题讨论的范畴,大家如果有兴趣可以自己深入学习。
5.2. 优化内容
1、 改造平台登录代码,把涉及的数据库查询操作修改为 PreparedStatement绑定变量的方式。
2、 修改首页加载涉及的查询代码。
3、 修改办件、事项、字典的常用查询语句。
6. 数据库优化
6.1. 概述
本次数据库优化主要从oracle参数、建立表索引、优化sql这个3个方面入手,优化主要流程如下:
1、 对应用进行压力测试
2、 查看压力测试后的oracle性能报告。
3、 根据性能报告调整优化基本参数,主要是sga,pga,process,session。
4、 梳理出需要优化的功能列表,然后找出涉及的sql语句,对语句进行优化。
5、 然后查找sql语句执行效率、占用cpu最差的语句、执行、读取磁盘和读取缓冲区的次数,进行优化。
6、 检查系统基础功能(用户、部门、权限、字典等)的表是否有建立主键和索引。
6.2. oracle基础
6.2.1. 查询当前用户连接数据库游标使用情况
select * from v$open_cursor t where t.USER_NAME in ('WZ_WAS','WZ_UCAP') -- and t.SQL_TEXT like 'SELECT * FROM UCAP_USER%'
select * from v$sql_shared_cursor t where t.SQL_ID='3nf9j2t694dv0'
select * from v$sql t where t.SQL_TEXT like 'SELECT * FROM UCAP_USER%'
select sql_id,child_number,sql_text,parse_calls,plan_hash_value,loads from v$sql t where t.SQL_TEXT like 'SELECT * FROM UCAP_USER%'
6.2.2. 检查占用CPU时间比较长的sql语句
select sql_text,cpu_time from v$sql where cpu_time >1e7 order by cpu_time
6.2.3. 查看sql语句执行、读取磁盘和读取缓冲区的次数
Select SQL_TEXT,EXECUTIONS,DISK_READS,COMMAND_TYPE,OPTIMIZER_MODE, SHARABLE_MEM,BUFFER_GETS from v$sqlarea ;
EXECUTIONS:执行次数
DISK_READS:读盘次数
COMMAND_TYPE:命令类型(3:select,2:insert;6:update;7delete;47:pl/sql程序单元)
OPTIMIZER_MODE:优化方式
SQL_TEXT:Sql语句
SHARABLE_MEM:占用shared pool的内存多少
BUFFER_GETS:读取缓冲区的次数
http://klygit.iteye.com/blog/564098
6.2.4. 查看process,session的使用情况
SELECT resource_name,
current_utilization,
max_utilization,
LIMIT,
ROUND (max_utilization / LIMIT * 100) || '%' rate
FROM (SELECT resource_name,
current_utilization,
max_utilization,
TO_NUMBER (initial_allocation) LIMIT
FROM v$resource_limit
WHERE resource_name IN ('processes', 'sessions')
AND max_utilization > 0);
6.2.5. 执行效率最差的10条sql语句
SELECT * FROM ( SELECT PARSING_USER_ID EXECUTIONS,SORTS,
COMMAND_TYPE, DISK_READS, sql_text FROM v$sqlarea
ORDER BY disk_reads DESC) WHERE ROWNUM<10 ;
6.2.6. 重建表空间的索引
create or replace procedure p_rebuild_all_index(tablespace_name in varchar2) as |
6.3. 优化内容
6.3.1. 创建索引
create index INDEX_ADVANCEINFO_RECEIVEDEPT on APAS_ADVANCEINFO (RECEIVE_DEPTUNID);
create index INDEX_APAS_INFO_DEPTID on APAS_INFO (DEPTID);
create index INDEX_APAS_INFO_SERVICEID on APAS_INFO (SERVICEID);
create index INDEX_ADVANCEINFO_DEPTNAME on APAS_ADVANCEINFO (RECEIVE_DEPTNAME);
create index INDEX_APAS_INFO_RECEIVE_DEPTID on APAS_INFO (RECEIVE_DEPTID);
create index INDEX_ADVANCEINFO_CREATEUSERID on APAS_ADVANCEINFO (CREATEUSERID);
create index IDX_NODE_TRANS0 on UCAP_FW_FLOW_INSTANCE (INSTANCE_NODE_TRANSACTOR_0);
6.3.2. 修改视图配置
主要是在增加索引的列上,去除like的查询,如
AND RECEIVE_DEPTID like '%${RECEIVE_DEPTID}%'修改为
AND RECEIVE_DEPTID = '${RECEIVE_DEPTID}' 或者
AND RECEIVE_DEPTID like '${RECEIVE_DEPTID}%'
这样才能使用索引
所以如果发现其他视图中,有存在索引列上有like语句,请参看如上修改
对涉及的常用功能模块,检查视图配置。
6.3.3. 修改oracle参数
6.3.3.1. 调整 process,sessions参数
通过如下语句可以查看当前设置值和系统曾经达到的最高指。
SELECT resource_name,
current_utilization,
max_utilization,
LIMIT,
ROUND (max_utilization / LIMIT * 100) || '%' rate
FROM (SELECT resource_name,
current_utilization,
max_utilization,
TO_NUMBER (initial_allocation) LIMIT
FROM v$resource_limit
WHERE resource_name IN ('processes', 'sessions')
AND max_utilization > 0);
Oracle的sessions和processes的关系是
sessions=1.1*processes + 5
步骤:
alter system set processes=1000 scope = spfile;
alter system set sessions=1105;
重启数据库。
6.3.3.2. 调整oracle的sga,pga大小
6.3.3.3. Sql优化
通过查找sql执行效率最差、读取磁盘最多,占用cpu最长的sql进行优化;主要优化的放心是查找该语句是否使用索引。