写点什么

性能优化手记上篇之【原则】&【方法】

作者:鲸品堂
  • 2022 年 5 月 31 日
  • 本文字数:3664 字

    阅读完需:约 12 分钟

性能优化手记上篇之【原则】&【方法】

背景


性能优化是软件开发中老生常谈的话题。性能问题重在平时良好的研发规范、设计规范的约束,思想认识的提高,敬畏之心的保持。但在实际产品研发活动过程中,无论项目的大小或多或少都会遇到性能问题。即便在项目伊始我们就定义性能保障的种种规章制度,往往也会受限于人力、时间等原因,在长期的需求迭代过程中存在放松的现象,导致性能问题的爆发。


同时随着时间的流逝,系统在长期的运行过程中由于数据量、访问量不断增长,造成系统的逻辑越来越复杂、请求耗时越来越长。在此情况下一旦遇到促销活动等大并发请求时,系统瓶颈问题就会凸显。


当遇到性能问题时如果没有思路、没有方法就很容易眉毛胡子一把抓,不但不能快速定位和解决问题,还会走不少弯路甚至制造出新的问题出来。


本篇将从【原则】&【方法】两个方面与大家探讨软件开发的性能优化。


优化原则


在对系统进行性能优化时既要最大程度地避免对原有逻辑和体验的破坏,又要能够快速定位、发现问题,因此我们应遵从一定的原则开展性能优化工作。以下的优化原则是笔者从实战中总结的的指导思路。


  • 重构原则:性能优化时不能影响现有业务功能,尽可能地避免用户体验感知下降,不能影响周边系统交互,尽量基于重构思想。

  • 最优先原则:产生性能问题瓶颈的原因多种多样,往往存在多个点都可进行优化,这时我们需要分析出影响性能的最大瓶颈位置,并且作为最优先考虑优化的点。因为在其他点上的优化,往往也会受限于最大瓶颈处的限制,不能带来性能提升或者提升效果不明显。

  • 二八原则:在软件系统中造成性能问题的往往是应用中的一个小模块,因此在性能优化时不要盲目动手,应该通过工具和标准方法逐步找出瓶颈模块。性能优化要做的就是对瓶颈按优先原则确定部分目标进行优化,通过对 20%的性能问题进行处理,达到 80%的效果,不宜全部并行处理。

  • 深度还原原则:性能问题时常是在某个特定场景下才会触发,因此在进行性能优化时需要深度还原造成性能问题的场景,包括环境、配置、业务数据等各方面。通过深度还原能够加快复现性能问题,分析问题产生原因。

  • 实事求是原则:性能优化是建立在客观、实事求是的基础之上,优化时以数据为主,推理验证为辅,优化前后的所有数据准确无误且有记可查,尽量用截图或报表方式呈现。


优化方法


如果说原则是指导我们解决问题的理论基础,那么在原则之上就必须要形成行之有效的方法了。笔者在过往的性能优化工作中,基于上述原则总结了 6 种优化方法,结合实战案例,分析性能问题的真正原因,结合每种方法从现象入手,对性能问题进行剖析并予以解决。


空间换时间


空间换时间在性能优化中是使用频率最高的一种方法,它主要通过增加数据副本缩短访问路径、提升访问媒介效率、增加硬件资源等方式,以达到更快的访问效率,快速获取所需数据。具体的典型操作包括冗余数据、增加数据索引、增加本地缓存、增加分布式缓存、使用 CDN 等。在过往的项目优化中,合理地运用空间换时间方法会带来意想不到的性能提升效果。


实战案例:


  • 现象:某产品发布上线后经过一段时间的运行,管理员在管理门户上查询订单信息的操作耗时增加,影响操作体验。

  • 分析:分析订单信息查询功能,发现订单信息展示时需要展示商品名称,而商品名称与订单信息不是同一个数据库,每次都需要根据商品 ID 调用服务去查询商品名称回来。在服务调用过程中当调用的服务次数多了,开销就增加了。

  • 解决方案:根据订单信息第一屏中展示的内容,商品名称是需要通过服务调用获取的,因此采用空间换时间的方式将商品中心 g_goods 表的数据冗余一份到订单中心。当进行订单信息第一屏数据展示时,将订单中心的 o_order_item 与 g_goods 关联查询,减少中心间服务调用。

同步转异步


同步转异步方法在性能优化使用频率也比较高,该方法主要是确保业务主流程正常,将主流程以外的业务逻辑通过异步的方式进行处理。通常用在外部系统接口、消息通知、日志记录、数据统计这类场景中。


实战案例:


  • 现象:现场有个客户使用的小程序,从客户点击登录按钮到客户信息展示的时间平均需要 3S 左右,无论在业务忙时还是在业务闲时耗时都差不多。

  • 分析:对客户登录后的处理逻辑进行分析,发现展示的客户信息很多是依赖于调用外部服务返回,并且服务使用同步的方式进行调用。当一个外部服务响应不及时,则会造成客户登录后信息加载缓慢,甚至出现空白页面的情况。

  • 解决方案:从客户体验出发将客户信息进行分块,系统内的客户信息在客户登录后优先返回到前端进行渲染展示。对于调用外部服务获取客户其他信息的处理改为异步调用的方式,当外部服务返回信息后再加载到前端页面进行展示。

  • 优化后:客户登录后信息展示的耗时从 3S 提升到 0.5S。


串行转并行


串行转并行是使用计算机的并行计算结构(如多核技术、多线程技术),把多个串行执行的命令或者步骤,改为并行执行的方式。使用该方法前需要确定调整的逻辑是否有依赖关系,只有无依赖关系的操作才能使用该方式。


实战案例:


  • 现象:客户在平台上订购权益商品后,客户无法立即使用购买权益商品的手机号码登录平台使用,引发客户投诉。

  • 分析:分析客户无法立即使用权益的原因,发现是客户订购的权益商品没有立即送往对应的权益提供商进行开通导致。进一步分析发现没有及时送的原因是平台生成权益商品订购单后,需要送多个外部系统,而且是按照顺序一个个送。当其中一个系统出现问题后其它系统将被堵住,而送权益提供商的处理恰巧排在最末。

  • 解决方案:调整权益商品订购单送外部系统的处理逻辑,将现有串行送外系的操作调整为并行同步给外系统,实现权益商品购买后能够立即送往权益提供商进行开通,各业务系统之间的操作相互隔离,互不影响。


化繁为简


在项目开发过程中,为了追求功能的灵活性、可扩展性以及复用性,实际执行的处理逻辑比业务所需的处理复杂得多,使整个逻辑处理做了很多无用功,导致耗时变长。这种情况可根据业务特点进行逻辑解耦、流程拆分等,将复杂逻辑细化成简单可复用的原子组件,再使用原子组件拼装出满足业务需求的处理机制、流程。


实战案例:


  • 现象:某产品查询客户可订购商品的功能,经过两年的需求迭代,校验规则越来越多,查询效率越来越慢。

  • 分析:借助 Arthas 工具分析商品查询调用链上的每一步耗时,发现规则引擎执行耗时严重。进一步对规则引擎进行分析发现:

  1. 单个规格执行耗时很短,只需十几毫秒,但存在 300 多个规则,导致总体规则执行经常超过 4S;

  2. 每次请求都重新生成了多个规则引擎对象,导致规则对象内存占用高达几 G,从而频繁触发 FullGC;

  3. 业务逻辑对执行的规则缺少细分,所有规则都会执行。

  • 解决方案:通过优化规则执行方法:

  1. 梳理出简单规则,简单规则不使用规则引擎 engine.eval,改为直接比较法进行判断;

  2. 创建规则引擎池 JsScriptEnginePool,减少规则引擎重复创建;

  3. 业务规则增加状态,只检索有效的规则进行执行。

  • 优化前:10 个并发, tps 在 1.6 左右,请求平均耗时 7.5s(再增加并发量就大面积请求异常)。

  • 优化后:100 并发用户时,平均 tps 为 102,请求平均耗时在 1s 内。


化整为零


将系统压力大的点通过分散压力的方式实现性能提升。数据层面通常是将冷热数据分离、分库分表的方式进行分解压力;服务访问层面通常是扩充应用服务器、调整负载均衡和路由规则等方式平衡服务请求。


实战案例:


  • 现象:某项目近两年的业务发展较快,每天新增订单大约 6W。客户在进行订单查询时耗时越来越长,每次查询耗时达到 3S 以上。

  • 分析:分析订单查询功能发现耗时长的主要原因是订单的数据量多,造成查询语句执行效率低。对业务场景进行分析发现 1~2 个月内的数据访问率在 92%以上,3~6 个月的数据访问率在 7%左右,超过 6 个月的数据访问率在 1%以下。

  • 解决方案:根据分析结果对订单表 oi_order_item 进行瘦身,新增 his_oi_order_item 表用来存放超过半年的数据。同时对 his_oi_order_item 表的数据访问提供新服务。通过将订单表 oi_order_item 的数据化整为零,大幅提升订单查询效率,数据库压力下降明显。订单查询耗时从原来 3S 下降到 0.5S。


参数调优


在应用中会包含大量的配置参数,其中有操作系统参数、运行环境参数、数据库参数、开源组件参数等等。在过往的性能问题优化中发现,有时只是对这些参数按照项目特性进行合理配置,就能达到理想的效果。


实战案例:


  • 现象:系统在已经上线运行超过半年,一直存在操作卡顿的现象,业务高峰期甚至 5 分钟就出现一次。

  • 分析:通过分析系统出现卡顿时的应用状态,发现 rights-intf 应用在卡顿时所有的线程都出现响应不及时的情况,并且 rights-intf 应用也在频繁触发 FullGC 操作。在业务高峰期每 5 分钟触发一次 FullGC。每次 FullGC 后老年代内存使用率从 98%左右下降到 50%左右。

  • 解决方案:根据分析结果倒推,怀疑 rights-intf 应用的 JVM Xms 和 Xmx 设置太小,导致频繁触发 FullGC 操作。检查 rights-intf 应用的 JVM Xms 和 Xmx 配置的为 1G。将 1G 改为 3G 后观察 rights-intf 应用未发生 FullGC 操作,系统运行平稳,卡顿现象消失。


小结


在项目建设过程中性能优化往往作为一种事后补救手段,在处理时常常面临着时间紧、分析定位困难、改造难度大,且容易造成客户投诉等问题,因此性能问题重点在于日常工作的关注,功能设计时提前考虑,开发过程中提前规避,测试和运营时提前发现。

发布于: 刚刚阅读数: 3
用户头像

鲸品堂

关注

全球领先的数字化转型专家 2021.03.16 加入

鲸品堂专栏,一方面将浩鲸精品产品背后的领先技术,进行总结沉淀,内外传播,用产品和技术助力通信行业的发展;另一方面发表浩鲸专家观点,品读行业、品读市场、品读趋势,脑力激荡,用远见和创新推动通信行业变革。

评论

发布
暂无评论
性能优化手记上篇之【原则】&【方法】_鲸品堂_InfoQ写作社区