以前我以为写的代码要崩溃是件挺困难的事情,但是现在发现貌似系统瘫痪也挺常见的……
当遇到系统瘫痪,所做的办法也不过是通过Linux命令查找线上环境的性能指标,查看dump日志,然后查代码,最后定位问题。看起来是一个很简单的步骤,但是这里每一步都考验着基础和功底。 窃以为,要想做好Java性能调优,有几点是很重要的。 第一,是计算机相关的基础要足够扎实。我们需要熟悉计算机组成原理、操作系统、数据库等等基础知识。这样才有可能在纷繁复杂的系统中找到调优的点。 其次,要透过源码来熟悉技术的本质。我经常觉得,只通过技术论坛上学到的技术是不够的,那些都是生产者消化后总结的知识点。我们需要去深入源码,自己去分析学习和总结,这样才能更客观地学习一项技术,而且还要能通过源码来学习别人的思维方式。 最后,则是要善于总结。使用一项技术,不能仅仅停留在“可以用”“好用”等方面,而是要善于去追问:为什么要使用,使用对系统性能有什么提升?和其他的技术对比好处在哪?其原理又是什么?唯有在理解这些问题之后,才能在遇到性能问题的时候,及时地想到解决方案。
可能影响系统性能的因素
-
CPU
-
内存
-
磁盘IO
-
网络
-
异常
-
数据库
-
锁竞争
跟系统性能相关的指标
-
响应时间 一般响应时间可以自下而上划分为四个:数据库响应时间、服务端响应时间、网络响应时间
-
吞吐量 吞吐量一般可以自下而上地划分为两种:磁盘吞吐量和网络吞吐量 先从磁盘吞吐量说起。 磁盘性能衡量有两个关键指标: IOPS(每秒的输入输出量):指单位时间内系统能处理的I/O请求数量。关注的是随机读写性能,通常适应于随机读写频繁的应用。如果小文件存储、OLTP数据库等。 数据吞吐量:单位时间内可以成功传输的数据量。对于大量频繁的顺序读写的引用,这是个很重要的指标。茹电视台的视频编辑、视频点播等。
网络吞吐量,则是指在网络传输时,设备能够接受的最大数据速率。
-
计算机资源分配使用率 通常指CPU使用率、内存使用率、磁盘I/O、网络I/O指标
-
负载承受能力 当系统压力上升时,可以通过观察系统响应时间的上升曲线是否平缓,来判断系统所能承受的负载压力极限。
系统性能调优策略的制定
性能测试
要对性能进行调优,首先必须的便是要有性能测试。
-
微基准性能测试 微基准性能测试可以精准定位到某个模块或者某个方法的性能问题,特别适合做一个功能模块或者一个方法在不同实现方式下的性能对比。例如,对比一个方法使用同步实现和非同步实现的性能。
-
宏基准性能测试 首先看测试环境,我们需要模拟线上的真实环境。 然后看测试场景。我们需要确定在测试某个接口时,是否有其他业务接口同时也在平行运行,造成干扰。如果有,请重视,因为你一旦忽视了这种干扰,测试结果就会出现偏差。 最后看测试目标。我们的性能测试是要有目标的,这里可以通过吞吐量以及响应时间来衡量系统是否达标。
进行性能测试还需要关注一些额外的问题。 1. 热身问题。 在 Java 编程语言和环境中,为了节约内存和执行效率,代码最初被执行时,解释器会率先解释执行部分代码。随着代码被执行的次数增多,当虚拟机发现某个方法或代码块运行得特别频繁时,就会把这些代码认定为热点代码(Hot Spot Code)。 为了提高热点代码的执行效率,在运行时,虚拟机将会通过即时编译器(JIT compiler,just-in-time compiler)把这些代码编译成与本地平台相关的机器码,并进行各层次的优化,然后存储在内存中,之后每次运行代码时,直接从内存中获取即可。 2. 性能测试结果不稳定。 做性能测试的时候可能会发现,数据集是一致,但是测试结果却不一样。这是因为测试,是经常伴随很多不稳定的因素,诸如其他进程影响、网络波动、JVM垃圾回收等。我们可以通过多次测试求平均值的方式来得到一个合适的结果。
调优策略
- 优化代码
- 优化设计
- 优化算法
- 时间换空间
- 空间换时间
- 参数调优
兜底策略
- 限流
- 智能化横向扩容
- 提前扩容
未完待续……