ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

为什么你的后端接口总是超时?

为什么你的后端接口总是超时? 数据库是最常被忽略的堵点一条没走索引的SQL在数据量小的时候跑得飞快。订单表过了千万行WHERE status 1 AND create_time 2024-01-01这种查询直接全表扫描单次执行8秒。接口里调了三次24秒没了。更隐蔽的是锁等待一个事务更新了某行数据迟迟不提交另一个请求去读同一行被锁挡住线程挂在那里连接池很快被占满。慢查询是慢性病锁等待是急性发作两者都足以让接口原地瘫痪。上线前用explain看一眼执行计划比事后救火划算得多。外部依赖是隐形杀手你的接口调了用户中心、风控服务、推荐引擎。用户中心响应200毫秒风控服务偶尔抽风到5秒推荐引擎超时时间设了30秒。一次请求串行调用三个服务最慢的那个决定整体耗时。更可怕的是没设超时。HTTP客户端默认超时可能是无限RPC框架默认超时可能是3秒但对方服务卡住时你的线程就一直等。一个没有超时设置的远程调用等于把自家线程的命交到别人手里。每个外部依赖都必须设连接超时和读取超时且要短于上游给你的超时预算。线程池与连接池配置不当就是自埋地雷数据库连接池最大20个连接接口QPS到50每个请求占用连接200毫秒20个连接每秒只能支撑100个请求。排队开始等待时间指数上升。线程池核心线程数太小任务队列无界请求堆积内存暴涨。拒绝策略用了CallerRunsPolicy结果Tomcat线程被拖去执行慢任务整个容器卡死。池子是稀缺资源不是越大越好是要和下游承载能力匹配。压测时盯着池子的活跃数、队列长度、等待时间比看CPU有意义。GC停顿和锁竞争JVM层面的暗流年轻代太小对象频繁晋升到老年代Full GC一触发整个应用停顿几秒。这几秒内所有接口全部超时。锁竞争更隐蔽一个synchronized方法被高频调用线程排队等锁等到的线程执行时间不长但排队时间远超执行时间。用jstack抓线程栈看到大量BLOCKED状态就知道锁是瓶颈。JVM不是黑盒GC日志和线程栈是它写给开发者的信只是很多人从不拆开看。超时时间层层叠加上游等下游下游等更下游网关超时5秒你的服务超时10秒你调的RPC超时15秒RPC调的数据库超时20秒。上游早断了下游还在跑。超时设置要像漏斗越往下越短而不是反过来。网关给5秒你的服务最多4秒RPC最多2秒数据库最多1秒。留出余量让最内层先失败外层才能优雅降级。否则线程全卡在等下游上游连接池耗尽雪崩就是这么来的。排查超时别只盯着接口本身。链路追踪看哪个span耗时最长慢查询日志找执行超时的SQLjstack看线程卡在哪GC日志看停顿频率。接口超时是症状病因在数据库、在外部调用、在池子配置、在JVM、在超时链路。头痛医头脚痛医脚重启一百次也治不了根。把每一个环节的耗时和资源占用摸清楚超时自然无处藏身。系统不会撒谎它只是用超时告诉你这里堵了。
返回列表