簡體   English   中英

持有Java JMX連接是個好主意

[英]Is holding a java JMX connection open a good idea

我有一個支持網站,我想顯示一些通過JMX從另一個Java應用程序收集的統計信息。 我們注意到,在另一個應用程序重新啟動后,支持應用程序有時無法獲取統計信息。 我猜這是因為支持應用程序已打開與另一個應用程序的JMX連接並保持連接。 然后,每次您轉到該頁面以顯示JMX統計信息時,它都會嘗試使用連接來收集它們,但它會失敗。

我的問題是,擁有一個JMX連接並嘗試重新連接時更好嗎?

還是每次在頁面上加載JMX統計信息時,都應該創建一個新的JMX連接,然后在獲得所需值后將其關閉?

據我所知,

JMX連接是RMI連接器對象,因此可以保存在客戶端應用程序中。 +使用心跳線方法重新連接。

這樣,我們可以避免重新建立不輕量的RMI連接的開銷。

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

我們最終並沒有使用心跳,但是在閱讀了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連接仍然可用,因此必須捕獲異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM