从3s到25ms!看看京东的接口优化技巧,确实很优雅!!

点击关注公众号,Java干货及时送达594b937c2ed95ad2f68c5fda314f8795.png

40c17a1ab26a933acfa5dc2ea921a2ef.png 学习 Spring Cloud 微服务的正确姿势!

d212e65ec6a716c29222bb642dfece9d.png 用上 ChatGPT 啦,强的离谱!

a562db0a1efcd7ce31f0f7fa71effdd7.png 终于把 Spring Boot 3.0 写成书了!


来源:https://toutiao.io/posts/0kwkbbt

大家好,最近看到京东云的一位大佬分享的接口优化方案,感觉挺不错的,拿来即用。建议收藏一波或者整理到自己的笔记本中,随时查阅!

下面是正文。

一、背景

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

0e9871f507f8c8203ea4b952340d1057.png

二、接口优化方案总结

1.批处理

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

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

2. 异步处理

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

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

e509cdff6c37b42410fd9cc612d34569.png

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

推荐一个开源免费的 Spring Boot 最全教程:

https://github.com/javastacks/spring-boot-best-practice

3. 空间换时间

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

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

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

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

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

f32db5e6e8af9d038214c3de122d19e1.png

4. 预处理

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

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

另外,如果你近期准备面试跳槽,建议在Java面试库小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

5. 池化思想

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

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

比如:对象池

6. 串行改并行

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

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

如图:

916d7faceedcb68026245a74e4b5e3d1.png

7. 索引

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

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

06863ee61c4f17acfc71472d2b89fb41.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,事务中避免处理太多数据

另外,如果你近期准备面试跳槽,建议在Java面试库小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

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();}
}

三、最后

我相信很多接口的效率问题不是一朝一夕形成的,在需求迭代的过程中,为了需求快速上线,采取直接累加代码的方式去实现功能,这样会造成以上这些接口性能问题。

变换思路,更高一级思考问题,站在接口设计者的角度去开发需求,会避免很多这样的问题,也是降本增效的一种行之有效的方式。


最后宣传下我的 ChatGPT 知识星球,R哥最近 ChatGPT 玩疯了,用它写文章、生成代码、做表格、写 PPT、写文案、做面试题,效率提升了 N 倍。

建议尽快上车,现在上手成本是越来越高了,不割韭菜,R哥是实实在在教大家东西。

星球分享了大量 ChatGPT 学习资料, 还输出了 50+ 篇保姆级教程,持续更新中,涉及方方面面,真正的高质量知识星球。

目前还是优惠价,快扫码加入吧:

55bee16acf95e5211a853843873f9560.png

1000 人后正式涨价啦,早就是优势!

End

d7de7ae235070a36410367e47ab7f230.png 学习 Spring Cloud 微服务的正确姿势!

c730dbc9b034a636ee5f41eaf0555201.png 终于把 Spring Boot 3.0 写成书了!

c0dda072d58805094ff04dfabf67a9c2.png 用上 ChatGPT 啦,强的离谱!

9cf48aa61463610380ea39c8f6fb17b7.png ChatGPT 视频课程来了,完全免费!

59fdc2d8ad7a357548b2dc95d11eb92f.png Java 20 正式发布,超神了。。

👇 点击阅读原文,玩转 ChatGPT!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/47162.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chatgpt赋能python:Python发送短信指南:你需要知道的一切

Python 发送短信指南:你需要知道的一切 Python 是一种高级编程语言,它的流行程度得益于其简单易学和高效的特性。Python 可以很容易地集成到各种应用程序中,用于发送短信。在本文中,我们将了解如何使用 Python 在不同平台和服务上…

chatgpt赋能python:Python操作ADB:实现Android设备的远程控制

Python操作ADB:实现Android设备的远程控制 1. 什么是ADB ADB(Android Debug Bridge)是一种基于命令行的工具,用于与连接的Android设备进行通信和操作。使用ADB,你可以在电脑上运行命令来控制设备,并且复制…

chatgpt赋能python:Python回滚-避免代码灾难的有效措施

Python回滚-避免代码灾难的有效措施 什么是Python回滚 Python回滚是一种避免代码灾难的有效措施,它可以让你在代码出现问题之后及时回退到之前的版本,保证系统不会受到影响。 回滚是一项非常重要的工作,越是复杂的项目越需要进行回滚。Pyt…

chatgpt赋能python:Pythonzmq库的介绍

Python zmq库的介绍 Python是一种强大的编程语言,它有着丰富的库和工具进行数据处理和网络通信。其中,zmq库是一种高效的消息传输协议,可以在本地或分布式环境中进行网络通信。本文将介绍Python zmq库的基本知识,以及如何在您的项…

chatgpt赋能python:Python怎么上传?

Python怎么上传? Python作为一种高级编程语言,具有易学易用、高效稳定、多功能等特点,受到越来越多程序员的青睐。然而,对于初学者来说,在学习完Python之后,如何将自己的作品上传至网上并分享给他人并不是…

chatgpt赋能python:PythonZMQ安装指南:从入门到精通

Python ZMQ安装指南:从入门到精通 Python ZMQ是一个基于ZeroMQ消息传递库的Python包,它可以让开发者轻松地实现分布式计算,消息传递和异步IO等功能。本文将介绍Python ZMQ的安装及基本使用方法,帮助开发者快速上手使用。 1. 安装…

chatgpt赋能Python-pythongit

PythonGit:使Git操作更加高效 Git作为目前最流行的版本控制工具之一,已经被广泛应用于软件开发、Web开发等领域。PythonGit则是一个基于Python编写的Git客户端库,可以让开发者们更加高效地进行Git操作,提高开发效率。 PythonGit…

chatgpt赋能Python-python_heapq

Python heapq介绍:优雅又高效的堆数据结构 Python中的heapq模块提供了堆数据结构的功能,以及实现了堆排序算法。堆是一种优秀的数据结构,常用于实现优先队列,也可用来寻找一组元素中的最小值或最大值。堆排序算法在排序N个元素时…

chatgpt赋能Python-python_heappush

Python中的Heapq模块 Python是一种常用的编程语言,它的标准库中包含了丰富的工具函数和模块,其中Heapq模块是一个十分实用的模块,它提供了对堆的支持。堆是一种常用的数据结构,它具有以下特点: 堆可以是最大堆或最小…

超级玛丽3通关指南+隐藏点整理

《超级玛丽3》已经成为一种童年的象征,它是我们儿时的记忆,是我们成长的见证。每每玩起这个游戏,都会让我们感觉仿佛回到的童年时代,给我们带来无限乐趣。下面是《超级玛丽3》全关卡的攻略指南,给你找找童年的感觉&…

运动会方阵计算机学院,哈工深运动会圆满闭幕 计算机学院大放异彩

计算机学院宣 (严心遥、王曦冉/图文)10月18日上午8点,天朗气清,惠风和畅,我校在大学城体育中心举行了哈尔滨工业大学(深圳)第三届运动会。本次运动会分为开幕式,各项运动的决赛,趣味运动会以及闭幕式等几个部分。令我们…

html满屋花项目,几款花卉,花姿妖娆,花开香飘溢满屋,真的太美了

沙漠玫瑰不仅是新人花,也是懒人花,沙漠玫瑰花形似小喇叭,玫瑰红色,非常艳丽。伞形花序三五成丛,灿烂似锦,四季开花不断。能在沙漠地区生长的沙漠玫瑰,说明非常耐干旱,水分越少反而生…

王者服务器维护5月1日,2018王者荣耀5月3日更新维护公告 5月3日更新了内容汇总...

【五五开黑节专属队徽上架小队商店】 【上架时间】: 5 月 5 日~ 6 月 5 日 5 月 5 日零点,五五开黑节专属队标上架小队商城, 688 小队币可兑换,上架限时 1 个月。 快和队友们一起开黑攒队币,兑换这份属于你们的专属荣光…

下列css属性中用于指定内容,使用link元素调用CSS的语法中,以下哪个属性是用来指定CSS文件的路径的?...

摘要: :探中国装具方器人便拆大学的末端工测机,使用属性用现夹能推移运、取、切割、搬等功可实。调用S的定C的路人围观的晋代为长得好出门发妇时因诗人是(看引。文件恶形行音性就象变象改变通过《马面形其正的上》纯程属成邪赛曲四度使得可以。... :探中…

金属有机骨架PCN-333(Al)CAS号:1843260-12-7-瑞禧

通过一步法将金属有机框架材料(PCN-333(Al)MOF)生长在多孔的三维洋麻杆生物碳(3D-KSC)材料构建新的支撑框架电极并将微过氧化物酶(MP-11)装载在PCN-333(Al)MOF材料中。花球状的PCN-333(Al)MOF孔径为5.5 nm,可以固载大量的MP-11分子且保持酶的良好的生物活性。 通过扫描电镜和电…

[JS]原生使用Object.defineProperty劫持数据,实现响应式数据驱动DOM(借助VUE2.X的核心思想)

举个栗子 点击按钮只修改响应式数据,达到DOM更新和数据更新的功能 核心思想 定义一个即将被监听劫持的对象 > 给每一个对象.属性增加Object.defineProperty(),从而实现修改属性是会触发getter和setter getter 用于获取被劫持后计算出指定的结果setter 监听到修改操作时,由s…

P04 并发小球V1 V2.1

目录 线程游戏V1——多线程 目标效果 一 Ball类 ​ 二 BallThread类 三 UIListenner类 ​ 四 GameUI类 运行结果 问题分析 线程游戏V2——三线程 目标效果 新增MoveThread线程实现类 修改监听器类UIListenner代码 运行结果 问题分析 问题2代码实现 V2版本如何实现…

用python写的判断是否是水仙花数

水仙花数是百位的3次方十位的3次方个位的3次方原数 while循环 i100while i<1000:a100i//100 #//用于取整&#xff0c;a100得到的值是百位的a10(i//10)%10 #%用于取余&#xff0c;a10得到的值是十位的ai%10 #a得到的值是个位的if(ia100**3a10**3a**3): #判断是…

固定管线shader编写:基本属性

欢迎转载&#xff01;转载时请注明出处&#xff1a; http://write.blog.csdn.net/postedit/50753008 shader 部分介绍&#xff1a; properties&#xff1a;属性部分 material&#xff1a;材质部分 lighting&#xff1a; 启用光照&#xff08;顶点光照&#xff09; settexture :…

计算机图形学(2):OpenGL画球体

参考文章 配置OpenGL环境看上一篇文章 效果图&#xff1a; main.cpp&#xff1a; #include "Dependencies/glew/glew.h" #include "Dependencies/GLFW/glfw3.h"#include "Dependencies/glm/glm.hpp" #include "Dependencies/glm/gtc/m…