详解SpringCloudGateway内存泄漏问题

网友投稿 1632 2022-11-30


详解SpringCloudGateway内存泄漏问题

SpringCloudGateway内存泄漏问题

项目完善差不多,在进入压力测试阶段期间,发现了gateway有内存泄漏问题,问题发现的起因是,当时启动一台gateway,一台对应的下游应用服务,在压力测试期间,发现特别不稳定,并发量时高时低,而且会有施压机卡住的现象,然后找到容器对应的宿主机,并使用container stats命令观察内存,经过观察发现,压力测试时内存会暴涨,并由于超过限制最大内存导致容器挂掉(这里由于用的swarm所以会自动选择节点重启)最终发现由于之前测试服务器配置低,所以限制了堆大小为1g,容器cpu 1,容器内存限制为了1g,经过调整后将内存改为4g且不限制容器资源的情况下,并发稳定,单机qps也不错,但是多次压力测试后依然会有卡住的问题,观察了日志之后确定为内存泄漏

io.netty.util.internal.OutOfDirectMemoryError:

failed to allocate 16777216 byte(s) of direct memory

(used: 4110417927, max: 4116185088)

- LEAK: ByteBuf.release() was not called before it's garbage-collected.

发现问题之后,我进入容器内dSSSpMump了内存快照,并下载到本机由jvisualvm分析,分析过程中并没有发现异常情况,由于gateway底层是netty,所以怀疑是堆外内存出了问题,这时候我从快照中查询bytebuff,依然很小,后来直接使用arthas去线上分析,分析发现堆内存正常,gc也没有问题

最后为了快速测试出异常,我调小了堆外内存大小,并配合nmt调查

-XX:NativeMemoryTracking=detail -XX:MaxDirectMemorySize=100M

在线上使用pmap去查看内存,发现了很多的anon,并且每次并发都会增长

转移到本地进行测试,发现内存远超出分配的堆大小,最终确定为堆外内存出了问题

既然是堆外内存出的问题,我们就只关心是否申请了buff没有释放,通过对代码的检查发现,只有两个地方使用到了相关的内容

DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);

return serverHttpResponse.writeWith(Flux.just(buffer));

对上面的代码进行大量压测后发现并无问题,内存没有异常增长不回收

ServerHttpRequest httpRequest = exchange.getRequest().mutate().headers(httpHeaders -> {

httpHeaders.add(GatewayConstants.LOGIN_USER_KEY, jsON.toJSONString(s));

}).build();

return chain.filter(exchange.mutate().rehttp://quest(httpRequest).build());

还有一处就是修改请求头这部分代码,当注释掉这部分时,内存稳定没有异常增长,当放开时,3000并发几乎增加800M内存,几次就怼到了5g+,由于gateway内置了一个请求头工厂(AddRequestHeaderGatewayFilterFactory),我去查看对应的源代码,是怎么实现的

如图,除了多了解析配置之外和我写的基本也一样,那为何会内存异常呢?只能去github上找找问题看看有人遇到相同的事没。

这个老哥遇到的问题也类似,他是修改请求体的内容时出现的

这个问题我也遇到了

看起来这个问题还是挺严重的,最后我也反手提了一个问题

没有啥回答,最后还是参考了一些别人的写法最后内存不会飙升了,但是不知其为何,还得继续调查


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详细分析Java Lambda表达式
下一篇:JAVA Static关键字的用法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~