为什么要做接口性能优化
想象一下以下几个场景:
我们在获取一个用户详情接口时,刷了无数次,浏览器就在那转圈,硬是刷不出来,打开控制台,显示接口超时假如我们服务A有个批量发营销短信的任务,服务A用批量的userid调服务B的用户服务以获取用户的手机号,从而完成短信发送功能。奈何服务B的通过userid接口获取用户详情的接口平均响应500ms以上,且接口请求量增大时,接口耗时明显上升,最后导致服务A的部分调用超时,短信发送失败c端用户打开某些页面时,譬如用户空间或者用户详情页时,发现数据加载很慢,或者加载不出,导致用户体验大幅降低etc…
以上只是列出了部分小的场景,在纷繁复杂的互联网业务领域,存在接口性能问题的场景更是不胜枚举。问题是有了,那么我们为什么要做接口性能的优化呢?
用户体验会得到显著提升服务更稳定,性能更高,单位时间可处理的请求提升,响应指标有质的提升有效防止了服务雪崩问题
怎样做接口性能优化,思路是怎样的
很显然,当我们讨论要做接口性能优化的时候,必然是此接口已经出现了一丢丢小毛病,确有优化的必要。譬如可能是用户感觉购物车有点卡,页面加载有点慢,又或者通过监控得知某些接口响应超出平均值太多…当有这些类似迹象发生时,我们就要开始着手处理,做性能优化了。从个人所经历的职业生涯来看,主要分为以下几个步骤:
确定是哪个接口存在性能问题确定这个接口的内部逻辑是怎样的,做了哪些事情分析接口存在性能问题的根本原因寻找确立优化方案回归验证方案效果
其中第2步相对比较容易处理,而核心在于第4步,第5步是用于验证效果。下面本文重点会探讨第4步如何进行处理
分析接口存在性能的根本原因
为什么说这个很重要呢,因为这个直接影响到后面选择何种优化方案,会消耗多少成本。接口存在性能问题的具体案例千千万,笔者就从遇到过的着手,从最常见、最简单的开始说明
业务接口存在for循环调用
举例来看,这种场景就是A接口存在性能瓶颈,经分析发现,A接口实现里会同步for循环调用某个正常的接口B(or方法、耗时处理逻辑),以模拟代码来看,典型的如同下面这种:
//性能瓶颈处
List list = xxx
for (T t: list) {
//b.biz 接口(or方法、耗时处理逻辑)
b.biz(t);
}
上述代码是我们在写业务代码是极有可能出现的,假定biz这块每次同步调用耗时均值为50ms,如果这个list.size()>10,那这个接口经过这个for循环后,耗时将达500ms以上,且size越大,耗时就越高。那么针对此种调用,如何进行优化呢?针对这种case,优化有多种方案:
将biz处改成批处理,这是最佳实践。但这样处理也可能存在问题,譬如biz()接口本身不存在这个批处理接口,亦或者无法改成批处理如果本身能确定list的size不会很大,譬如超过10,成本最低,改造速度最快的方法就是使用java8中的集合的parallelStream()方法,该方法会并发地执行。缺点就是无法控制并发的粒度在无法改造biz接口,且list.size()又比较大的情况下,可以使用自定义线程池,并发地调用。如果存在需要获取biz()返回值的场景,并发调用时可使用countDownLatch等待获取全部返回值。缺点就是biz()接口瞬时会承受比较大的压力,极端情况下服务可能被打垮,这种不作为推荐使用方案
业务接口查db慢
这种场景还是很常见的,典型的如以下代码:
doSmt()
//典型的查db耗时高
List list = xxxDao.selectXXX(xxx)
doSmtAnother()
很显然瓶颈在于查库慢,但是关于这种case,如果细究起来可能得另开一章sql优化来讲了。可以稍微提几点,当发现查db慢时,可以从以下几个方向着手:
复合场景,存在较多查询
还有一种典型场景就是某个接口实现很复杂,业务逻辑多,调用其他接口或者方法的地方非常多,且接口的上下游链路里存在多个重复查询的情况(如A接口在调B接口之前查了C,然后调B接口时又查了一遍针对此类场景,可以从以下方法着手:
确定接口的上下游是否存在重复调用的情况,若存在,可通过改造降低查询次数接口的实现是否过于复杂,分析是否存在有效简化的可能,针对耗时较高的部分定点优化,缓存、并发都可以采用
接口勉强复合要求,但需要更高性能
当我们到达山穷水尽的时候,倘若需要做更进一步的优化,可以着手的点有哪些呢?从个人浅薄的知识来看,我能想到的有如下这些:
如果是针对的前端静态资源类接口,可将资源前置,靠近相应的用户侧,采用cdn加速可有效改善资源类接口响应速度如果是动态服务类接口,服务端的数据中心应选择恰当,另外对于Java语言后端服务来说,可以考虑从jvm性能调优的角度来进行优化,针对不同特性的应用,调整相应的gc算法及gc策略如果针对的是超高并发、超高性能接口的场景,可考虑使用go语言开发此类核心接口
后记
当碰到更典型的case和更好的解决方案时,此篇文章会进行追加。欢迎有不同想法的小伙伴共同探讨
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点