【发布时间】:2015-09-12 10:52:35
【问题描述】:
我们正在运行grpc-java 0.8.0 版服务器来处理远程调用。服务端逻辑很简单,就是从 DB 中获取给定 id 指定的数据,并设置到redis 缓存中。
JVM 参数配置为-Xss256k -Xmx8G。一旦服务器启动并处理大约 400 QPS,JVM 就会占用 4GB(top 中的 RES)内存。我发出 jmap 命令jmap -histo:live <pid> 并得到以下转储文件:
num #instances #bytes class name
----------------------------------------------
1: 4998400 119961600 io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry
2: 212415 23503536 [B
3: 11076 20170816 [Lio.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry;
4: 70853 10010904 [C
5: 28819 2518640 [Lio.netty.util.Recycler$DefaultHandle;
6: 31232 1998848 com.mysql.jdbc.ConnectionPropertiesImpl$BooleanConnectionProperty
7: 7287 1764136 [I
8: 70000 1680000 java.lang.String
9: 45766 1464512 java.util.Hashtable$Entry
10: 134 1291992 [D
11: 14376 1265088 io.netty.buffer.PooledUnsafeDirectByteBuf
12: 5527 1160200 [Ljava.util.HashMap$Node;
13: 16340 1116584 [[B
从中我们可以看到有大量 io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry 实例占用了大约 100MB 内存。 (注意grpc 使用netty 作为其通信层。)这似乎是不正常的。即便如此,堆内对象也无法占用 4GB 内存。这一定是由于堆外内存使用情况,例如netty 使用的直接缓冲区。
是否存在堆外内存泄漏?
为什么会发生这种情况?以及如何解决或诊断此问题?
【问题讨论】:
-
您使用的是哪个版本的 grpc-java? PooledUnsafeDirectByteBuf 的数量看起来很合理。我想知道这是否是 PoolThreadCache 的问题。机器有几个核心?当您说“4G 内存”时,您是如何衡量的?
-
@EricAnderson 我正在使用 grpc 0.8.0,在
top中观察到 4GB 内存消耗,RES字段。 -
嗯...你能试试 Netty 4.1 Beta6(组 io.netty,神器 netty-codec-http2,版本 4.1.0.Beta6)。 0.8.0 使用了 Beta 5,而 Beta 6 包含了改进 gRPC 的优化。我认为这可能会改善您的情况:github.com/netty/netty/commit/…
-
@EricAnderson 我已经用 netty 4.1 beta6 升级到了 grpc 0.9.0 并得到了显着的改进。谢谢你的建议。
标签: java memory-leaks netty heap-memory grpc