0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

接口优化的常见方案实战总结

OSC开源社区 来源:OSCHINA 社区 2023-03-06 09:22 次阅读

作者 | 京东云开发者

一、背景

针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案。

743a85c0-bb79-11ed-bfe3-dac502259ad0.png

二、接口优化方案总结

1. 批处理

批量思想:批量操作数据库,这个很好理解,我们在循环插入场景的接口中,可以在批处理执行完成后一次性插入或更新数据库,避免多次 IO。

//for循环单笔入库
list.stream().forEatch(msg->{
    insert();
});
//批量入库
batchInsert();

2. 异步处理

异步思想:针对耗时比较长且不是结果必须的逻辑,我们可以考虑放到异步执行,这样能降低接口耗时。

例如一个理财的申购接口,入账和写入申购文件是同步执行的,因为是 T+1 交易,后面这两个逻辑其实不是结果必须的,我们并不需要关注它的实时结果,所以我们考虑把入账和写入申购文件改为异步处理。如图所示:

74502362-bb79-11ed-bfe3-dac502259ad0.png

至于异步的实现方式,可以用线程池,也可以用消息队列,还可以用一些调度任务框架。

3. 空间换时间

一个很好理解的空间换时间的例子是合理使用缓存,针对一些频繁使用且不频繁变更的数据,可以提前缓存起来,需要时直接查缓存,避免频繁地查询数据库或者重复计算。

需要注意的事,这里用了合理二字,因为空间换时间也是一把双刃剑,需要综合考虑你的使用场景,毕竟缓存带来的数据一致性问题也挺令人头疼。

这里的缓存可以是 R2M,也可以是本地缓存、memcached,或者Map。

举一个股票工具的查询例子:

因为策略轮动的调仓信息,每周只更新一次,所以原来的调接口就去查库的逻辑并不合理,而且拿到调仓信息后,需要经过复杂计算,最终得出回测收益和跑赢沪深指数这些我们想要的结果。如果我们把查库操作和计算结果放入缓存,可以节省很多的执行时间。如图:

7460285c-bb79-11ed-bfe3-dac502259ad0.png

4. 预处理

也就是预取思想,就是提前要把查询的数据,提前计算好,放入缓存或者表中的某个字段,用的时候会大幅提高接口性能。跟上面那个例子很像,但是关注点不同。

举个简单的例子:理财产品,会有根据净值计算年化收益率的数据展示需求,利用净值去套用年化收益率计算公式计算的逻辑我们可以采用预处理,这样每一次接口调用直接取对应字段就可以了。

5. 池化思想

我们都用过数据库连接池,线程池等,这就是池思想的体现,它们解决的问题就是避免重复创建对象或创建连接,可以重复利用,避免不必要的损耗,毕竟创建销毁也会占用时间。

池化思想包含但并不局限于以上两种,总的来说池化思想的本质是预分配与循环使用,明白这个原理后,我们即使是在做一些业务场景的需求时,也可以利用起来。

比如:对象池

6. 串行改并行

串行就是,当前执行逻辑必须等上一个执行逻辑结束之后才执行,并行就是两个执行逻辑互不干扰,所以并行相对来说就比较节省时间,当然是建立在没有结果参数依赖的前提下。

比如,理财的持仓信息展示接口,我们既需要查询用户的账户信息,也需要查询商品信息和 banner 位信息等等来渲染持仓页,如果是串行,基本上接口耗时就是累加的。如果是并行,接口耗时将大大降低。

如图:

746e9572-bb79-11ed-bfe3-dac502259ad0.png

7. 索引

加索引能大大提高数据查询效率,这个在接口设计之出也会考虑到,这里不再多赘述,随着需求的迭代,我们重点整理一下索引不生效的一些场景,希望对小伙伴们有所帮助。

具体不生效场景不再一一举例,后面有时间的话,单独整理一下。

7480839a-bb79-11ed-bfe3-dac502259ad0.png

8. 避免大事务

所谓大事务问题,就是运行时间较长的事务,由于事务一致不提交,会导致数据库连接被占用,影响到别的请求访问数据库,影响别的接口性能。

举个例子:

@Transactional(value ="taskTransactionManager", propagation =Propagation.REQUIRED, isolation =Isolation.READ_COMMITTED, rollbackFor ={RuntimeException.class,Exception.class})
    publicBasicResultpurchaseRequest(PurchaseRecordrecord){
        BasicResult result =newBasicResult();
        //插入账户任务
        taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_account.type(),TaskEnum.Account_bizType.purchase_request.type()));
        //插入同步任务
        taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.purchase.type()));
        //插入影像件上传任务
        taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.cert.type()));
        result.setInfo(ResultInfoEnum.SUCCESS);
        return result;
    }
上面这块代码主要是申购申请完成后,执行一系列的后续操作,如果现在新增申购完成后,发送 push 通知用户的需求。很有可能我们会在后面直接追加,如下图所示:事务中嵌套 RPC 调用,即非 DB 操作,这些非 DB 操作如果耗时较大的话,可能会出现大事务问题。大数据引发的问题主要有:死锁、接口超时、主从延迟等。
@Transactional(value ="taskTransactionManager", propagation =Propagation.REQUIRED, isolation =Isolation.READ_COMMITTED, rollbackFor ={RuntimeException.class,Exception.class})
    publicBasicResultpurchaseRequest(PurchaseRecordrecord){
        BasicResult result =newBasicResult();
        ...
        pushRpc.doPush(record);        
        result.setInfo(ResultInfoEnum.SUCCESS);
        return result;
    }
所以为避免大事务问题,我们可以通过以下方案规避: 1,RPC 调用不放到事务里面 2,查询操作尽量放到事务之外 3,事务中避免处理太多数据

9. 优化程序结构

程序结构问题一般出现在多次需求迭代后,代码叠加形成。会造成一些重复查询、多次创建对象等耗时问题。在多人维护一个项目时比较多见。解决起来也比较简单,我们需要针对接口整体做重构,评估每个代码块的作用和用途,调整执行顺序。

10. 深分页问题

深分页问题比较常见,分页我们一般最先想到的就是 limit ,为什么会慢,我们可以看下这个 SQL:

select*from purchase_record where productCode ='PA9044'andstatus=4orderby orderTime desclimit100000,200
limit 100000,200 意味着会扫描 100200 行,然后返回 200 行,丢弃掉前 100000 行。所以执行速度很慢。一般可以采用标签记录法来优化,比如:
select*from purchase_record where productCode ='PA9044'andstatus=4and id >100000limit200
这样优化的好处是命中了主键索引,无论多少页,性能都还不错,但是局限性是需要一个连续自增的字段

11.SQL 优化

sql 优化能大幅提高接口的查询性能,由于本文重点讲述接口优化的方案,具体 sql 优化不再一一列举,小伙伴们可以结合索引、分页、等关注点考虑优化方案。

12. 锁粒度避免过粗

锁一般是为了在高并发场景下保护共享资源采用的一种手段,但是如果锁的粒度太粗,会很影响接口性能。 关于锁粒度:就是你要锁的范围有多大,不管是 synchronized 还是 redis 分布式锁,只需要在临界资源处加锁即可,不涉及共享资源的,不必要加锁,就好比你要上卫生间,只需要把卫生间的门锁上就可以,不需要把客厅的门也锁上。 错误的加锁方式:

//非共享资源
        privatevoidnotShare(){
        }
        //共享资源
        privatevoidshare(){
        }
        privateintwrong(){
            synchronized(this){
                share();
                notShare();
            }
        }

正确的加锁方式:

//非共享资源
        privatevoidnotShare(){
        }
        //共享资源
        privatevoidshare(){
        }
        privateintright(){
            notShare();
            synchronized(this){
                share();

            }
        }

三、最后

接口性能问题形成的原因思考

我相信很多接口的效率问题不是一朝一夕形成的,在需求迭代的过程中,为了需求快速上线,采取直接累加代码的方式去实现功能,这样会造成以上这些接口性能问题。 变换思路,更高一级思考问题,站在接口设计者的角度去开发需求,会避免很多这样的问题,也是降本增效的一种行之有效的方式。 以上,共勉!

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8580

    浏览量

    151046
  • 文件
    +关注

    关注

    1

    文章

    565

    浏览量

    24733
  • 优化
    +关注

    关注

    0

    文章

    220

    浏览量

    23892
  • 代码
    +关注

    关注

    30

    文章

    4780

    浏览量

    68539

原文标题:接口优化的常见方案实战总结

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    PCBA测试的常见方

    以看出整个工艺流程存在的问题,比如前期工序SMT、DIP等,存在问题,就进行调整,让整个工艺更加完善。PCBA测试常见方法,主要有以下几种: 1.手工测试手工测试就是直接依靠视觉进行测试,通过视觉与比较来
    发表于 11-08 17:19

    前端性能怎么优化

    前端性能优化常见方
    发表于 03-27 11:42

    光耦隔离的4种常见方法对比

    光耦隔离的4种常见方法对比
    发表于 05-31 11:06 13.2w次阅读
    光耦隔离的4种<b class='flag-5'>常见方</b>法对比

    运放使用常见问题总结

    实战电子的经验总结。实用的运放问题答疑。适合初学者和进一步提高的友友。
    发表于 07-29 18:31 0次下载

    嵌入式接口保护设计方案

    接口是嵌入式设备中最常见的组成部分,是数据传输的通道,它起着数据传输与隔离保护电路的作用,今天我们一起探讨接口保护设计一种常见方案
    发表于 10-13 11:24 849次阅读

    DSP程序优化总结

    DSP程序优化总结
    发表于 10-23 14:24 2次下载
    DSP程序<b class='flag-5'>优化</b><b class='flag-5'>总结</b>

    检测LED单元板的常见方

    LED电子显示屏很重要的组成部分就有LED单元板,如果单元板有问题,会直接影响LED显示屏的整体质量!所以,如何辨别LED单元板的好坏是LED显示屏商家关心的问题,下面整理了一些检测LED单元板的常见方法。
    发表于 05-04 17:31 3818次阅读

    电平转换常见方法的汇总比较资料下载

    电子发烧友网为你提供电平转换常见方法的汇总比较资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
    发表于 04-09 08:44 9次下载
    电平转换<b class='flag-5'>常见方</b>法的汇总比较资料下载

    HarmonyOS测试技术与实战-HarmonyOS自研图形栈总结

    HDC 2021华为开发者大会 HarmonyOS测试技术与实战-HarmonyOS自研图形栈总结
    的头像 发表于 10-23 15:47 1614次阅读
    HarmonyOS测试技术与<b class='flag-5'>实战</b>-HarmonyOS自研图形栈<b class='flag-5'>总结</b>

    18种接口优化方案汇总1

    之前工作中,遇到一个`504`超时问题。原因是因为接口耗时过长,超过`nginx`配置的`10`秒。然后 真枪实弹搞了一次接口性能优化,最后接口从`11.3s`降为`170ms`。本文
    的头像 发表于 02-15 15:59 852次阅读
    18种<b class='flag-5'>接口</b><b class='flag-5'>优化</b><b class='flag-5'>方案</b>汇总1

    18种接口优化方案汇总2

    之前工作中,遇到一个`504`超时问题。原因是因为接口耗时过长,超过`nginx`配置的`10`秒。然后 真枪实弹搞了一次接口性能优化,最后接口从`11.3s`降为`170ms`。本文
    的头像 发表于 02-15 15:59 664次阅读
    18种<b class='flag-5'>接口</b><b class='flag-5'>优化</b><b class='flag-5'>方案</b>汇总2

    箱式变压器保养的常见方法和事项

      箱式变压器是工业、矿山、建筑等各个领域中常见的基础设施,作为电力系统中不可缺少的设备之一,需要定期进行保养与维护,以确保其正常、安全、稳定地运行。以下是箱式变压器保养的常见方法:
    发表于 04-19 14:45 2897次阅读

    MCU批量生产下载程序的几种常见方

    MCU批量生产下载程序的几种常见方
    的头像 发表于 10-24 17:22 1608次阅读
    MCU批量生产下载程序的几种<b class='flag-5'>常见方</b>法

    无功补偿的原理、作用及常见方

    无功补偿的原理、作用及常见方式  无功补偿是电力系统中的一项重要技术措施,用于改善电力质量和提高能源利用效率。本文将详细介绍无功补偿的原理、作用以及常见的补偿方式。 一、无功补偿的原理 无功功率
    的头像 发表于 01-19 14:19 9006次阅读

    性能优化之路总结

    针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化
    的头像 发表于 06-17 15:00 325次阅读