本文由 简悦 SimpRead 转码, 原文地址 https://mp.weixin.qq.com/s/Z4dhYFauX8YAeOW45z8zaA
武培轩推荐搜索 JavaSpring Boot数据结构MySQLRedisElasticsearch
前言
最近对外接口偶现 504 超时问题,原因是代码执行时间过长,超过 nginx 配置的 15 秒,然后真枪实弹搞了一次接口性能优化。在这里结合优化过程,总结了接口优化的八个要点,希望对大家有帮助呀~
数据量比较大,批量操作数据入库
耗时操作考虑异步处理
恰当使用缓存
优化程序逻辑、代码
SQL 优化
压缩传输内容
考虑使用文件 / MQ 等其他方式暂存,异步再落地 DB
跟产品讨论需求最恰当,最舒服的实现方式
先看一下我们对外转账接口的大概流程吧
优化前:
1 | // for循环单笔入库 |
优化后:
1 | // 批量入库,mybatis demo实现 |
性能对比:
单位(ms) | for 循环单笔入库 | 批量入库 |
---|---|---|
500 条 | 1432 | 1153 |
1000 条 | 1876 | 1425 |
解析
批量插入性能更好,更加省时间,为什么呢?
打个比喻: 假如你需要搬一万块砖到楼顶, 你有一个电梯, 电梯一次可以放适量的砖(最多放 500), 你可以选择一次运送一块砖, 也可以一次运送 500, 你觉得哪种方式更方便,时间消耗更少?
2. 耗时操作考虑异步处理
耗时操作,考虑用异步处理,这样可以降低接口耗时。本次转账接口优化,匹配联行号的操作耗时有点长,所以优化过程把它移到异步处理啦,如下:
优化前:
优化后
匹配联行号的操作异步处理
性能对比:
假设一个联行号匹配 6ms
|
| 同步 | 异步 |
| — | — | — |
| 500 条 | 3000ms | ~ |
| 1000 条 | 6000ms | ~ |
解析:
因为联行号匹配比较耗时,放在异步处理的话,同步联机返回可以省掉这部分时间,大大提升接口性能,并且不会影响到转账主流程功能。
除了这个例子,平时我们类似功能,如用户注册成功后,短信邮件通知,也是可以异步处理的,这个优化建议香饽饽的~
所以,太耗时的操作,在不影响主流程功能的情况下,可以考虑开子线程异步处理的啦。
3. 恰当使用缓存
在适当的业务场景,恰当地使用缓存,是可以大大提高接口性能的。这里的缓存包括:Redis,JVM 本地缓存,memcached,或者 Map 等。
这次转账接口,使用到缓存啦,举个简单例子吧~
优化前
以下是输入用户账号,匹配联行号的流程图
优化后:
恰当使用缓存,代替查询 DB 表,流程图如下:
解析:
把热点数据放到缓存,不用每次查询都去 DB 拉取,节省了这部分查 SQL 的耗时,美滋滋呀~
当然,不是什么数据都适合放到缓存的哦,访问比较频繁的热点数据才考虑缓存起来呢~
优化程序逻辑、程序代码,是可以节省耗时的。
我这里就本次的转账接口优化,举个例子吧~
优化前:
优化前,联行号查询了两次(检验参数一次,插入 DB 前查询一次),如下伪代码:
1 | punlic void process(Req req){ |
优化后:
优化后,只在校验参数的时候插叙一次,然后设置到对象里面~ 入库前就不用再查啦,伪代码如下:
1 | void checkTransParams(Req req){ |
解析:
对于优化程序逻辑、代码,是可以降低接口耗时的。以上 demo 只是一个很简单的例子,就是优化前 payeeBankNo 查询了两次,但是其实只查一次就可以了。很多时候,我们都知道这个点,但就是到写代码的时候,又忘记了呀~ 所以,写代码的时候,留点心吧,优化你的程序逻辑、代码哦。
除了以上 demo 这点,还有其它的点,如优化 if 复杂的逻辑条件,考虑是否可以调整顺序,或者 for 循环,是否重复实例化对象等等,这些适当优化,都是可以让你的代码跑得更快的。
- 优化你的 SQL
很多时候,你的接口性能瓶颈就在 SQL 这里,慢查询需要我们重点关注的点呢。
我们可以通过这些方式优化我们的 SQL:
加索引
避免返回不必要的数据
优化 sql 结构
分库分表
读写分离
- 压缩传输内容
压缩传输内容,文件变得更小,因此传输会更快啦。10M 带宽,传输 10k 的报文,一般比传输 1M 的会快呀;打个比喻,一匹千里马,它驮着一百斤的货跑得快,还是驮着 10 斤的货物跑得快呢?
解析:
如果你的接口性能不好,然后传输报文比较大的话,这时候是可以考虑压缩文件内容传输的,最后优化效果可能很不错哦~
7. 考虑使用文件 / MQ 等其他方式暂存数据,异步再落地 DB
如果数据太大,落地数据库实在是慢的话,可以考虑先用文件的方式保存,或者考虑 MQ,先落地,再异步保存到数据库~
本次转账接口,如果是并发开启,10 个并发度,每个批次 1000 笔数据,数据库插入会特别耗时,大概 10 秒左右,这个跟我们公司的数据库同步机制有关,并发情况下,因为优先保证同步,所以并行的插入变成串行啦,就很耗时。
优化前:
优化前,1000 笔先落地 DB 数据库,再异步转账,如下:
优化后:
先保存数据到文件,再异步下载下来,插入数据库,如下:
解析:
如果你的耗时瓶颈就在数据库插入操作这里了,那就考虑文件保存或者 MQ 或者其他方式暂存吧,文件保存数据,对比一下耗时,有时候会有意想不到的效果哦。
8. 跟产品讨论需求最恰当,最舒服的实现方式
这点个人觉得还是很重要的,有些需求需要好好跟产品沟通的。
比如有个用户连麦列表展示的需求,产品说要展示所有的连麦信息,如果一个用户的连麦列表信息好大,你拉取所有连麦数据回来,接口性能就降下来啦。如果产品打桩分析,会发现,一般用户看连麦列表,也就看前几页~ 因此,奸笑,哈哈~ 其实,那个超大分页加载问题也是类似的。即 limit + 一个超大的数,一般会很慢的~~
总结
本文基于一次对外接口耗时优化的实践,总结了优化接口性能的八个点,希望对大家日常开发有帮助哦~ 嘻嘻
完
觉得不错,点个在看~