性能调优总结
1 性能调优的目的
目的:使系统达到以下三个标准
高可用:通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的可用性
高可靠:产品在规定的条件下,在规定的时间内完成规定的功能的能力
可拓展:易于扩大规模,尤其是具有良好的水平扩展能力,处理能力与机器数量呈线性关系
2 监控篇(ps:tongweb自带jvm监控)
1.1 jps使用步骤(前提 hostname -i 可以看到准确的ip)
- 参数 -l: 返回java进程全路径
-q: 仅显示进程ID
-v: 返回JVM参数,比如堆大小
- jps连接远程主机,需要开启jstat
①进入jdk的bin目录下,新建jstatd.all.policy文件,内容如下:
grant codebase “file:${java.home}/…/lib/tools.jar” {
permission java.security.AllPermission;
};
②然后在远程机器上启动,jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.r.server.hostname=[ip]
③使用jps ip 访问远程jvm
或者用jvisualVM
④如何确定jvm端口,在远程主机上ps 查询pid与端口
1.2 jstat使用步骤
class: 用于查看类加载情况的统计
compiler:用户查看HotSpot中即时编译情况的统计
gc: 用于查看JVM中堆的垃圾收集情况的统计
gccapacity:用户查看新生代 老生代的存储容量情况
gccause:最后一次及当前正在发生垃圾收集的原因
genew:用于查看新生代垃圾收集的情况
gcnewcaoacity:用户查看新生代的存储容量情况
gcold:用于查看老生代及持久代发生GC的情况
gcoldcapacity:用户查看老生代的容量
gcpermcapacity:用于查看持久代的容量
Printcompilation HotSpot:编译方法的统计
gcutil:GC统计
outputOptions:代表输出格式,参数interval和count代表查询间隔和查询次数
Loaded:加载类的数目
Bytes:加载类的Size,单位为Byte
Time:加载和卸载类花费的时间
Unloaded:卸载类的数目
jstat -gccapacity -h5 [java进程号] 1000 表示每5行显示一次表头,每1秒钟刷新一次
与jps搭配使用:
jps # 查出对用端口号
jstat -class [port] # 查出类加载情况
jstat开启远程连接在jps步骤
1.3 jmap 使用
分析堆内存,获取堆快照
jmap -dump:format=b,file=d:\heap.hprof [pid] # 生成特定的堆快照
堆快照需要特定的工具,可以用jvisualvm打开;
内存溢出往往是因为大对象没有回收造成的,大对象往往都是集合对象,可以在【实例数】中排序寻找大对象,分析内存溢出的方法。
1.4 jvisualvm使用
使用tomcat:
tomcat中修改catainal.sh(win下是bat),在头中添加如下内容:
JAVA_OPTS="
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8184
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false"
然后在jvisualvm中添加远程jmx
可以看到主页显示了jvm的cpu利用率,堆与非堆内存使用情况,加载了对少类,有多少线程数,还可以做dump操作,查看堆
内存详细。便于分析jvm状态。
可以对线程进行dump,然后分析当前的线程栈信息,通过这些信息来定位到程序问题。
2 性能分析篇
2.1 性能分析方法
自底向上:通过监控硬件及操作系统性能指标来分析性能问题。
自顶向下:通过生成负载来观察被测试的系统性能,比如响应时间/吞吐量,然后由请求起点开始向下分析。
2.2 单机性能分析与调优
常见的系统架构大体分为三部分 web服务 中间件 db
服务运行在中间件上,中间件和db运行在操作系统上,操作系统运行在硬件设施上。
2.3 性能分析流程
①
Client:客户浏览器,比如Chrome等访问WEB页面
Load Machine:生成负载的机器,即我们的压测机器用来模拟用户负载
②
Web Server:提供Web服务的服务器,即我们访问的Web页面由此中间件提供服务,比如Nginx等
Middlerware:中间件,比如Tomcat jboss webLogical等
OS:操作系统
System Resource:系统硬件资源
③
App Server:应用服务,实现业务逻辑,比如生成统计
DB:数据库
分别对应的调优参数:
①
RT:响应时间,一个业务逻辑的完成时间
TPS:每秒完成的事务数
CPU:CPU性能指标,比如cpu利用率/负载
Mem:内存性能指标,比如可用物理内存/虚拟内存使用率
Diks:Disk性能指标,比如Disk Time io等待
Network: 网络指标
②
Tcp Connections:指TCP连接数,可以用netstat命令统计得到
Thread Pool:建建建建立的线程池,监控线程状态
JVM: JVM性能指标,比如GC情况,heap使用情况。
Load Average: CPU负载队列长度
③
DB Connections: 中间件与数据库之间建立的连接数及链接状态
④
DB Time:消耗在数据库操作上的CPU时间
TOP SQL:按内存占用有多到少排序SQL,按CPU占用由多到少排序sql
PGA/SGA内存使用情况
2.4 系统性能关注点
-
CPU利用率高:
① 计算量大:连接查询/运算
② IO等待/资源争用
③ 过多的系统调用,比如写日志
④ 过多的线程打断任务,比如卡住线程等待用户输入 -
内存吃紧:
① 过多的缓存 : 加内存,分布式
② 内存泄漏 -
磁盘繁忙 SSD磁盘基本不存在这种情况,但仍需注意
-
网络流量大 暂不关注
-
操作系统 ① 系统负载:建议CPU在70%以下
② 操作系统为了安全,限制了外部的TCP建立,需要修改该限制
③ 缓存,用来提高IO -
数据库 ① 优化业务过程,尽量减少数据请求,不管是读还是写
② 优化SQL语句提高效率处理方法:
① 预处理,比如物化 多维数据,先把数据放在后台统计,生成一个较小的数据集,然后程序对
物化后的数据进行访问来减小系统压力,比如lucene
② 分而治之,并行查询
③ 优化SQL语句提高效率经常遇到的问题
① 慢查询
② 大事务
③ 死锁
④ DB Time高
⑤ 磁盘IO等待时间
⑥ 对于一些热点数据,可以置入内存中,如果国产化平台不支持,可以使用Hibernate的二级缓存 -
中间件
JVM:
① 避免频繁的FULL GC
② 查看线程,主要关注blocked的线程,长时间blocked可能造成死锁
③ 中间件在接收用户请求时为了节省建立连接 销毁链接的资源消耗,需要监控其使用情况,当超过
一定使用率的时候,考虑加大连接池
④ 数据库连接池同上 -
Web Server
前端关注的问题如下:
① 页面Size:动态数据 CSS JS 图片等的大小
② 隐藏的无用的数据传输优化: ① 页面静态化 ② 减小页面Size 图片变小 CSS合并 JS精简 压缩页面 客户端缓存图片 样式 JS ③ 砍掉无用请求,无用数据传输 ④ 对数据做异步处理,提高用户体验
-
程序优化
① 表单压缩,减少http
② 局部刷新
③ 仅取所需
④ 不做多余的调用,逻辑清晰
⑤ 谨慎继承,减少大对象的产生
⑥ 程序算法优化,比如二分法
⑦ 批处理
⑧ 延迟加载,只提供主表内容,在点击查看详细再去查询
⑨ 防止内存泄漏,记得对过期登陆做处理,给缓存做策略
⑩ 减少大对象引用,减少堆空间的占用 -
防止争用死锁
-
尽量利用索引
-
内存分配,在操作数据库的时候避免冲击内存底限,对大数据不提供order by 操作,防止PGA区域占满,
即使允许排序,也要限定查询条件来减小数据集的范围。 -
并行:使用多个进程或者线程来处理任务,比如并行查询和tomcat线程池
-
异步 MQ解耦系统关系,减少阻塞
-
使用设计模式优化程序,比如回调来减少阻塞,使用监听器来解耦依赖
-
使用合适的IO模式,比如NIO AIO等
3 配置优化
JVM配置优化 合理分配堆和非堆的内存,配置合适的内存回收算法
连接池 数据库连接池可以节省建立连接和关闭链接的资源消耗
线程池 一般是在中间件进行配置
缓存机制 目的:减少DB
数据库连接池配置:
原则:按需分配
公式:没有具体的公式进行计算,可以通过测试来估算,但是要小于中间件的线程池数量
线程池优化:
没有线程池表现:1 cpu使用不高,用户感觉响应时间很长(代码瓶颈或者线程池开少了)
2 cpu使用很高,用户感觉响应时间很长(可能硬件资源不够,可能死锁)
如果server请求cpu耗时20ms,数据库处理耗时40ms,那么总耗时就是60ms,这时候cpu就有40ms的空闲,
这时就能多处理两个任务。
服务器最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu)* CPU数量
同一个系统而言,支持的线程数越多,TPS越高,TPS越大,系统越繁忙,响应时间也会增大
3.1DB优化
3.1.1 MYSQL调优
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; # 查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; # 查看等待锁的事务
- 数据量小的情况下,对索引进行分析重建,具体请看数据库索引介绍
- 将数据保存在innodb_buffer_pool_size中,减少磁盘IO
innodb_buffer_pool_size 中包含 数据缓存 索引缓存 缓冲数据 内部结构;
- 查询innodb_buffer_pool_size大小
- 配置Innodb_buffer_pool_size的大小
innodb_buffer_pool_size默认大小为128M。最大值取决于CPU的架构。在32-bit平台上,最大值为2^32 -1 ,在64-bit平台上最大值为2^64-1。当缓冲池大小大于1G时,将innodb_buffer_pool_instances设置大于1的值可以提高服务器的可扩展性。
大的缓冲池可以减小多次磁盘I/O访问相同的表数据。在专用数据库服务器上,可以将缓冲池大小设置为服务器物理内存的80%。
下图所示的值是允许在不重启服务器的情况下调整缓冲池的大小(一般去修改ini文件)。
innodb_buffer_pool_size = innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances #是会自动调节的