将一个接口响应时间从2s优化到 200ms以内的一个案例

将一个接口响应时间从2s优化到 200ms以内的一个案例一 背景在开发联调阶段发现一个接口的响应时间特别长 经常超时 囧 本文讲讲是如何定位到性能瓶颈以及修改的思路 将该接口从 2s 左右优化到 200ms 以内 二 步骤 2 1 定位定位性能瓶颈有两个思路 一个是通过工具去监控 一个是通过经验去猜想 2 1 1 工具监控就工具而言 推荐使用 arthas 用到的是 trace 命令具体安装步骤很简单 大家自行研究 我的使用步骤是

一、背景

在开发联调阶段发现一个接口的响应时间特别长,经常超时,囧…

本文讲讲是如何定位到性能瓶颈以及修改的思路,将该接口从 2 s 左右优化到 200ms 以内 。

二、步骤

2.1 定位

定位性能瓶颈有两个思路,一个是通过工具去监控,一个是通过经验去猜想。

2.1.1 工具监控

就工具而言,推荐使用 arthas ,用到的是 trace 命令

具体安装步骤很简单,大家自行研究。

我的使用步骤是,先最终待研究的函数的最外层:

trace com.xxx.service.impl.AServiceImpl refresh

其中耗时最多的子函数会被标红色

Affect(class-cnt:2 , method-cnt:2) cost in 525 ms. `---ts=2020-0X-0Y 13:33:18;thread_name=DubboServerHandler-127.0.0.1:20880-thread-36;id=24e;is_daemon=true;priority=5;TCCL=com.mmm.WWWClassLoader@4362d7df `---[1761.ms] com.xxx.service.impl.AServiceImpl$$EnhancerBySpringCGLIB$$e3cd7543:refresh() +---[0.017066ms] com.xxx.service.impl.AServiceImpl$$EnhancerBySpringCGLIB$$e3cd7543:$jacocoInit() `---[1761.00347ms] org.springframework.cglib.proxy.MethodInterceptor:intercept() `---[1757.ms] com.xxx.service.impl.AdServiceImpl:refresh() +---[0.006629ms] com.xxx.biz.yyy.service.impl.AServiceImpl:$jacocoInit() +---[0.004073ms] java.util.Collections:singletonList() +---[1709.ms] com.yyy.service.impl.AServiceImpl:refreshSomeThings() `---[48.ms] com.yzzzz.service.impl.AServiceImpl:createSurvey() 

继续再 trace 耗时最多的子函数。

trace com.yyy.service.impl.AServiceImpl refreshSomeThings

最终定位到最影响耗时的函数上,继续往下跟。

最后发现造成性能瓶颈的函数是一个网络请求,单次请求大概 100多毫秒。

为了避免调用的数据量太大,项目中采用分批调用的方式,但是每个批次太小,导致请求次数过多。

假设请求 N 次(如 10次),每次请求 M毫秒(如 200ms),总耗时就是 N*M (2000)毫秒。

2.1.2 猜想

如果开发经验足够丰富,大致可以猜出哪些接口可能存在性能问题。

最常见的有:

  1. 慢 SQL 会是性能瓶颈,主要原因是没有命中索引。
  2. 发送远程数据请求(RPC 远程调用、HTTP 远程调用)。
  3. I/O 操作等。

最常见的是在循环中执行 SQL或者网络请求。

然后审查一下自己的代码发现 SQL 查询部分都可以命中索引,调用链路上有一个函数最终会调用 HTTP 请求,而且是在一个循环里。

因此最有可能成为造成接口延时的是底层依赖的 HTTP 请求。

2.2 解决

既然 HTTP 请求是性能瓶颈,那么要尽量减少请求,或者让请求由串行改为多线程并发/并行

减少网络请求的次数,可以将多个请求合并成一个批量接口(或者增加批量请求的每个批次的大小)。

这里的批次甚至可以使用动态配置,根据情况动态修改。

串行改为并行可以使用 CompletableFuture 来实现,具体参见:《Java 数据分批调用接口的正确姿势》

最终一个接口从1 s – 2 s降低到了 200 ms 以内。

3、总结

很多人不愿意学习 arthas ,如果不去学习不去了解,遇到可以用上的场景想不起来去用。

另外大家可以积累下开发过程中常见的性能瓶颈的原因,以便未来遇到性能瓶颈是可以快速排查和解决问题。

最后大家在开发阶段或测试阶段,多看错误日志,多关注接口的响应时长等,尽早排除问题,尽早做优化。

希望本文对大家开发能够有帮助。

如果我的文章对你有帮助,欢迎关注,点赞评论!!在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233580.html原文链接:https://javaforall.net

(0)
上一篇 2025年7月7日 下午5:01
下一篇 2025年7月7日 下午5:22


相关推荐

  • 广东电信在线人工服务器,202.96.128.86广东电信DNS故障及解决方法

    广东电信在线人工服务器,202.96.128.86广东电信DNS故障及解决方法广东用户如果遇到能上QQ,但网页打不开,提示“找不到服务器”的现象,而且如果别人能访问,而你不能访问,多数情况下就是你的DNS解析故障造成的。解决这个问题比较有效的方法是换一个DNS服务器。下面是几个常用的广东电信DNS,广东的朋友如果遇到一些网页打不开时,可以更换下DNS看看。61.144.56.100广东省广州市电信61.144.56.101广东省广州市电信202.96.128.68广东…

    2022年7月11日
    43
  • html js打开一个新页面跳转,js页面跳转

    html js打开一个新页面跳转,js页面跳转在我们开发网站的过程中 有时候一些页面的跳转需要使用 js 去实现 接下来吾爱编程为大家分享一下常用的 js 页面跳转方法 有需要的小伙伴可以参考一下 1 直接跳转指定页面 alert 哈哈 我是直接跳转 window location href https www itbiancheng com 2 返回上一页 alert 哈哈 我要返回上一页 window history ba

    2026年3月19日
    2
  • Android程序员接私活完整攻略「建议收藏」

    Android程序员接私活完整攻略「建议收藏」接私活对程序员这个圈子来说是一个既公开又隐私的话题,不说全部,应该大多数程序员都有过想要接私活的想法,当然,也有部分得道成仙的不主张接私活。但是很少有人在公开场合讨论私活的问题,似乎都在避嫌。就跟有人下班后跑滴滴一样,程序员私有时间接点活挣点钱不也很正常么,不过不要在上班时间就行,就跟你上班期间出去跑滴滴一样。当你竭尽全力想要去接私活的时候一定做过这样的事,百度搜索“程序员如何接私活”或者…

    2022年6月14日
    160
  • 解析Java中文乱码的处理方法

    解析Java中文乱码的处理方法【引自程序犹如人生的博客】为什么说乱码是中国程序员无法避免的话题呢?这个首先要从编码机制上说起,大家都是中文和英文的编码格式不是一样,解码也是不一样的!如果中国的程序员不会遇到乱码,那么只有使用汉语编程。汉语编程是怎么回事,我也不大清楚,应该是前年吧!我一朋友给我介绍汉语编程,怎么不错不错?当时因为学习忙没去关注这个,等我闲了,那个朋友不弄这个,问他,他也不说不大清楚,最后自己对这个学习也不了了之

    2022年7月7日
    48
  • vue定义全局变量

    vue定义全局变量1 将从服务器请求的数据作为全局变量 全局变量模块挂载到 Vue prototype 在开发中 有时需要将从接口请求到的一些数据当做全局变量 在其他页面多次使用 比如 登录成功后可能需要将用户名 id 等信息存起来 便于其他页面展示或使用 将这些信息定义为全局变量是用起来就很方便 举栗子 在 login vue 中拿到了用户的一些信息 script importVuef script

    2026年3月17日
    2
  • 如何在 Cursor 中设置和使用 MCP:全面指南

    如何在 Cursor 中设置和使用 MCP:全面指南

    2026年3月16日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号