调了个方法导致接口变慢好多,真实原因有点坑。

前言

这篇文章是按照我的记忆梳理的,然后解决方法其实很简单,主要是梳理一下当时的排查思路,所以请大家多多指教。错误之处或表述不清楚的地方,欢迎评论指出或建议,感谢。

背景

事情发生在一个正常的下午,领导对我说:有项目组汇报说一个创建的接口变的比较慢,让我尽快排查一下。我一听,这个功能不是我写的,心里首先放松一下,那就排查吧!

验证线上

首先,当然是和领导确认,什么情况下,访问这个接口慢,因为有时候可能在某个特殊的场景下才会导致此类问题,或者是偶发情况,确定了这一点,也方便排查,然后我就按照领导说的,找到所属的数据页面,进行同样的操作。发现果然比较慢(这是我工作中学到的,不管别人怎么说,自己验证一遍),F12看了下,返回时间差不多快2s了,这个速度确实是有点慢的,因为这个添加的处理逻辑按理来说是不复杂的,不应该这么慢。

本地排查

接下来,就是排查的步骤,首先本地先启动一下,连接测试库看看是否有慢的问题,如果本地也慢,就比较方便一些,可以通过日志来打印每一部分花费的时间(我一般用StopWatch类),就可以知道哪里慢了。但是遗憾的是本地没有复现这种情况。

代码排查

既然无法复现,就只能看代码了,对比了下涉及到这个文件的提交记录,大概伪代码如下:

java 复制代码
...
...
String name = xxxService.getMember(name);
...
Project project = prjService.getProject(code);
...
project.getProjectId();
...
...

看见的第一眼,我直接忽略了这一段,觉得没啥问题啊,然后事实证明,事出反常必有妖。

最终原因

其实慢的原因就是我直觉忽略了的这一段代码中的Project project = prjService.getProject(code);,当我点进去后我才发现,里面别有洞天,我没法给大家复制代码,还是给大家一个伪代码:

java 复制代码
....
Project project = prjDao.getObject(code);
String pId = project.getProjectId();
List<Task> list = prjDao.queryTaskList(pId);
for (Task task : list){
    String taskId = task.getTaskId();
    Work w = prjDao.getObject(taskId);
    ....
    s = s.apend(w.getName());
}
project.setExtend(s);
....

以上代码存在的问题主要就是在for循环中进行对数据库的查询,如果list的长度很长的话,就会导致查询慢的问题,当时发现的时候真的是无语了,你如果有扩展,可以在方法中进行清晰的标识(比如:queryprojectExtend),并且代码也不必这么写,可以提取所有的taskId到一个list中,然后作为参数进行查询。

另外还有一个坑的点就是,其实原来的人调用这段方法本身其实就是为了拿一个project.getProjectId();,所以完全可以另外写一个简单获取的方法即可。

解决并验证

因为知道了原因,所以从数据库找了数据比较多的一个来进行复现,果然复现成功,也证明了问题就是出在这里。 首先把代码进行修复,修复后的伪代码如下:

java 复制代码
....
Project project = prjDao.getObject(code);
String pId = project.getProjectId();
List<Task> list = prjDao.queryTaskList(pId);
List<String> idList = list.getIdLIst(list);
List<Work> works = prjDao.queryObjectsByIds(idList);
for (Work task : list){
    s = s.apend(w.getName());
}
project.setExtend(s);
....

以上虽然也使用了for循环,但是内部只是做了字符串的拼接,也可使用Stream,会更简洁。 更改完后,继续测试该接口,发现是正常的。

思考总结

其实这次的问题很简单,没有涉及到高大上的一些问题来调整,要避免其实也很简单,调用其他人写的方法时,大概点进去观察一下。写方法的时候多想一下,是否会造成查询慢的问题,就可以了。

  • for循环查询这种情况,尽量避免。
  • 调用他人方法时需要知道内部大概的逻辑,切勿望文生义。
  • 不要想当然,觉得没问题就不排查。

致谢

感谢你的耐心阅读,如果我的分享对你有所启发或帮助,就给个赞呗,很开心能帮到别人。

相关推荐
杜杜的man30 分钟前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*31 分钟前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu33 分钟前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s34 分钟前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子36 分钟前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王1 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
2402_857589362 小时前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
一只爱打拳的程序猿2 小时前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring