[英]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.