在启动参数中增加如下配置:
-Djava.rmi.server.hostname=ip
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1199
-Dcom.sun.management.jmxremote.authenticate=false //关闭权限校验
-Dcom.sun.management.jmxremote.ssl=false//关闭ssl校验
这里我们没有启用权限验证,如何进行权限验证,请自行搜索。
如图:在远程中,右键添加远程主机,输入主机ip,确定后,在主机ip上右键选择jmx连接,输入配置的端口即可。
如果你是部署在docker一样的容器中,那么恭喜你,你将看到如下报错:
你没看错,这就是网上常说的 无法使用service:jmx:rmi:///jndi/rmi://ip:port/jmxrmi连接到ip:port错误。
在你尝试了网上说的,hostname-i确认修改,等手段后,你会发现最终指向的是jmx在主进程外,启动的默认服务端口是随机的。而我们的docker容器无法动态映射这个端口。还有说这是jdk5的失误。
事实上,确实是由于这个服务端口是随机生成的,导致我们请求注册服务后,返回的服务调用不通导致,但是是不是真的无法配置呢?看源码:
public JMXConnectorServer(MBeanServer mbeanServer) {
this.mbeanServer = mbeanServer;
}
public static synchronized JMXConnectorServer startRemoteConnectorServer(String var0, Properties var1) {
int var2;
try {
var2 = Integer.parseInt(var0);
} catch (NumberFormatException var29) {
throw new AgentConfigurationError("agent.err.invalid.jmxremote.port", var29, new String[]{var0});
}
if (var2 < 0) {
throw new AgentConfigurationError("agent.err.invalid.jmxremote.port", new String[]{var0});
} else {
//这里的var3就是rmiurl中服务端要设置的地址。我们可以看到如果没有设置的话按照0处理,也就是随机值,这个值也可以通过-Dcom.sun.management.jmxremote.rmi.port指定。至此我们就解决了随机端口的问题
int var3 = 0;
String var4 = var1.getProperty("com.sun.management.jmxremote.rmi.port");
try {
if (var4 != null) {
var3 = Integer.parseInt(var4);
}
} catch (NumberFormatException var30) {
throw new AgentConfigurationError("agent.err.invalid.jmxremote.rmi.port", var30, new String[]{var4});
}
if (var3 < 0) {
throw new AgentConfigurationError("agent.err.invalid.jmxremote.rmi.port", new String[]{var4});
} else {
String var5 = var1.getProperty("com.sun.management.jmxremote.authenticate", "true");
boolean var6 = Boolean.valueOf(var5);
String var7 = var1.getProperty("com.sun.management.jmxremote.ssl", "true");
boolean var8 = Boolean.valueOf(var7);
String var9 = var1.getProperty("com.sun.management.jmxremote.registry.ssl", "false");
boolean var10 = Boolean.valueOf(var9);
String var11 = var1.getProperty("com.sun.management.jmxremote.ssl.enabled.cipher.suites");
String[] var12 = null;
if (var11 != null) {
StringTokenizer var13 = new StringTokenizer(var11, ",");
int var14 = var13.countTokens();
var12 = new String[var14];
for(int var15 = 0; var15 < var14; ++var15) {
var12[var15] = var13.nextToken();
}
}
String var31 = var1.getProperty("com.sun.management.jmxremote.ssl.enabled.protocols");
String[] var32 = null;
if (var31 != null) {
StringTokenizer var33 = new StringTokenizer(var31, ",");
int var16 = var33.countTokens();
var32 = new String[var16];
for(int var17 = 0; var17 < var16; ++var17) {
var32[var17] = var33.nextToken();
}
}
String var34 = var1.getProperty("com.sun.management.jmxremote.ssl.need.client.auth", "false");
boolean var35 = Boolean.valueOf(var34);
String var36 = var1.getProperty("com.sun.management.jmxremote.ssl.config.file");
String var18 = null;
String var19 = null;
String var20 = null;
if (var6) {
var18 = var1.getProperty("com.sun.management.jmxremote.login.config");
if (var18 == null) {
var19 = var1.getProperty("com.sun.management.jmxremote.password.file", getDefaultFileName("jmxremote.password"));
checkPasswordFile(var19);
}
var20 = var1.getProperty("com.sun.management.jmxremote.access.file", getDefaultFileName("jmxremote.access"));
checkAccessFile(var20);
}
String var21 = var1.getProperty("com.sun.management.jmxremote.host");
String var22 = var1.getProperty("com.sun.management.jmxremote.serial.filter.pattern");
if (log.debugOn()) {
log.debug("startRemoteConnectorServer", Agent.getText("jmxremote.ConnectorBootstrap.starting") + "\n\t" + "com.sun.management.jmxremote.port" + "=" + var2 + (var21 == null ? "" : "\n\tcom.sun.management.jmxremote.host=" + var21) + "\n\t" + "com.sun.management.jmxremote.rmi.port" + "=" + var3 + "\n\t" + "com.sun.management.jmxremote.ssl" + "=" + var8 + "\n\t" + "com.sun.management.jmxremote.registry.ssl" + "=" + var10 + "\n\t" + "com.sun.management.jmxremote.ssl.config.file" + "=" + var36 + "\n\t" + "com.sun.management.jmxremote.ssl.enabled.cipher.suites" + "=" + var11 + "\n\t" + "com.sun.management.jmxremote.ssl.enabled.protocols" + "=" + var31 + "\n\t" + "com.sun.management.jmxremote.ssl.need.client.auth" + "=" + var35 + "\n\t" + "com.sun.management.jmxremote.authenticate" + "=" + var6 + (var6 ? (var18 == null ? "\n\tcom.sun.management.jmxremote.password.file=" + var19 : "\n\tcom.sun.management.jmxremote.login.config=" + var18) : "\n\t" + Agent.getText("jmxremote.ConnectorBootstrap.noAuthentication")) + (var6 ? "\n\tcom.sun.management.jmxremote.access.file=" + var20 : "") + "");
}
MBeanServer var23 = ManagementFactory.getPlatformMBeanServer();
JMXConnectorServer var24 = null;
JMXServiceURL var25 = null;
try {
ConnectorBootstrap.JMXConnectorServerData var26 = exportMBeanServer(var23, var2, var3, var8, var10, var36, var12, var32, var35, var6, var18, var19, var20, var21, var22);
var24 = var26.jmxConnectorServer;
var25 = var26.jmxRemoteURL;
log.config("startRemoteConnectorServer", Agent.getText("jmxremote.ConnectorBootstrap.ready", var25.toString()));
} catch (Exception var28) {
throw new AgentConfigurationError("agent.err.exception", var28, new String[]{var28.toString()});
}
try {
HashMap var37 = new HashMap();
var37.put("remoteAddress", var25.toString());
var37.put("authenticate", var5);
var37.put("ssl", var7);
var37.put("sslRegistry", var9);
var37.put("sslNeedClientAuth", var34);
ConnectorAddressLink.exportRemote(var37);
} catch (Exception var27) {
log.debug("startRemoteConnectorServer", var27);
}
return var24;
}
}
}
重点看看这段代码:
int var3 = 0;
String var4 = var1.getProperty("com.sun.management.jmxremote.rmi.port");
try {
if (var4 != null) {
var3 = Integer.parseInt(var4);
}
} catch (NumberFormatException var30) {
throw new AgentConfigurationError("agent.err.invalid.jmxremote.rmi.port", var30, new String[]{var4});
}
对,你没看错默认是0,是随机端口,但是我们是可以通过-Dcom.sun.management.jmxremote.rmi.port参数指定的。
-Djava.rmi.server.hostname=ip
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.rmi.port=11199
-Dcom.sun.management.jmxremote.port=1199
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
同时将1199和11199端口映射到宿主机上即可。
到这里容器下的jmx监控就完成了。
jmx的参考资料
csdn的一个文章介绍