Repository: incubator-unomi Updated Branches: refs/heads/master 73ddec1a4 -> 7b19dfa06
UNOMI-136 Replace JMX statistics collecting with Karaf Cellar events - Remove JMX system statistics collection - Replace with local collection and then sending events to the Karaf Cellar cluster 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/7b19dfa0 Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/7b19dfa0 Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/7b19dfa0 Branch: refs/heads/master Commit: 7b19dfa064b01cded88726bdc59d53b068a0b29a Parents: 73ddec1 Author: Serge Huber <[email protected]> Authored: Tue Nov 7 10:39:45 2017 +0100 Committer: Serge Huber <[email protected]> Committed: Tue Nov 7 10:39:45 2017 +0100 ---------------------------------------------------------------------- .../services/services/ClusterServiceImpl.java | 187 +++++++------------ .../services/ClusterSystemStatisticsEvent.java | 43 +++++ .../ClusterSystemStatisticsEventHandler.java | 138 ++++++++++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 23 ++- .../main/resources/org.apache.unomi.cluster.cfg | 9 +- 5 files changed, 276 insertions(+), 124 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/7b19dfa0/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 57d8d3e..6bc0cdc 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 @@ -17,6 +17,7 @@ package org.apache.unomi.services.services; +import org.apache.commons.lang3.ArrayUtils; import org.apache.karaf.cellar.config.ClusterConfigurationEvent; import org.apache.karaf.cellar.config.Constants; import org.apache.karaf.cellar.core.*; @@ -31,16 +32,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.*; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; -import java.io.IOException; +import java.io.Serializable; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; -import java.net.ConnectException; -import java.net.MalformedURLException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Implementation of the persistence service interface @@ -57,12 +54,13 @@ public class ClusterServiceImpl implements ClusterService { private GroupManager karafCellarGroupManager; private String karafCellarGroupName = Configurations.DEFAULT_GROUP_NAME; private ConfigurationAdmin osgiConfigurationAdmin; - private String karafJMXUsername = "karaf"; - private String karafJMXPassword = "karaf"; - private int karafJMXPort = 1099; private String publicAddress; private String internalAddress; - private Map<String, JMXConnector> jmxConnectors = new LinkedHashMap<>(); + private Map<String, Map<String,Serializable>> nodeSystemStatistics = new ConcurrentHashMap<>(); + private Group group = null; + + private Timer nodeStatisticsUpdateTimer; + private long nodeStatisticsUpdateFrequency = 10000; public void setPersistenceService(PersistenceService persistenceService) { this.persistenceService = persistenceService; @@ -88,18 +86,6 @@ public class ClusterServiceImpl implements ClusterService { this.osgiConfigurationAdmin = osgiConfigurationAdmin; } - public void setKarafJMXUsername(String karafJMXUsername) { - this.karafJMXUsername = karafJMXUsername; - } - - public void setKarafJMXPassword(String karafJMXPassword) { - this.karafJMXPassword = karafJMXPassword; - } - - public void setKarafJMXPort(int karafJMXPort) { - this.karafJMXPort = karafJMXPort; - } - public void setPublicAddress(String publicAddress) { this.publicAddress = publicAddress; } @@ -108,11 +94,19 @@ public class ClusterServiceImpl implements ClusterService { this.internalAddress = internalAddress; } + public void setNodeStatisticsUpdateFrequency(long nodeStatisticsUpdateFrequency) { + this.nodeStatisticsUpdateFrequency = nodeStatisticsUpdateFrequency; + } + + public Map<String, Map<String, Serializable>> getNodeSystemStatistics() { + return nodeSystemStatistics; + } + public void init() { if (karafCellarEventProducer != null && karafCellarClusterManager != null) { boolean setupConfigOk = true; - Group group = karafCellarGroupManager.findGroupByName(karafCellarGroupName); + group = karafCellarGroupManager.findGroupByName(karafCellarGroupName); if (setupConfigOk && group == null) { logger.error("Cluster group " + karafCellarGroupName + " doesn't exist, creating it..."); group = karafCellarGroupManager.createGroup(karafCellarGroupName); @@ -155,20 +149,21 @@ public class ClusterServiceImpl implements ClusterService { clusterConfigurationEvent.setSourceGroup(group); karafCellarEventProducer.produce(clusterConfigurationEvent); } + + nodeStatisticsUpdateTimer = new Timer(); + TimerTask statisticsTask = new TimerTask() { + @Override + public void run() { + updateSystemStats(); + } + }; + nodeStatisticsUpdateTimer.schedule(statisticsTask, 0, nodeStatisticsUpdateFrequency); + } logger.info("Cluster service initialized."); } 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); - } - } logger.info("Cluster service shutdown."); } @@ -196,43 +191,22 @@ public class ClusterServiceImpl implements ClusterService { if (internalEndpoint != null) { clusterNode.setInternalHostAddress(internalEndpoint); } - String serviceUrl = "service:jmx:rmi:///jndi/rmi://" + karafCellarNode.getHost() + ":" + karafJMXPort + "/karaf-root"; - try { - 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 systemCpuLoad = null; - try { - systemCpuLoad = (Double) mbsc.getAttribute(operatingSystemMXBeanName, "SystemCpuLoad"); - } catch (MBeanException e) { - logger.error("Error retrieving system CPU load", e); - } catch (AttributeNotFoundException e) { - logger.error("Error retrieving system CPU load", e); + Map<String,Serializable> nodeStatistics = nodeSystemStatistics.get(karafCellarNode.getId()); + if (nodeStatistics != null) { + Long uptime = (Long) nodeStatistics.get("uptime"); + if (uptime != null) { + clusterNode.setUptime(uptime); } - final OperatingSystemMXBean remoteOperatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); - clusterNode.setLoadAverage(new double[]{remoteOperatingSystemMXBean.getSystemLoadAverage()}); + Double systemCpuLoad = (Double) nodeStatistics.get("systemCpuLoad"); if (systemCpuLoad != null) { clusterNode.setCpuLoad(systemCpuLoad); } - - } catch (MalformedURLException e) { - logger.error("Error connecting to remote JMX server", e); - } catch (ConnectException ce) { - handleTimeouts(serviceUrl, ce); - } catch (java.rmi.ConnectException ce) { - handleTimeouts(serviceUrl, ce); - } catch (java.rmi.ConnectIOException cioe) { - handleTimeouts(serviceUrl, cioe); - } catch (IOException e) { - logger.error("Error retrieving remote JMX data", e); - } catch (MalformedObjectNameException e) { - logger.error("Error retrieving remote JMX data", e); - } catch (InstanceNotFoundException e) { - logger.error("Error retrieving remote JMX data", e); - } catch (ReflectionException e) { - logger.error("Error retrieving remote JMX data", e); + List<Double> loadAverage = (List<Double>) nodeStatistics.get("systemLoadAverage"); + if (loadAverage != null) { + Double[] loadAverageArray = loadAverage.toArray(new Double[loadAverage.size()]); + ArrayUtils.toPrimitive(loadAverageArray); + clusterNode.setLoadAverage(ArrayUtils.toPrimitive(loadAverageArray)); + } } clusterNodes.put(karafCellarNode.getId(), clusterNode); } @@ -240,23 +214,6 @@ public class ClusterServiceImpl implements ClusterService { return new ArrayList<ClusterNode>(clusterNodes.values()); } - private void handleTimeouts(String serviceUrl, Throwable throwable) { - Throwable rootCause = throwable; - while (rootCause.getCause() != null) { - rootCause = rootCause.getCause(); - } - logger.warn("JMX RMI Connection error, will reconnect on next request. Active debug logging for access to detailed stack trace. Root cause=" + rootCause.getMessage()); - logger.debug("Detailed stacktrace", throwable); - JMXConnector jmxConnector = jmxConnectors.remove(serviceUrl); - try { - if (jmxConnector != null) { - jmxConnector.close(); - } - } catch (Throwable t) { - // ignore any exception when closing a timed out connection. - } - } - @Override public void purge(Date date) { persistenceService.purge(date); @@ -284,39 +241,6 @@ 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.warn("Closing invalid JMX connection resulted in :" + e1.getMessage() + ", this is probably ok."); - logger.debug("Error closing invalid JMX connection", e1); - } - if (e.getMessage() != null && e.getMessage().contains("Connection closed")) { - logger.warn("JMX connection to url {} was closed (Cause:{}). Reconnecting...", url, e.getMessage()); - } else { - 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; - } - private Map<String, String> getMapProperty(Properties properties, String propertyName, String defaultValue) { String propertyValue = properties.getProperty(propertyName, defaultValue); return getMapProperty(propertyValue); @@ -350,4 +274,37 @@ public class ClusterServiceImpl implements ClusterService { return getMapProperty(oldPropertyValue); } + private void updateSystemStats() { + final RuntimeMXBean remoteRuntime = ManagementFactory.getRuntimeMXBean(); + long uptime = remoteRuntime.getUptime(); + ObjectName operatingSystemMXBeanName = ManagementFactory.getOperatingSystemMXBean().getObjectName(); + Double systemCpuLoad = null; + try { + systemCpuLoad = (Double) ManagementFactory.getPlatformMBeanServer().getAttribute(operatingSystemMXBeanName, "SystemCpuLoad"); + } catch (MBeanException e) { + logger.error("Error retrieving system CPU load", e); + } catch (AttributeNotFoundException e) { + logger.error("Error retrieving system CPU load", e); + } catch (InstanceNotFoundException e) { + logger.error("Error retrieving system CPU load", e); + } catch (ReflectionException e) { + logger.error("Error retrieving system CPU load", e); + } + final OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + double systemLoadAverage = operatingSystemMXBean.getSystemLoadAverage(); + + ClusterSystemStatisticsEvent clusterSystemStatisticsEvent = new ClusterSystemStatisticsEvent("org.apache.unomi.cluster.system.statistics"); + clusterSystemStatisticsEvent.setSourceGroup(group); + clusterSystemStatisticsEvent.setSourceNode(karafCellarClusterManager.getNode()); + Map<String,Serializable> systemStatistics = new TreeMap<>(); + ArrayList<Double> systemLoadAverageArray = new ArrayList<>(); + systemLoadAverageArray.add(systemLoadAverage); + systemStatistics.put("systemLoadAverage", systemLoadAverageArray); + systemStatistics.put("systemCpuLoad", systemCpuLoad); + systemStatistics.put("uptime", uptime); + clusterSystemStatisticsEvent.setStatistics(systemStatistics); + nodeSystemStatistics.put(karafCellarClusterManager.getNode().getId(), systemStatistics); + karafCellarEventProducer.produce(clusterSystemStatisticsEvent); + } + } http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/7b19dfa0/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEvent.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEvent.java b/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEvent.java new file mode 100644 index 0000000..cbe162d --- /dev/null +++ b/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEvent.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.services.services; + +import org.apache.karaf.cellar.core.event.Event; + +import java.io.Serializable; +import java.util.Map; +import java.util.TreeMap; + +/** + * The cluster event used to transmit update to node system statistics. + */ +public class ClusterSystemStatisticsEvent extends Event { + + Map<String,Serializable> statistics = new TreeMap<>(); + + public ClusterSystemStatisticsEvent(String id) { + super(id); + } + + public Map<String, Serializable> getStatistics() { + return statistics; + } + + public void setStatistics(Map<String, Serializable> statistics) { + this.statistics = statistics; + } +} http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/7b19dfa0/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEventHandler.java ---------------------------------------------------------------------- diff --git a/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEventHandler.java b/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEventHandler.java new file mode 100644 index 0000000..2fef85c --- /dev/null +++ b/services/src/main/java/org/apache/unomi/services/services/ClusterSystemStatisticsEventHandler.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.services.services; + +import org.apache.karaf.cellar.config.Constants; +import org.apache.karaf.cellar.core.CellarSupport; +import org.apache.karaf.cellar.core.Configurations; +import org.apache.karaf.cellar.core.Group; +import org.apache.karaf.cellar.core.control.BasicSwitch; +import org.apache.karaf.cellar.core.control.Switch; +import org.apache.karaf.cellar.core.control.SwitchStatus; +import org.apache.karaf.cellar.core.event.EventHandler; +import org.apache.karaf.cellar.core.event.EventType; +import org.osgi.service.cm.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A Karaf Cellar event handler to process incoming events that contain system statistics updates from nodes. + */ +public class ClusterSystemStatisticsEventHandler extends CellarSupport implements EventHandler<ClusterSystemStatisticsEvent> { + + public static final String SWITCH_ID = "org.apache.unomi.cluster.system.statistics.handler"; + private static final Logger logger = LoggerFactory.getLogger(ClusterSystemStatisticsEventHandler.class.getName()); + private final Switch eventSwitch = new BasicSwitch(SWITCH_ID); + private ClusterServiceImpl clusterServiceImpl; + + public void setClusterServiceImpl(ClusterServiceImpl clusterServiceImpl) { + this.clusterServiceImpl = clusterServiceImpl; + } + + public void init() { + // nothing to do + } + + public void destroy() { + // nothing to do + } + + @Override + public void handle(ClusterSystemStatisticsEvent event) { + // check if the handler is ON + if (this.getSwitch().getStatus().equals(SwitchStatus.OFF)) { + logger.debug("CELLAR SYSTEM STATS: {} switch is OFF, cluster event not handled", SWITCH_ID); + return; + } + + if (groupManager == null) { + //in rare cases for example right after installation this happens! + logger.error("CELLAR SYSTEM STATS: retrieved event {} while groupManager is not available yet!", event); + return; + } + + // check if the group is local + if (!groupManager.isLocalGroup(event.getSourceGroup().getName())) { + logger.debug("CELLAR SYSTEM STATS: node is not part of the event cluster group {}",event.getSourceGroup().getName()); + return; + } + + Group group = event.getSourceGroup(); + String groupName = group.getName(); + + String pid = event.getId(); + + if (isAllowed(event.getSourceGroup(), Constants.CATEGORY, pid, EventType.INBOUND)) { + + // check if it's not a "local" event + if (event.getSourceNode() != null && event.getSourceNode().getId().equalsIgnoreCase(clusterManager.getNode().getId())) { + logger.trace("CELLAR SYSTEM STATS: cluster event is local (coming from local synchronizer or listener)"); + return; + } + + + Map<String, Serializable> nodeSystemStatistics = clusterServiceImpl.getNodeSystemStatistics().get(event.getSourceNode().getId()); + if (nodeSystemStatistics == null) { + nodeSystemStatistics = new ConcurrentHashMap<>(); + } + nodeSystemStatistics.putAll(event.getStatistics()); + clusterServiceImpl.getNodeSystemStatistics().put(event.getSourceNode().getId(), nodeSystemStatistics); + } + + } + + @Override + public Class<ClusterSystemStatisticsEvent> getType() { + return ClusterSystemStatisticsEvent.class; + } + + /** + * Get the cluster configuration event handler switch. + * + * @return the cluster configuration event handler switch. + */ + @Override + public Switch getSwitch() { + // load the switch status from the config + try { + Configuration configuration = configurationAdmin.getConfiguration(Configurations.NODE, null); + if (configuration != null) { + String handlerStatus = (String) configuration.getProperties().get(Configurations.HANDLER + "." + this.getClass().getName()); + if (handlerStatus == null) { + // default value is on. + eventSwitch.turnOn(); + } else { + Boolean status = new Boolean(handlerStatus); + if (status) { + eventSwitch.turnOn(); + } else { + eventSwitch.turnOff(); + } + } + } + } catch (Exception e) { + // nothing to do + } + return eventSwitch; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/7b19dfa0/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml ---------------------------------------------------------------------- diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml index c18bedd..3d9b181 100644 --- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -37,11 +37,9 @@ update-strategy="reload" placeholder-prefix="${cluster."> <cm:default-properties> <cm:property name="group" value="default" /> - <cm:property name="jmxUsername" value="karaf" /> - <cm:property name="jmxPassword" value="karaf" /> - <cm:property name="jmxPort" value="1099" /> <cm:property name="contextserver.publicAddress" value="https://localhost:9443"/> <cm:property name="contextserver.internalAddress" value="http://127.0.0.1:8181"/> + <cm:property name="nodeStatisticsUpdateFrequency" value="10000"/> </cm:default-properties> </cm:property-placeholder> @@ -165,9 +163,7 @@ <property name="karafCellarGroupManager" ref="karafCellarGroupManager" /> <property name="karafCellarGroupName" value="${cluster.group}" /> <property name="osgiConfigurationAdmin" ref="osgiConfigurationAdmin" /> - <property name="karafJMXUsername" value="${cluster.jmxUsername}" /> - <property name="karafJMXPassword" value="${cluster.jmxPassword}" /> - <property name="karafJMXPort" value="${cluster.jmxPort}" /> + <property name="nodeStatisticsUpdateFrequency" value="${cluster.nodeStatisticsUpdateFrequency}" /> </bean> <service id="clusterService" ref="clusterServiceImpl" auto-export="interfaces"/> @@ -282,4 +278,19 @@ <service id="configSharingService" ref="configSharingServiceImpl" auto-export="interfaces"> </service> + <!-- Cluster System Statistics Event Handler --> + <bean id="clusterSystemStatisticsEventHandler" class="org.apache.unomi.services.services.ClusterSystemStatisticsEventHandler" + init-method="init" destroy-method="destroy"> + <property name="configurationAdmin" ref="osgiConfigurationAdmin"/> + <property name="clusterManager" ref="karafCellarClusterManager"/> + <property name="groupManager" ref="karafCellarGroupManager"/> + <property name="clusterServiceImpl" ref="clusterServiceImpl" /> + </bean> + <service ref="clusterSystemStatisticsEventHandler" interface="org.apache.karaf.cellar.core.event.EventHandler"> + <service-properties> + <entry key="managed" value="true"/> + </service-properties> + </service> + + </blueprint> http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/7b19dfa0/services/src/main/resources/org.apache.unomi.cluster.cfg ---------------------------------------------------------------------- diff --git a/services/src/main/resources/org.apache.unomi.cluster.cfg b/services/src/main/resources/org.apache.unomi.cluster.cfg index 9bdc7af..b6498e7 100644 --- a/services/src/main/resources/org.apache.unomi.cluster.cfg +++ b/services/src/main/resources/org.apache.unomi.cluster.cfg @@ -15,8 +15,11 @@ # limitations under the License. # group=default -jmxUsername=karaf -jmxPassword=karaf -jmxPort=1099 contextserver.publicAddress=https://localhost:9443 contextserver.internalAddress=http://127.0.0.1:8181 +# +# The nodeStatisticsUpdateFrequency controls the frequency of the update of system statistics such as CPU load, +# system load average and uptime. This value is set in milliseconds and is set to 10 seconds by default. Each node +# will retrieve the local values and broadcast them through a cluster event to all the other nodes to update +# the global cluster statistics. +nodeStatisticsUpdateFrequency=10000 \ No newline at end of file
