JMX 远程JVM监控
概述
当线上服务器发生JVM相关问题的时候,能够监听内存、CPU、线程、类加载 等指标就非常重要。目前容器设计使用了arthas监控,命令行界面不太友好且容器挂了后arthas进程也挂了,因此开始调研JMX远程监控JVM方式。
参考文档
https://docs.oracle.com/cd/E19698-01/816-7609/6mdjrf86t/index.html
JMX协议
JMX(Java Management Extentions)技术提供了一系列工具,使用这些工具我们可以构建用于管理和监控设备与应用的解决方案。JMX 从 Java5 开始包含在 JDK 里发布。
JMX局限性
1、JMX 协议对NAT网络、防火墙不友好,内部通讯机制会传递内网的ip到客户端导致无法正常连接;
2、只能在问题发生后,再开启JMX远程监控,解决问题比较滞后;
3、需要配合客户端工具jconsole、JVisualVM等工具监控;
Java应用开启JMX监控
通过追加JVM-D参数开启JMX
-Djava.rmi.server.hostname=0.0.0.0 -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
以上方式没有开启认证,存在安全问题,禁止在生产环境采用该方式。
service:jmx:rmi:///jndi/rmi://127.0.0.1:12345/jmxrmi
注意:JMX局限性考虑,只能在内网使用该方案监控。【适合本地使用】
开启认证-密码模式
开启密码后,默认会加载$JAVA_HOME\jre\lib\management\jmxremote.password
-Dcom.sun.management.jmxremote.authenticate=true
手动指定密码配置文件
-Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=/app/jmxremote.password
JMXMP 协议
JMXMP 全称为 JMX Messaging Protocol,它的安全设施比 RMI 更加高级。请回顾下前文引用的 JMX 三层架构图,Remote Management Level 中的 RMI 是可以替换为 JMXMP 协议的。
在 JMXMP connector 里面,server 和 client 之间的通信依赖一条单独的 TCP 连接,每一条消息都是一个序列化的 Java 对象。而且,server 和 client 之间的通信分为两个流,每个流负责一个方向,这允许我们在任意时刻在这条连接上发送多个并发的请求给 server。
JMXMP开启后,TCP端口能够在公网上直接使用,但需要注意添加认证。
开发JMXMP暴露监控端口
org.jvnet.opendmk jmxremote_optional 1.0_01-ea
通过注册SpringBean启动JMXMP协议。
package com.panzhi.tech.common.core.jmxmp; import com.panzhi.tech.common.core.jmxmp.config.JMXProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import javax.annotation.Resource; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import java.io.IOException; import java.lang.management.ManagementFactory; /** * JMXMP 监控 * * @author marker */ @Slf4j public class JMXMPService implements DisposableBean, InitializingBean { private JMXConnectorServer jmxConnectorServer; @Resource private JMXProperties jmxProperties; // 这里配置host:port 0.0.0.0:8001 /** * afterPropertiesSet * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { if (Boolean.FALSE.equals(jmxProperties.getEnabled())) { return; } try { JMXServiceURL url = new JMXServiceURL(null, jmxProperties.getHost(), jmxProperties.getPort()); jmxConnectorServer = JMXConnectorServerFactory .newJMXConnectorServer(url, null, ManagementFactory.getPlatformMBeanServer()); // 启动监控服务 jmxConnectorServer.start(); } catch (IOException e) { log.error("JMX MP初始化失败", e); } } @Override public void destroy() throws Exception { if (Boolean.FALSE.equals(jmxProperties.getEnabled())) { return; } jmxConnectorServer.stop(); } }
jvisualvm链接JMXMP端口
jvisualvm命令中需要添加-cp:a加载 jmxremote_optional-1.0_01-ea.jar包或拷贝到lib/ext目录下。
方式一(推荐)
将文件拷贝到 $JAVA_HOME\jre\lib\ext 目录下,启动jvisualvm.exe。
方式二
D:\SDK\JDK1.8\bin> jvisualvm.exe -cp:a D:\SDK\JDK1.8\lib\jmxremote_optional-1.0_01-ea.jar
开启jvisualvm后,点击【】添加JMX链接,输入链接地址,勾选不要求SSL点击【确定】
service:jmx:jmxmp://10.233.90.6:8001
JMXMP开启认证?
后期有时间再解决,待解决
通过JVM参数开启JMXMP
通过环境变量开启JMXMP,由于安全问题未解决,需要关注的时候在开启,不需要使用则关闭。
JAVA_JMX_OPTS="-Dmanagement.jmxmp.enabled=true -Dmanagement.jmxmp.host=0.0.0.0 -Dmanagement.jmxmp.port=8001"
当环境变量配置在JVM 启动参数中后,8001端口将开启,如果是容器跑的,在容器内部开启8001。需要将8001端口映射到宿主机才能够访问到JMXMP监控信息。
使用JVisualVM
JVisualVM链接上JMX的效果
监控 CPU& 内存
注意:重点禁止点击【堆dump】,它会使用这个应用卡死,并且传递这个内存的数据占用网络资源。
监控线程
这里的线程监控没有到具体类,也没有top功能,建议还是使用arthas监控thread,可以做到TOP10 的CPU消耗线程。
实时监控GC情况
需要安装visual GC 插件,需要JDK支持,镜像的openjdk不支持