Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
heavyrian2012 committed Oct 8, 2024
1 parent 5059455 commit 3be2a73
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions md/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,4 @@
* [音视频高级版的单端口化和强制TCP化](blogs/音视频高级版的单端口化和强制TCP化.md)
* [数据库重复消息ID的问题](blogs/数据库重复消息ID的问题.md)
* [物联网设备的接入](blogs/物联网设备的接入.md)
* [内存泄漏排查](blogs/内存泄漏排查.md)
1 change: 1 addition & 0 deletions md/blogs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@
* [超级群组](超级群组.md)
* [音视频高级版的单端口化和强制TCP化](音视频高级版的单端口化和强制TCP化.md)
* [物联网设备的接入](物联网设备的接入.md)
* [内存泄漏排查](内存泄漏排查.md)
29 changes: 29 additions & 0 deletions md/blogs/内存泄漏排查.md
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的日志发给我们分析,看一下都调用了哪些接口。

0 comments on commit 3be2a73

Please sign in to comment.