系统上线后,发现某个接口响应很慢,你如何定位可能的原因,以及对应的解决思路?
- 标签:后端、场景题
🏛 业务架构师
这题和"接口变慢排查"同源,但我会给出更完整的定位→解决→预防闭环,突出量化和分级。
定位:先测量,不猜
- 确认现象与影响面:哪个接口、从什么时候开始(对照发布记录,7 成概率是变更引入)、P95 还是 P99 慢、影响多少交易——影响面决定投入多少人力。
- 链路分段:Trace 全链路看耗时分布,定位慢在应用内还是下游。
- 应用内:GC 停顿(-Xlog:gc)、锁等待(jstack BLOCKED)、线程池排队、序列化大对象。
- 数据库:慢 SQL 日志、执行计划(索引失效、回表多、锁等待
innodb_row_lock)。 - 依赖方:下游 RPC P99、第三方接口(对方限流/降级了没)。
解决思路按成本从低到高
- 零成本:回滚最近变更、参数调优(连接池/线程池)
- 低成本:加索引、热点数据加缓存、减小报文/日志降级
- 中成本:串行调用并行化(CompletableFuture)、非核心链路异步化(MQ 削峰)
- 高成本:分库分表、架构重构——走到这步前必须证明前面手段都无效,我评审过太多"一慢就上分库分表"的过度设计
预防机制(架构师必须讲)
- 核心接口定 SLO(如 P99 < 500ms)+ 告警基线,慢了主动发现而不是用户投诉才知道
- 变更管控:发布必须灰度 + 可回滚,性能压测纳入发布卡点
- 容量巡检:大促前按预估流量 3 倍压测
一句话总结:接口性能问题的本质是容量供给与业务需求的错配,排查是技术活,但"什么时候投入多少优化"是业务账——转化率和资损风险决定优先级。
🏗 系统架构师
定位思路是分层二分:先定环节、再定组件、最后定语句,避免一上来就钻进代码。
一、定位慢在哪个环节
- 有链路追踪(我的标配):traceID 拉出 span 瀑布,网关、应用、MySQL、Redis、下游 RPC 各自耗时一目了然,通常 1 分钟内锁定"最厚的 span"。
- 没有 trace:用排除法分层看监控——入口 P99 高 + 应用内 RT 低,问题在接入层/队列;应用内 RT 高,继续下钻是 DB、缓存还是下游。
二、组件内定位
- DB:慢查询日志 +
explain,看全表扫描、索引失效(隐式类型转换、函数包字段、深分页 OFFSET)。 - JVM:arthas
trace到方法行级耗时;GC 日志排除停顿。 - 下游:看它的 P99 和熔断计数,确认是否重试放大。
- 锁/池:连接池、线程池水位是否排队(排队时间常被误认为"代码慢")。
三、解决思路按优先级
- 缓存:读多写少的数据加多级缓存(本地 Caffeine + Redis),1s 的 DB 查询可压到 1ms 级。
- 修 SQL/索引:覆盖索引、改游标分页、拆大事务。
- 异步化:非关键路径(通知、积分、日志)扔 MQ,同步链路只留主干。
- 并行化:串行调下游改
CompletableFuture并行,RT 取最大值而非求和。 - 扩容限流:容量不够就水平扩,扩不动就限流保命。
最后必须闭环:建立优化前后的 P99 基线对比 + 持续告警,没有度量就没有优化——这是我作为架构师反复强调的纪律。
💻 全栈开发专家
先定位慢在哪一层,再对症下药,不上来就猜代码。
第一步:全链路定位
- 有 SkyWalking/Zipkin 直接看 trace 瀑布图,慢在哪个 span 一目了然:网关、应用自身、DB、Redis 还是第三方 HTTP。
- 没链路追踪时,用网关/access log 的时间戳差值粗定位,再到应用里用 Arthas
trace com.xxx.Service method -n 5 '#cost > 100'逐层打印每行耗时。
第二步:按层排查
- 慢 SQL:开慢查询日志(
long_query_time=0.2),EXPLAIN看全表扫描/索引失效(隐式类型转换、函数包字段、最左前缀不满足)。 - 锁等待:
SELECT * FROM information_schema.INNODB_TRX看长事务;应用层的 synchronized/分布式锁竞争看 jstack BLOCKED 线程。 - 远程调用:连接池不够(排队)、超时重试放大、下游本身抖动。
- GC 停顿:
jstat -gcutil看 FGC 频率,RT 毛刺常是 Full GC。
解决思路
缓存(Redis/本地 Caffeine)挡读、索引优化、串行调并行(CompletableFuture)、大接口拆分异步化、池化参数调优。
我踩过的坑 一次接口 800ms,最后发现是 HikariCP maximumPoolSize=10,高峰期 200 个请求在排队等连接——连接池等待不会出现在业务日志里,必须看监控指标 hikaricp.connections.pending。