赞
踩
之前也做了几次的性能优化,每次的过程好像大体上都差不多,所以就此总结一下。如果有哪里不到位的地方,欢迎及时指正。
性能优化的过程,总概括下来可以分为三个阶段:
这里我们主要对前两个部分进行展开。
无论在什么领域,监控都是流程中优化的关键。我们需要从上层下层的顺序去监控,采集到我们需要的信息,然后才能进行优化。
应用层
本层需要观察到优化的方法每一步的时间,从而逐个击破地进行优化。
需要固定的监控点位置有三种:
一般在本层我们需要两个工具:
方法监控: 观察单个方法的性能,对于优化TP50非常有用。
链路监控: 追踪偶尔性能较差的调用,对于优化TP50之上的指标比较有用。
JVM层
本层是除了应用层之外的第二关键的信息,主要包括三类信息:
这里的工具一般是通过JRE自带的jstat/jmap/jstack等命令或者第三方工具如javamelody来观察。
容器或物理机层
容器层的指标很多,一般来说我们只会观察以下三个指标:
容器层一般平台都会提供监控指标,不需要额外的工具。
这部分更多的作用是帮助我们排除掉个别异常的机器或分组,减少干扰。
对监控的分析是很重要的,但是在确定动手之前,我们仍然需要进行可能性的收集,这个有时候会给我们带来远超预期的价值。在这里我们关注两个方面:
在第一个阶段中,我们已经隐约有了一些想法,这个阶段就是要选择并验证。在这个阶段个人的经验最重要只有一点,不要设置边界。如果站在研发的视角,我们更多的关注是系统稳定性,所以有一些边界我们不愿意去做突破,但往往是这些边界限制了性能的提升程度。
业务设计优化
从上面收集的资料,最好的改进措施应该是业务设计优化,在领域驱动开发的方式中会体现的比较多,在日常中比较难以实现。如果研发能够从自己的视角提出一些建议,帮助产品和业务去做的更好,那么这就是一个双赢,既保证了系统的稳定性,也实现了业务的快速响应。
举个例子: 业务的需求是在某个一级类目上设置属性,当读取价格时,如果有这个属性,那么就需要以A的逻辑去计算返回,否则以B的逻辑去计算返回。这个问题的难点是什么? 我个人对它的理解是它突破了现有的业务模型。在当下的模型里类目属性都在四级类目上,所以对于价格系统来说很难受,商品只会给我返回末级的类目id,我还需要查询查询几次拿到一级类目,然后再去拿属性,才能进行计算。
所以我觉得理想的解法应该是末级类目设置属性,提供批量设置的功能。这样从写和读的方式都不会要求现有的业务模型结构性的改变,读和写都达到一个平衡。
为什么属性在末级类目就合理呢?
之前也有查阅很多资料,给出的原因和商品挂末级类目比较一致。我们类比类目树就像一棵树,树干只是为了细分,目的是提供一个管理的路径,而不会存储数据,树枝才是真正存储数据的地方。这个结构无论是做管理、还是用来搜索都很简单明了,所以才会被认为是一个合理的结构。归根结底,简单的设计就是最好的设计。
逻辑设计优化
这部分依赖于我们之前的方法监控和链路监控,当我们发现一个步骤比较慢的时候,就要想办法优化。根据经验,我对这里的优化方法做一个总结。包括三个类型: 并发请求的执行优化,单个请求步骤优化和存储结构变更。
并行请求的执行优化:
单个请求的步骤优化:
存储结构变更:
资源API优化
资源API的优化,往往能带来N倍的性能提升。这里个人目前的是Redis缓存,通过pipeline,可以比hmget带来4倍以上的提升。
这部分最主要的优化可以来自于公司中间件的建议或者官方的一些命令探索。
Redis的dump命令有做过一些尝试,但在我们的场景提升并不明显。从dump和hmget命令说明来比,主要时间复杂度一部分可以从Redis转移到应用,降低Redis的cpu压力。
JVM优化
因为个人的经验都来自于Java的优化,所以这里的VM就变成了JVM。
JVM的优化网上有很多,所以这里就结合个人的经验来简单的总结一下。
服务设计优化
通过对服务合适的分组也可以达到性能的优化。当然服务分组会有很多考虑,这里我们只考虑性能优化的部分。主要的区分依据来自服务组合区分和调用者分组。
服务组合区分是将流量和性能近似相同的服务单独分组,这样可以对资源进行细粒度的伸缩,降低各个服务之间的互相影响。
调用者分组是根据优先级、业务用途进行区分,这里建议提供三种分组。
核心交易分组: 请求次数、批量个数、数据范围通常都会比较小,容易命中本地缓存。
worker分组: 在这个分组可以不设置本地缓存,主要是隔离一些异常的调用。
正常服务: 除上面2个之外的分组。如果数据存在两种存储介质中,比如Redis和文件,那么还可以将正常服务进行分成两个分组,从而能够对资源得到充分的利用。
当我们确定了一个措施,如何验证这个措施有效呢?最主要的手段就是压测了。
首先我们需要建立我们的基准测试指标。这里包括未改进时的指标和资源各种API的指标。这两个API有不同的作用,一个是我们当前的状况,另一个则是我们优化的上限。
接下来就可以使用控制变量法单机验证,逐个对优化措施叠加进行压测来,验证效果。
最后我们需要灰度集群验证和线上观察。
在文章的最后也放出来个人的一些思考,欢迎大家讨论。
思考1: 在压测gravelvm之后我还是感触挺大的,竟然可以做到这么大的提升。虽然性能优化是永恒的课题,但优化的主导权是不是会一直在我们手中?
思考2: 对于监控工具的需求是无止尽的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。