记一次中间件内存泄露问题排查

场景:

业务接口开发完毕,压测性能非常不稳定。调用链路是:

压力机Jmeter ----> api网关 ----> 业务接口

现象就是,平均rt基本在300ms左右,偶尔短暂的时间内,可以降低到预计的70ms。由于经验并不丰富,只能从头到尾慢慢排查。

排查思路:

第一反应是,网关本身产品不会有问题,先排查业务侧:

  • top看每个核心使用率不高、load在1左右、free看内存空闲很多

  • 排查业务的sofa线程池日志,线程池等待时间为0,说明线程状态空闲

  • 启动arthas,调出dashboard

    • 堆内存使用不高

    • 线程几乎都是空闲的

    • ygc频率高,但是暂停时间都是5毫秒左右,fgc没有。不可能是gc造成的秒级延迟

  • arthas监控了一下接口的调用,由于业务自定义了rpc的filter,而且filter里面大量使用反射,所以从FilterChain的入口开始monitor,发现平均rt在50毫秒左右

  • 然后tcpdump抓了包,发现响应时间在60毫秒以内,基本排除了业务测的问题,开始怀疑是api网关出现问题

接着开始排查api网关:

  • 登录rms日志监控平台,检查网关容器的使用情况:

    • CPU使用较为平稳

    • 内存占用非常高,3个容器中有两个均达到了80%

开始怀疑是否是网关内存占用过高导致。由于api网关基于蚂蚁开源的mosn开发,组里没有一个懂go语言的,只能定性地去做测试来进一步判断。

下面开始对网关进行定性地分析:

  • 找到唯一那台内存使用较低的网关节点,进行单节点压测,发现响应时间均在预期的70ms内,响应时间曲线较为平稳。

  • 找到其他内存使用较高的节点,进行单节点压测,发现响应时间回到300ms,曲线及其不稳定

初步可以得出是网关的问题。

分析:

3个网关容器,2台响应慢,1台响应快、由于我们压测时,使用的是3个节点共同的F5地址,可能存在某种负载算法,使得我们大部分时间请求的是内存高的网关节点,导致响应时间慢,曲线波动大,一小部分时间段内,请求的是内存低的网关节点,响应时间快,曲线波动不明显!

我们知道go和java一样,也是存在gc机制的,运行一段时间,尤其是经过一段时间的压测,发现内存越来越高,只能说明网关发生了内存的泄露,可能和java类似,每次gc都有泄露的对象被残留,积少成多,而我们的压测,逐渐加剧了这个情况。

后续:

已经联系网关的研发同学,确实存在内存泄露问题,需要我们提供dump文件进行分析,并在后续迭代的版本中进行解决。

你可能感兴趣的:(java,分布式,中间件,微服务)