-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
heavyrian2012
committed
Oct 8, 2024
1 parent
5059455
commit 3be2a73
Showing
3 changed files
with
31 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,4 @@ | |
* [超级群组](超级群组.md) | ||
* [音视频高级版的单端口化和强制TCP化](音视频高级版的单端口化和强制TCP化.md) | ||
* [物联网设备的接入](物联网设备的接入.md) | ||
* [内存泄漏排查](内存泄漏排查.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# 内存泄漏检查 | ||
野火这么多年以来基本上没有遇到过内存泄漏问题,唯一一个客户联系不是特别顺畅,只是说内存增长很多,但堆内存没有变化,怀疑是堆外内存泄漏,但后来也失去了联系。我们自己也尝试在本地来复现堆外内存泄漏,包括在我们上线的测试环境中测试,没有办法来复现这个问题。我们怀疑是可能不同JDK发行版本或者是某个linux发行版本差异导致的,但还需要继续处理这个问题。因此我们写下此文档以便有客户出现问题时,能够检查此问题。如果出现内存泄漏问题请及时联系我们。 | ||
|
||
## java应用的内存构成 | ||
java开发都非常熟悉Xmx,Xms等参数,这个是对JVM的内存的控制。一个Java应用首先是一个Linux应用(假设在linux系统下),其中包含一大块给虚拟机的内存,所有编写的java代码都在这块内存中。但也有例外,可以申请到jvm以外的内存,也就是堆外内存。Javer常见的堆外内存就是Netty的堆外内存。除了这个以外,还可能有些代码使用JNI分配到非堆内存。也有可能使用自定义的classloader使用不到导致占用非堆内存。等等很多可能的原因。 | ||
|
||
## Netty堆外内存的检查 | ||
Netty有完善的堆外内存检查方法,在野火IM启动脚本wildfirechat.sh 最后一行启动命令中,添加一个参数```-Dio.netty.leakDetectionLevel=PARANOID```,加完之后的命令可能如下: | ||
``` | ||
$JAVA -server $JAVA_OPTS $JAVA_OPTS_SCRIPT -Dio.netty.leakDetectionLevel=PARANOID -Dlog4j.configurationFile="file:$LOG_FILE" -Dlog4j2.formatMsgNoLookups=true -Dcom.mchange.v2.c3p0.cfg.xml="$C3P0_CONF_FILE" -Dhazelcast.configuration=$HZ_CONF_FILE -Dwildfirechat.path="$WILDFIRECHAT_CONFIG_PATH" -cp "$WILDFIRECHAT_HOME/lib/*" cn.wildfirechat.server.Server | ||
``` | ||
参数```PARANOID```会对每一个堆外的内存分配进行跟踪,会消耗一定的资源。如果担心影响正常的业务,可使用参数```ADVANCED```,这个参数会做1%的抽查,能够做到基本无影响。 | ||
|
||
当有内存泄漏被检查到时,就会打印到日志中。从日志中搜索```LEAK```就能看到。 | ||
|
||
## NMT(Native Memory Tracking) | ||
JVM提供了Native Memory Tracking(NMT)功能,可以跟踪非JVM管理的内存。在野火IM的启动脚本```wildfirechat.sh```中,最后一行启动命令之前添加```JAVA_OPTS="$JAVA_OPTS -XX:NativeMemoryTracking=detail"```,用来开启NMT功能。应用运行一段时间进入平稳期后,执行命令```jcmd <pid> VM.native_memory detail```打印出非堆内存的详细信息并保存。等到问题出现后,再打印出非堆内存的情况,并把这两次的结果发给野火来分析。 | ||
|
||
## 开启GC日志 | ||
GC日志也会提供一些有效的信息,在野火IM的启动脚本```wildfirechat.sh```中打开下面这几行配置 | ||
``` | ||
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails" | ||
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps" | ||
JAVA_OPTS="$JAVA_OPTS -XX:+PrintHeapAtGC" | ||
``` | ||
这样在控制台就会打印出GC的详细情况。 | ||
|
||
## 业务使用情况 | ||
野火提供有非常多的server api和客户端api,大部分客户只用到其中一个子集。所以也不排除是使用了某个不常用接口导致的,所以当出现这个问题后,也需要把野火IM的日志发给我们分析,看一下都调用了哪些接口。 |