主要从以下几个方面(tomcat优化包括jvm方向、SQL优化)总结下对于性能优化的理解 ,以及一些操作步骤。虽然代码的架构优化,也是一个能大大提升性能的方向,但是对于老项目来说,我们往往不能轻易调整整个代码的架构,而从以上三个方面切入的性价比看上去还不错。我们首先要谈tomcat优化,tomcat 也是使用了jvm的,所以jvm的优化其实也包含在tomcat优化中。sql的优化相对独立。
tomcat的性能调得好不好,我们可以参考两个指标。一个是响应速度(请求整个过程的耗时),一个是吞吐量(单位时间内系统支持的事务数TPS)。那么我们优化之前首先得有一个标准,目前的性能到底怎样,以上两个指标分别是多少。不然你优化之后也不能知道自己的优化效果。我们这里介绍使用一款基准测试工具 ApacheBench(因为不是专业做压测的,所以选择一款容易上手的).
详细的操作使用细节可以参考这里
这里复制下人家的结果分析贴下效果
>PS > ab -n 10 -c 10 http://httpbin.org/get?name=rethink"&"age=3
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking cnblogs.com (be patient).....done
Server Software: gunicorn/19.9.0 服务器类型
Server Hostname: httpbin.org 域名
Server Port: 80 web端口
Document Path: /get?name=rethink&age=3 测试的页面路径
Document Length: 280 bytes 测试的页面大小
Concurrency Level: 10 测试的并发数
Time taken for tests: 2.629 seconds 整个测试活动持续的时间
Complete requests: 10 完成的请求数量(只包含状态码==200的请求)
Failed requests: 0 失败的请求数量(包含状态码!=200的请求和超时的请求)
Non-2xx responses: 10 状态码不等于2xx的响应数
Total transferred: 5210 bytes 整个过程中的网络传输量
HTML transferred: 2800 bytes 整个过程中的HTML内容传输量
Requests per second: 3.80 [/sec] (mean) 每秒的响应请求数(QPS),数值等于 请求总数(-n)/Time taken for tests,后面括号中的mean表示这是一个平均值
Time per request: 2629.486 [ms] (mean) 用户平均请求等待时间=concurrency * timetaken * 1000 / done
Time per request: 12.893 [ms] (mean, across all concurrent requests) 每个连接请求实际运行时间的平均值
Transfer rate: 25.15 [Kbytes/sec] received 传输速率
Connection Times (ms)
min mean[+/-sd] median max
Connect: 210 216 6.1 216 229
Processing: 229 1022 658.7 1081 2181
Waiting: 229 827 558.2 866 1731
Total: 445 1238 659.4 1291 2399
Percentage of the requests served within a certain time (ms)
50% 1291 整体响应时间的分布比
66% 1507
75% 1731
80% 1949
90% 2399 表示90%的请求在1291ms内得到响应
95% 2399
98% 2399
99% 2399
100% 2399 (longest request)
整个场景中所有请求的响应情况。在场景中每个请求都有一个响应时间
其中 50% 的用户响应时间小于 1291 毫秒
80 % 的用户响应时间小于 1949 毫秒
最大的响应时间小于 2399 毫秒
以上基本就测出来某个接口的响应速度了。
接下来就是调整tomcat的参数了。首先你需要掌握虚拟机的内存结构。
这里放一张抄袭的图,不理解的可以去先学习下。
使用free 命令查看服务器当前可用内存大小。按照实际场景给 tomcat 的启动参数中配置内存参数
参数包括以下一些
堆相关参数设置
-Xms 堆初始值 -Xms4g:初始化堆内存大小为4GB。
-Xmx 堆最大可用值 -Xmx4g:堆内存最大值为4GB
-Xmn 新生代堆最大可用值 -Xmn1200m:设置年轻代大小为1200MB。增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:NewSize=n 设置年轻代大小
-Xss -Xss512k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。
-XX:NewRatio=n 设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个堆空间的1/4
-XX:SurvivorRatio=n 年轻代中Eden区与两个Survivor区的比值.注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n 设置持久(永久代/元空间)代大小 Java8中永久代的参数失效
-XX:MaxDirectMemorySize=1G:直接内存 报java.lang.OutOfMemoryError: Direct buffer memory异常可以上调这个值。
-XX:MaxTenuringThreshold=15:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论
-XX:ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。
-XX:ParallelGCThreads=8:新生代并行收集器的线程数。
收集器设置
-XX:+UseSerialGC 设置串行收集器
-XX:+UseParallelGC 设置并行收集器
-XX:+UseParalledlOldGC 设置并行年老代收集器
-XX:+UseConcMarkSweepGC 设置并发收集器
参考 通过不断调整各个参数,我们需要将性能调整至一个合理的区间,我们除了看响应时长是否有改善以外,我们也要观察jvm的内存使用情况,比如gc次数,比如停顿时间等。那么怎么知道当前jvm的各个参数呢?
jmap -heap 进程id 可以查看内存当前使用情况,各个区域内存使用占比,确定内存参数的调整方向。
jconsole 如何分析当前的gc 情况 (参考),
主要是配置tomcat 并发的线程数
1、查询哪些sql 是慢sql,通常的方法是通过开启数据库的慢sql日志,由dba统计发给各个业务线。
2、show processlist 命令 可以实时看到正在执行的sql,如果执行完了就没了
3、show profiles 也可以查到各个sql的执行时间
那么在确定好sql之后就是优化工作了
1、插入大量数据优化
load data
按照主键自增的顺序导入
先关闭唯一性校验,加载完后再放开
关闭自动提交事务,导入完后开启自动提价
3、order by 优化
因为索引本身是有序的,所以如果刚好是order by 索引,则能免去排序,直接返回数据即可。
order by 的顺序和索引的实际顺序要相同
多字段order by 不能一个升序一个降,要统一
4、group by优化
也会有排序,
加上order by null
5、子查询优化
原则:使用多表连接查询替换子查询
or 查询优化
要用or 则条件中的所有字段都需要有索引,不然都失效,
并且不能使用符合索引
优化方案
用union 替换or