Repository: incubator-unomi Updated Branches: refs/heads/master ddbebd25f -> e61412fc9
As Apache JIRA is down, this is a fix for on OutOfMemory : native thread limit reached problem because we were not properly closing or re-using the JMX connectors. This modification should fix the problem by re-using JMX connectors and storing them in a map where they are stored by URL. Upon the service shutdown all the connectors are closed. When a connector is used, it is first tested and if it fails it is removed from the map and a new one is created. Signed-off-by: Serge Huber <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/e61412fc Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/e61412fc Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/e61412fc Branch: refs/heads/master Commit: e61412fc90abc210d638c8b8cb848efd4be057a4 Parents: ddbebd2 Author: Serge Huber <[email protected]> Authored: Thu Jan 12 17:47:17 2017 +0100 Committer: Serge Huber <[email protected]> Committed: Thu Jan 12 17:47:17 2017 +0100 ---------------------------------------------------------------------- .../services/services/ClusterServiceImpl.java | 62 ++++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/e61412fc/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java index 8fb67d3..a002b55 100644 --- a/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java @@ -70,6 +70,8 @@ public class ClusterServiceImpl implements ClusterService { private String secureAddress; private String securePort; + private Map<String,JMXConnector> jmxConnectors = new LinkedHashMap<>(); + PersistenceService persistenceService; public void setPersistenceService(PersistenceService persistenceService) { @@ -178,6 +180,15 @@ public class ClusterServiceImpl implements ClusterService { } public void destroy() { + for (Map.Entry<String,JMXConnector> jmxConnectorEntry : jmxConnectors.entrySet()) { + String url = jmxConnectorEntry.getKey(); + JMXConnector jmxConnector = jmxConnectorEntry.getValue(); + try { + jmxConnector.close(); + } catch (IOException e) { + logger.error("Error closing JMX connector for url {}", url, e); + } + } } @Override @@ -224,32 +235,19 @@ public class ClusterServiceImpl implements ClusterService { clusterNode.setData(false); } try { - // now let's connect to remote JMX service to retrieve information from the runtime and operating system MX beans - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+karafCellarNode.getHost() + ":"+karafJMXPort+"/karaf-root"); - Map<String,Object> environment=new HashMap<String,Object>(); - if (karafJMXUsername != null && karafJMXPassword != null) { - environment.put(JMXConnector.CREDENTIALS,new String[]{karafJMXUsername,karafJMXPassword}); - } - JMXConnector jmxc = JMXConnectorFactory.connect(url, environment); - MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); + String serviceUrl = "service:jmx:rmi:///jndi/rmi://"+karafCellarNode.getHost() + ":"+karafJMXPort+"/karaf-root"; + JMXConnector jmxConnector = getJMXConnector(serviceUrl); + MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); final RuntimeMXBean remoteRuntime = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); clusterNode.setUptime(remoteRuntime.getUptime()); ObjectName operatingSystemMXBeanName = new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME); - Double processCpuLoad = null; Double systemCpuLoad = null; try { - processCpuLoad = (Double) mbsc.getAttribute(operatingSystemMXBeanName, "ProcessCpuLoad"); - } catch (MBeanException e) { - e.printStackTrace(); - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } - try { systemCpuLoad = (Double) mbsc.getAttribute(operatingSystemMXBeanName, "SystemCpuLoad"); } catch (MBeanException e) { - e.printStackTrace(); + logger.error("Error retrieving system CPU load", e); } catch (AttributeNotFoundException e) { - e.printStackTrace(); + logger.error("Error retrieving system CPU load", e); } final OperatingSystemMXBean remoteOperatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); clusterNode.setLoadAverage(new double[] { remoteOperatingSystemMXBean.getSystemLoadAverage()}); @@ -301,4 +299,32 @@ public class ClusterServiceImpl implements ClusterService { return support.isAllowed(group, category, pid, type); } + private JMXConnector getJMXConnector(String url) throws IOException { + if (jmxConnectors.containsKey(url)) { + JMXConnector jmxConnector = jmxConnectors.get(url); + try { + jmxConnector.getMBeanServerConnection(); + return jmxConnector; + } catch (IOException e) { + jmxConnectors.remove(url); + try { + jmxConnector.close(); + } catch (IOException e1) { + logger.error("Error closing invalid JMX connection", e1); + } + logger.error("Error using the JMX connection to url {}, closed and will reconnect", url, e); + } + } + // if we reach this point either we didn't have a connector or it didn't validate + // now let's connect to remote JMX service to retrieve information from the runtime and operating system MX beans + JMXServiceURL jmxServiceURL = new JMXServiceURL(url); + Map<String,Object> environment=new HashMap<String,Object>(); + if (karafJMXUsername != null && karafJMXPassword != null) { + environment.put(JMXConnector.CREDENTIALS,new String[]{karafJMXUsername,karafJMXPassword}); + } + JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, environment); + jmxConnectors.put(url, jmxConnector); + return jmxConnector; + } + }
