本文以线上某用A提供的接口调用超时问题为契机,分析接口超时的几种原因,并针对此次因gc停顿时间较长导致三方请求超时问题进行优化,从而保证系统稳定性。
1. 问题背景
应用A提供了销售可售库存查询基础能力,应用B是该能力使用方之一。2022-10-10 11:36:12和2022-10-11 10:28:42时间点分别偶发出现接口超时问题。
该接口rt平均在11ms左右,整体性能较好,由于该接口是基础查询能力,为商品展示及下单等核心链路提供查询能力,且流量占比较高,影响面较广,问题出现后,我们紧急排查分析。
2. 原因分析
RPC服务调用方反馈服务有时会有超时,查看监控平台发现有客户端调用超时,调用方的超时时间设置为 6s。接口超时问题一般有如下几个原因。
2.1 常见原因概述
1. 接口性能差
一般接口性能差,可能由于程序中循环进行数据库操作,亦或是存在慢sql,导致客户端超时。针对这种情况,一般需要对程序设计进行优化,如通过批量查询减少循环操作数据库,同时通过sql优化、增加或变更索引等方式,提高sql执行效率。
2. 请求没命中缓存
通过使用缓存,我们可以大大提高程序响应速度,如果缓存失效且有大量请求时,所有压力集中在数据库,也可能会导致客户端超时。这种情况,我们可能需要通过缓存失效时间优化、多级缓存或者本地缓存等降低缓存miss情况。
3.资源竞争瓶颈
这种情况一般是请求过多,而应用机器性能与请求总量不匹配,cpu资源竞争激烈。这种情况一般需要进行服务容量评估,结合线上应用机器监控,增加机器或者对升级应用机器。
4.请求处理线程少
RPC服务请求处理线程太少,大量请求在队列中等待处理,导致客户端超时。
5.GC 时业务线程停顿,导致客户端超时
主要是GC时出现STW,导致客户端超时。gc时出现STW属于正常现象,如果时间较长,会影响客户端正常请求,需要进一步分析原因。
2.2 根因分析
我们对照2.1中常见原因中前四种进行对照,并不属于常见原因概述范围之中。通过应用机器监控,我们发现其中一台机器有一些异常,如图。
从图中我们可以看出应用并没有发生full gc,但是确有10s钟停顿时间,并且是偶发现象,对于这种问题一般只能通过分析这个时间点gc日志,找出耗时时间较长的那段gc日志(分析过程略去)。通过分析发现,gc remark阶段gc耗时较长。
3.问题解决
对于unloading时间耗时长这个问题,我们也通过一番推导与对比,最终确认了与应用机器配置swapiness有关(默认配置是60,出现问题的机器没有做更改,新机器默认是30)。具体可参考一篇不错的博文 JVM性能调优案例01:Unloading时间太长 。我们将swapiness由60修改到10,并持续观察了一段时间,发现耗时由最高的10s降到0.1s左右,大大降低了STW停顿时长问题。
4.经验总结
-
对于偶发的超时问题,一定要引起重视并去解决,否则在大流量情况下如大促期间,可能会对业务产生影响;
-
操作系统为了保证系统的安全,会把长期不活跃的数据(垃圾数据)移到Swap。 等到GC到来时,就需要把这些数据swap in,产生Swap洪峰,延长了GC耗时。如果堆内存较大,尽量避免使用swap,可以将swapiness参数降为1,避免内存swap到磁盘去导致gc时间变长;