✅如果一个接口响应时间不符合预期,怎么排查跟解决?
典型回答
如果一个接口的接口响应时间(RT)不符合预期,就是慢了呗,那想要解决这个问题,首先应该知道哪里慢了。
性能优化,就是哪里亮了点哪里,首先需要知道哪里亮了。
如果是前端耗时长,那么可以考虑是网络请求发出到返回的耗时,可能包含 DNS、TCP 建连、TLS 握手、数据传输等。
如果是后端耗时长,那么可能是后端应用处理时间,比如业务逻辑、数据库、外部接口调用等。
如果A调用B,B的耗时并不长,但是A却提示调用B超时,可能考虑的网络耗时,比如TCP重传的情况。
✅一次RPC请求,客户端显示超时,但是服务端不超时,可能是什么原因?
所以,我们需要有一套行之有效的做线上接口慢的定位的方案。
问题定位
首先,最简单的方案就是,如果你是分布式系统,接入了分布式链路追踪的工具,比如skywalking,可以通过他的trace来查看具体哪里慢了,是自己慢了,数据库慢了,Redis慢了,还是下游接口满了。
如果你不知道啥叫分布式链路追踪,或者没用过Prometheus,那么就可以用另外一个方案,那就是Arthas来查看trace的情况。
PS:很多人说线上不能使用arthas,我只能说,这玩意阿里开源的,我们线上定位慢接口都也在用,所以没啥不能用的。当然,做一些特殊操作的时候要注意,可能会导致一些STW,比如拉堆dump,线程dump等,但是这个和arthas没关系,是这些操作本身就这样的,你自己用其他命令执行也一样。
下面这个文档中,介绍了如何通过arthas查看接口耗时。
下载arthas后,运行:
sh as.sh 使用 trace 命令查看接口耗时:
[arthas@1658]$ trace com.alibaba.fin.pricing.**.PriceCalculateService trial '#cost > 50' -n 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 427 ms, listenerId: 6
`---ts=2021-11-08 15:10:24;thread_name=HSFBizProcessor-DEFAULT-8-thread-224;id=2d7c1;is_daemon=true;priority=10;TCCL=com.taobao.pandora.boot.loader.LaunchedURLClassLoader@783e6358;trace_id=2132e43116363554229592404e58b8;rpc_id=9.40.6
`---[264.85838ms] com.alibaba.fin.pricing.**.service.PriceCalculateService:trial()
+---[0.012009ms] com.alibaba.fin.pricing.**.request.PriceCalculateRequest:getTenant() #95
+---[0.001564ms] com.alibaba.fin.pricing.**.request.PriceCalculateRequest:getProduct() #96
...
...
...
+---[221.884809ms] com.alibaba.fin.pricing.*.ExercisePriceDomainService:queryMatchedEffectiveExercisePrice() #167
+---[0.002242ms] com.alibaba.fin.pricing.**.service.PriceQueryRequest:<init>() #170
`---[0.012586ms] com.alibaba.fin.pricing.**.service.PriceCalculateService:getTieredPrice() #170经过分析发现,方法总时长264ms,其中有221ms 是耗费在ExercisePriceDomainService:queryMatchedEffectiveExercisePrice() 方法上,那么这个方法的调用就是性能瓶颈了。
所以,通过trace命令,就可以定位到具体慢点地方,然后逐一解决。
问题解决
定位到哪里慢之后,就可以去解决慢的问题了。
| 问题 | 解决方案 |
|---|---|
| 资源不足(CPU、内存等) | 扩容 |
| 网络慢 | 同机房策略、单元化架构 |
| GC频繁 | JVM调优、调整堆大小 |
| 慢SQL | ✅如何进行SQL调优? |
| 表中数据量大 | 分库分表、 分布式数据库 |
| 查询慢 | 加缓存 |
| 缓存失效 | 优化过期时间和淘汰策略 |
| 外部服务慢 | 异步调用 |
| 干的活多 | 多线程执行 |
| 锁冲突 | 用乐观锁、减少锁粒度、无锁化编程 |
| 数据操作多 | 批处理 |
| IO操作慢 | 用NIO\AIO\Netty等 |