持有java JMX连接打开一个好主意

时间:2014-07-17 10:42:08

标签: java jmx

我有一个支持网站,我想通过JMX显示从另一个Java应用程序收集的一些统计数据。我们注意到,在重新启动其他应用后,支持应用有时无法获取统计信息。我想这是因为支持应用程序已打开与其他应用程序的JMX连接并保持它。然后,每次进入页面显示JMX统计信息时,它都会尝试使用连接收集它们,然后失败。

我的问题是,拥有一个JMX连接并尝试在重新连接时解决它是否更好?

或者每当我们加载带有JMX统计数据的页面时,我们是否应该创建一个新的JMX连接,然后在获得所需的值后关闭它?

2 个答案:

答案 0 :(得分:1)

据我所知,

JMX连接是RMI Connector对象,因此可以保存在客户端应用程序中。 +使用心跳方法重新连接。

这样我们就可以避免重新建立不轻量级的RMI连接的开销。

参考:javax.management.remote.rmi.RMIConnector

答案 1 :(得分:0)

我们最终没有使用心跳,但在阅读了Girish的回答之后提出了以下内容

public class JmxMetricsRetriever {

private final JMXServiceURL jmxUrl;
private final Map<String, Object> env;

private MBeanServerConnection connection;

private JmxMetricsRetriever(JMXServiceURL jmxUrl, Map<String, Object> env) {
    this.jmxUrl = jmxUrl;
    this.env = env;
    reconnect();
}

public synchronized Object getAttributeValue(String jmxObjectName, String attributeName) {
    try {
        if (connection == null) {
            reconnect();
        }
        try {
            return getAttributeValuePrivate(jmxObjectName, attributeName);
        } catch (ConnectException exc) {
            //This is to reconnect after the Server has been restarted.
            reconnect();
            return getAttributeValuePrivate(jmxObjectName, attributeName);
        }
    } catch (MalformedObjectNameException |
            AttributeNotFoundException |
            MBeanException |
            ReflectionException |
            InstanceNotFoundException |
            IOException ex) {
        throw new RuntimeException(ex);
    }
}

private synchronized Object getAttributeValuePrivate(String jmxObjectName, String attributeName) throws MalformedObjectNameException, MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException {
    ObjectName replication = new ObjectName(jmxObjectName);

    return connection.getAttribute(replication, attributeName);
}

private synchronized void reconnect() {
    logger.info(String.format("Reconnecting to [%s] via JMX", jmxUrl.toString()));
    try {
        JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxUrl, env);
        this.connection = jmxConnector.getMBeanServerConnection();
        jmxConnector.connect();
    } catch (IOException e) {
        //Log something but don't throw an exception otherwise our app will fail to start.
    }
}

public static JmxMetricsRetriever build(String url, String port, String user, String password) {
    try {
        JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + url + ":" + port + "/jmxrmi");
        Map<String, Object> env = new HashMap<>();
        env.put(JMXConnector.CREDENTIALS, new String[]{user, password});


        return new JmxMetricsRetriever(jmxUrl, env);
    } catch (MalformedURLException ex) {
        throw new RuntimeException(ex);
    }
}

}

当我们启动我们的应用程序时,我们尝试创建一个JMX连接并保持它。每次我们获得JMX属性时,我们都会检查连接是否已创建(如果我们连接的服务器在启动我们的服务时未启动,则可能没有)。然后尝试检索我们的属性。如果失败,请尝试重新连接并获取属性值。我们找不到更好的方法来测试JMX连接仍然可用,因此必须捕获异常。