使用Java自带的VisualVM监控远程服务器摆设在Docker容器中的Java项目并使用 ...

打印 上一主题 下一主题

主题 551|帖子 551|积分 1653

事情是如许的,我们项目最近应业主的要求迁移到了新的服务器,起月朔切正常,摆设、上线、测试都没有问题,项目大概运行了一周的工作日时间都没出现问题,直到周六那天,项目经理打电话过来说服务器崩了,图片上传不了,验证码加载不出来等各种问题。。。然后火速连到服务器docker stats --no-stream查看了一下Docker 命令中用来体现容器资源利用情况,发现这个Java服务一直在持续的上涨到15G左右(正常也就几百兆),以至于涨到服务器挂掉了。。。额,我初步怀疑是定时任务太多的问题。

于是我立刻咨询单位里履历比力丰富的大佬,让我去监控一下程序的进程,内存使用等情况。如果暂时使用的话,就让我暂时处理的话就新建一个boot项目,把定时任务都丢里面去构建一个jar,直接在服务器里java -jar跑。这个方法可能可以维持一段时间,由于本质问题还没得到办理,后面还是会出问题。于是我去上网搜了一下有个JDK文件夹里叫VisualVM的工具可以及时监控。

有时候程序内存溢出或者做压力测试的时候我们就需要监控我们的程序的运行状况,包罗内存使用情况、CPU使用情况等等,VisualVM就是监控这些数据的一个很好的工具。

下面我将教大家怎么连到Docker容器中的Java服务进行及时监控
1.修改docker-compose.yml文件

在文件中添加连接端口,这里设置成1199

2.修改Dockerfile文件

添加配置
-Djava.rmi.server.hostname = xxx.xxx.xxx.xxx 指定宿主机的公网ip
-Dcom.sun.management.jmxremote.port = xxxx 用于Java VisualVM远程监控的端口
-Dcom.sun.management.jmxremote.rmi.port = xxxx 指定用于Java VisualVM远程监控的端口”需要挂载到宿主机的哪个端口
-Dcom.sun.management.jmxremote.authenticate = true | false 配置是否需要验证,如果true,则在使用Java VisualVM连接的时候需要你认证账号密码
-Dcom.sun.management.jmxremote.ssl = true | false 不指定ssl
  1. ENV JAVA_OPTS="-Djava.rmi.server.hostname=192.168.1.140 -Dcom.sun.management.jmxremote.port=1199 -Dcom.sun.management.jmxremote.rmi.port=1199 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
复制代码

或者如许

3.开放端口1199

因每个服务器都有不同的设定,我这边是业主自行搭的服务器,通过路由控制的,需要路由那里开放1199端口。还有就是保证防火墙也给予端口开放状态,否则将无法连接!如果你是阿里云服务器,则去阿里云资源管理中的安全组进行端口的开放。
4.实验连接Docker中的Java服务

完成下面两个步调即可连接


5.分析Java服务的各项指标

这里是运行9分钟的时候的截图,这时CPU已经100%了,不知道是软件的问题还是什么情况。

这里是运行了15小时左右的截图,在这里发现了启动线程数总数2w多,以及CPU占用率100%,很大的概率存在内存走漏。

如VisualVM工具使用JMX连接GC出现不受此jvm支持,请看下面这篇教程怎样办理
https://developer.aliyun.com/article/1402853
当然,我们也可以使用jdk自带的jconsole工具类进行分析

连接方式与VisualVM一样,也是IP加端口

6.使用mat工具分析内存溢出、内存走漏问题

软件下载安装:
自行下载安装,可以看这篇教程:https://blog.csdn.net/wts563540/article/details/132380827
mat工具下载地址:https://www.eclipse.org/mat/downloads.php
导出堆文件:
如果你的 Java 应用程序是在 Docker 容器中运行的,你可以通过以下步调来获取容器内 Java 进程的 PID,并使用 jmap 或 jcmd 工具获取堆 dump:
获取容器内 Java 进程的 PID:首先,你需要进入正在运行 Java 应用程序的 Docker 容器中。你可以使用以下命令来实行一个暂时的交互式 Shell,以便实行后续的命令:
  1. docker exec -it <container_id> /bin/bash
复制代码
将 <container_id> 替换为你的容器 ID。
在容器内部获取 Java 进程的 PID:在容器内部实行以下命令来获取 Java 进程的 PID:
  1. jps
复制代码
这将列出容器内运行的 Java 进程及其对应的进程 ID。
   使用 jmap 或 jcmd 工具获取堆 dump:在容器内部,使用得到的 Java 进程 PID 来实行 jmap 或 jcmd命令,如前面提到的那样。确保你在容器内部已经正确设置了 JDK 的情况变量,并且具有充足的权限来实行这些命令。
  使用 jmap 工具获取堆 dump:打开命令行终端,输入以下命令来获取堆 dump:
  1. jmap -dump:format=b,file=heapdump.hprof <pid>
复制代码
将 <pid> 替换为你要获取堆 dump 的 Java 进程的进程 ID。实行该命令后,将会生成一个名为 heapdump.bin 的堆 dump 文件。
使用 jcmd 工具获取堆 dump:打开命令行终端,输入以下命令来获取堆 dump:
  1. jcmd <pid> GC.heap_dump heapdump.hprof
复制代码
将 <pid> 替换为你要获取堆 dump 的 Java 进程的进程 ID。实行该命令后,同样会生成一个名为 heapdump.bin 的堆 dump 文件。
将堆 dump 文件从容器中复制到宿主机:获取到堆 dump 文件后,你可能希望将文件从容器中复制到宿主机上进行分析。你可以使用 docker cp 命令来实现这一点,比方:
  1. docker cp <container_id>:/path/to/heapdump.hprof /path/on/host/heapdump.hprof
复制代码
其中 /path/to/heapdump.hprof 是容器内的堆 dump 文件路径,/path/on/host/heapdump.hprof 是宿主机上的目标路径。
接着我们使用mat工具打开:有可能会打不开。。。我暂时没找到办理办法。。。

别急,还有在线版的工具来分析内存溢出、内存走漏。在线地址:https://heaphero.io/heap-index.jsp#header

这个在线版也可以进行分析,但是并没有mat工具那么具体!
我使用这个在线版分析了我导出的堆文件,导入后可以看到分析出来的结果陈诉,下面有更具体的信息我就不展示了。

额。。。意思是这个对象被持续加载了11w个

我还在郁闷到底是谁写的那么史的代码,当我打开代码看了一下发现小丑竟然是自己。。。。。。。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表