英文:
JMX Connection does not replay when running JMXConnectorFactory.connect
问题
需要您的帮助来理解为什么我无法从客户端应用程序连接到使用JMX的服务器应用程序。我有一个服务器应用程序,它初始化了一个JMX Bean服务器,而一个客户端正在尝试使用JMX连接到此服务器。这两个应用程序都在Windows的本地机器上运行。Jconsole工作得很好,我可以用它连接到服务器。但是当运行客户端时,它在以下行上“卡住”:
JMXConnector jmxConnector = JMXConnectorFactory.connect(url, null);
应用程序端JMX服务器初始化代码:
MyClass mc = new MyClass ();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName obj = new ObjectName("JMX:name=MyClassJmx");
mbs.registerMBean(mc, obj);
应用程序端JMX服务器JVM参数:
-Dcom.sun.management.jmxremote.port=10090
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
我连接到应用程序的客户端代码:
final JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://127.0.0.1:10090");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url, null);
jmxConnector.connect();
需要注意的是,使用以下方式可以工作:
service:jmx:rmi:///jndi/rmi://:10090/jmxrmi
英文:
Need your help to understand why I am unable to connect from a client application to a server application using JMX.
I have a Server application that is initiating a JMX Bean server and a client that is trying to connect to this Server using JMX. both app are ruining on local machine in windows.
Jconsole is working just fine and I am able to connect with it to the Server.
But when running the client it get "stuck" on line:
JMXConnector jmxConnector = JMXConnectorFactory.connect(url, null);
Application side JMX Server init code:
MyClass mc = new MyClass ();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName obj = new ObjectName("JMX:name=MyClassJmx");
mbs.registerMBean(mc, obj);
Application side JMX Server JVM params:
-Dcom.sun.management.jmxremote.port=10090
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
My client connection to Application code :
final JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://127.0.0.1:10090");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url, null);
jmxConnector.connect();
A note, using
service:jmx:rmi:///jndi/rmi://:10090/jmxrmi
is working.
答案1
得分: 0
JMX Messaging Protocol (JMXMP) 连接器是通用连接器的一种配置,其中传输协议基于TCP,对象封装使用本地的Java序列化。其安全性比RMI连接器更先进。安全性基于Java安全套接字扩展(JSSE)、Java身份验证和授权服务(JAAS)以及简单的身份验证和安全性层(SASL)。
通用连接器及其JMXMP配置是可选的,这意味着它们并不总是包含在JMX远程API的实现中。J2SE平台不包括可选的通用连接器。
注意:如果您想使用JMXMP连接器,请从http://java.sun.com/products/JavaManagement/download.html下载JSR 160参考实现,并将jmxremote_optional.jar文件添加到您的类路径中。
您是否已经在服务器和客户端类路径中包含了jmxremote_optional.jar
文件?
我没有使用JMXMP连接器的先前经验,我按照JMX文档进行了操作,并尝试通过编写以下示例进行了验证,它是有效的。
JMX MBean 接口
SystemConfigMBean.java
package jmx.learning;
public interface SystemConfigMBean {
public void setThreadCount(int noOfThreads);
public int getThreadCount();
public void setSchemaName(String schemaName);
public String getSchemaName();
public String doConfig();
}
实现 JMX MBean 接口的类
SystemConfig.java
package jmx.learning;
public class SystemConfig implements SystemConfigMBean {
private int threadCount;
private String schemaName;
public SystemConfig(int numThreads, String schema){
this.threadCount=numThreads;
this.schemaName=schema;
}
@Override
public void setThreadCount(int noOfThreads) {
this.threadCount=noOfThreads;
}
@Override
public int getThreadCount() {
return this.threadCount;
}
@Override
public void setSchemaName(String schemaName) {
this.schemaName=schemaName;
}
@Override
public String getSchemaName() {
return this.schemaName;
}
@Override
public String doConfig(){
return "No of Threads="+this.threadCount+" and DB Schema Name="+this.schemaName;
}
}
创建并在 MBean 服务器中注册 MBean,使用 JMXMP 连接器
SystemConfigManagement.java
package jmx.learning;
import java.io.IOException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
public class SystemConfigManagement {
private static final int DEFAULT_NO_THREADS = 10;
private static final String DEFAULT_SCHEMA = "default";
public static void main(String[] args) throws MalformedObjectNameException,
InterruptedException, InstanceAlreadyExistsException,
MBeanRegistrationException, NotCompliantMBeanException, IOException {
// 实例化 MBean 服务器
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
// 创建一个 JMXMP 连接器服务器
JMXServiceURL url = new JMXServiceURL("jmxmp", null, 5555);
JMXConnectorServer cs = JMXConnectorServerFactory
.newJMXConnectorServer(url, null, mbs);
cs.start();
// 注册 MBean
SystemConfig mBean = new SystemConfig(DEFAULT_NO_THREADS,
DEFAULT_SCHEMA);
ObjectName name = new ObjectName("jmx.learning:type=SystemConfig");
mbs.registerMBean(mBean, name);
do {
Thread.sleep(3000);
System.out.println("Thread Count=" + mBean.getThreadCount()
+ " Schema Name=" + mBean.getSchemaName());
} while (mBean.getThreadCount() != 0);
}
}
JMXMP 连接器客户端
SystemConfigManagementClient.java
package jmx.learning;
import java.io.IOException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class SystemConfigManagementClient {
public static void main(String[] args) {
JMXConnector jmxc = null;
try {
// 创建一个 JMXMP 连接器客户端
System.out.println("\nCreate a JMXMP connector client");
JMXServiceURL url = new JMXServiceURL(
"service:jmx:jmxmp://localhost:5555");
jmxc = JMXConnectorFactory.connect(url, null);
// 获取 MBeanServerConnection
MBeanServerConnection serverConn = jmxc.getMBeanServerConnection();
ObjectName objectName = new ObjectName(
"jmx.learning:type=SystemConfig");
// 执行 doConfig() 方法
String value = (String) serverConn.invoke(objectName, "doConfig",
new Object[] {}, new String[] {});
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jmxc != null) {
try {
jmxc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
注意:我已经下载了jmxremote_optional.jar
文件并将其放置在项目的类路径中。
执行:
服务器输出:
d:\Java\jdk1.8.0_261\bin\java.exe -cp .;d:\External_Library\jmxremote_optional.jar jmx.learning.SystemConfigManagement
Thread Count=10 Schema Name=default
Thread Count=10 Schema Name=default
客户端输出:
d:\Java\jdk1.8.0_261\bin\java.exe -cp .;d:\External_Library\jmxremote_optional.jar jmx.learning.SystemConfigManagementClient
Create a JMXMP connector client
No of Threads=10 and DB Schema Name=default
我对您编写的服务器代码不太确定,看起来该代码似乎期望RMI连接器。因此,从客户端使用 RMI 连接器的 Java 远程方法协议(JRMP)进行连接尝试是有效的。
即使您传递了属性 -Dcom.sun.management.jmxremote.port=portNum
,这个属性表明 portNum 是您希望通过其
英文:
The JMX Messaging Protocol (JMXMP) connector is a configuration of the generic connector where the transport protocol is based on TCP and the object wrapping is native Java serialization. Security is more advanced than for the RMI connector. Security is based on the Java Secure Socket Extension (JSSE), the Java Authentication and Authorization Service (JAAS), and the Simple Authentication and Security Layer (SASL).
The generic connector and its JMXMP configuration are optional, which means that they are not always included in an implementation of the JMX Remote API. The J2SE platform does not include the optional generic connector.
Note – If you want to use a JMXMP connector, download the JSR 160 Reference Implementation from http://java.sun.com/products/JavaManagement/download.html, and add the jmxremote_optional.jar file to your classpath.
Did you included jmxremote_optional.jar
file in your server and client classpath?
I don't have prior experience with JMXMP Connector approach, I followed JMX documentation and tried to verify by writing the following example and it works.
> JMX MBean interface
SystemConfigMBean.java
package jmx.learning;
public interface SystemConfigMBean {
public void setThreadCount(int noOfThreads);
public int getThreadCount();
public void setSchemaName(String schemaName);
public String getSchemaName();
// any method starting with get and set are considered
// as attributes getter and setter methods, so I am
// using do* for operation.
public String doConfig();
}
> A class to implement the JMX MBean interface
SystemConfig.java
package jmx.learning;
public class SystemConfig implements SystemConfigMBean {
private int threadCount;
private String schemaName;
public SystemConfig(int numThreads, String schema){
this.threadCount=numThreads;
this.schemaName=schema;
}
@Override
public void setThreadCount(int noOfThreads) {
this.threadCount=noOfThreads;
}
@Override
public int getThreadCount() {
return this.threadCount;
}
@Override
public void setSchemaName(String schemaName) {
this.schemaName=schemaName;
}
@Override
public String getSchemaName() {
return this.schemaName;
}
@Override
public String doConfig(){
return "No of Threads="+this.threadCount+" and DB Schema Name="+this.schemaName;
}
}
> Creating and Registering the MBean in the MBean Server using JMXMP
> connector
SystemConfigManagement.java
package jmx.learning;
import java.io.IOException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
public class SystemConfigManagement {
private static final int DEFAULT_NO_THREADS = 10;
private static final String DEFAULT_SCHEMA = "default";
public static void main(String[] args) throws MalformedObjectNameException,
InterruptedException, InstanceAlreadyExistsException,
MBeanRegistrationException, NotCompliantMBeanException, IOException {
// Instantiate the MBean server
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
// Create a JMXMP connector server
JMXServiceURL url = new JMXServiceURL("jmxmp", null, 5555);
JMXConnectorServer cs = JMXConnectorServerFactory
.newJMXConnectorServer(url, null, mbs);
cs.start();
// register the MBean
SystemConfig mBean = new SystemConfig(DEFAULT_NO_THREADS,
DEFAULT_SCHEMA);
ObjectName name = new ObjectName("jmx.learning:type=SystemConfig");
mbs.registerMBean(mBean, name);
do {
Thread.sleep(3000);
System.out.println("Thread Count=" + mBean.getThreadCount()
+ " Schema Name=" + mBean.getSchemaName());
} while (mBean.getThreadCount() != 0);
}
}
> JMXMP Connector Client
SystemConfigManagementClient.java
package jmx.learning;
import java.io.IOException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class SystemConfigManagementClient {
public static void main(String[] args) {
JMXConnector jmxc = null;
try {
// Create a JMXMP connector client
System.out.println("\nCreate a JMXMP connector client");
JMXServiceURL url = new JMXServiceURL(
"service:jmx:jmxmp://localhost:5555");
jmxc = JMXConnectorFactory.connect(url, null);
// get MBeanServerConnection
MBeanServerConnection serverConn = jmxc.getMBeanServerConnection();
ObjectName objectName = new ObjectName(
"jmx.learning:type=SystemConfig");
// Executing doConfig() method
String value = (String) serverConn.invoke(objectName, "doConfig",
new Object[] {}, new String[] {});
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jmxc != null) {
try {
jmxc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
NOTE: I have downloaded jmxremote_optional.jar
file and kept in project classpath.
Execution:
Server Output:
d:\Java\jdk1.8.0_261\bin\java.exe -cp .;d:\External_Library\jmxremote_optional.jar jmx.learning.SystemConfigManagement
Thread Count=10 Schema Name=default
Thread Count=10 Schema Name=default
Client Output:
d:\Java\jdk1.8.0_261\bin\java.exe -cp .;d:\External_Library\jmxremote_optional.jar jmx.learning.SystemConfigManagementClient
Create a JMXMP connector client
No of Threads=10 and DB Schema Name=default
I am not sure about the Server code you have written, looks like that code is expecting RMIConnector. Thus from Client the Connection attempt using RMI connector Java Remote Method Protocol (JRMP) is working.
Even you have passed property -Dcom.sun.management.jmxremote.port=portNum
This property indicate, portNum is the port number through which you want to enable JMX RMI connections.
NOTE: For demo purpose I didn't show the secure handling stuff, in real code those need to be in place.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论