如何取得jvm实例的cpu占用(转)

本文会贴很多代码,代码遵循Google的java代码格式。

获取数据篇

1、jmx连接的创建是一个比较重的操作,我们使用apache的common pool2创建连接工厂。

public class JmxConnectionFactory implements KeyedPooledObjectFactory<JmxServer, JMXConnector> {

  @Override
  public PooledObject<JMXConnector> makeObject(JmxServer server) throws Exception {
    JMXServiceURL
        serviceURL =
        new JMXServiceURL(String.format(
            "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", server.getHost(), server.getPort()));
    Map<String, Object> environment = Maps.newHashMap();
    String username = server.getUsername();
    String password = server.getPassword();
    if ((username != null) && (password != null)) {
      String[] credentials = new String[2];
      credentials[0] = username;
      credentials[1] = password;
      environment.put(JMXConnector.CREDENTIALS, credentials);
    }
    environment.put("sun.rmi.transport.proxy.connectTimeout", 1000);
    environment.put("sun.rmi.transport.tcp.responseTimeout", 3000);
    JMXConnector connect = JMXConnectorFactory.connect(serviceURL, environment);
    return new DefaultPooledObject<JMXConnector>(connect);


  }

  @Override
  public void destroyObject(JmxServer key, PooledObject<JMXConnector> object) throws Exception {
    object.getObject().close();
  }

  @Override
  public boolean validateObject(JmxServer key, PooledObject<JMXConnector> object) {
    JMXConnector connector = object.getObject();
    try {
      connector.getConnectionId();
      return true;
    } catch (IOException exception) {
      // ignore
    }
    return false;
  }

  @Override
  public void activateObject(JmxServer key, PooledObject<JMXConnector> p) throws Exception {
  }

  @Override
  public void passivateObject(JmxServer key, PooledObject<JMXConnector> p) throws Exception {
  }
}
 

2、从连接池中获取JMX连接

private static GenericKeyedObjectPool<JmxServer, JMXConnector> POOL;
  private static AtomicInteger actives = new AtomicInteger(0);
  //....
try {
      JMXConnector connector = POOL.borrowObject(server);
      try {
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();
        // 在这个地方使用连接获取JVM的监控数据
        // ......
      } finally {
        POOL.returnObject(server, connector);
      }
 

3、计算cpu占用的逻辑是: 获取:ProcessCpuTime,Uptime,AvailableProcessors,然后结合上一次获取到的数据得出,算式为:

Math.min(99F, (ProcessCpuTime-PreProcessCpuTime) / ((Uptime-PreUptime) * 10000F * AvailableProcessors));

方式一:通过获取相应的Bean,然后通过Bean去获取数据

private long prevUpTime, prevProcessCpuTime;
// ......
      RuntimeMXBean runtimeMBean =
          newPlatformMXBeanProxy(mbsc, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
      OperatingSystemMXBean
          operatingSystemMBean =
          newPlatformMXBeanProxy(mbsc, OPERATING_SYSTEM_MXBEAN_NAME,
                                 com.sun.management.OperatingSystemMXBean.class);
      int nCPUs = operatingSystemMBean.getAvailableProcessors();
      if (runtimeMBean != null && operatingSystemMBean != null) {
        long uptime = runtimeMBean.getUptime();
        long processCpuTime = operatingSystemMBean.getProcessCpuTime();
        if (prevUpTime != 0 && prevProcessCpuTime != 0) {
          long elapsedCpu = processCpuTime - prevProcessCpuTime;
          long elaspedTime = uptime - prevUpTime;
          float cpuUsage = Math.min(99F, elapsedCpu / (elaspedTime * 10000F * nCPUs));
          prevUpTime = uptime;
          prevProcessCpuTime = processCpuTime;
          //
          JsonObject value = new JsonObject();
          String key = "CpuUsage";
          LOGGER.debug("received value '{}%' for item '{}'", cpuUsage, key);
          value.addProperty(MonitorConst.JSON_TAG_VALUE, cpuUsage);
          value.addProperty(MonitorConst.JSON_TAG_NAME, key);
          return value;
        } else {
          prevUpTime = uptime;
          prevProcessCpuTime = processCpuTime;
        }
      }
// ......

方式二、通过key来直接获取,代码通用些,比较长,代码参考zabbix gateway实现

// 通用获取方法
protected String getStringValue(MBeanServerConnection mbsc, String key) throws Exception {
    MonitorItem item = new MonitorItem(key);

    if (item.getKeyId().equals("jmx")) {
  if (2 != item.getArgumentCount()) {
    throw new MonitorException(
    "required key format: jmx[<object name>,<attribute name>]");
  }

  ObjectName objectName = new ObjectName(item.getArgument(1));
  String attributeName = item.getArgument(2);
  String realAttributeName;
  String fieldNames = "";
  int sep;

  //
  // Attribute name and composite data field names are separated by dots. On the other hand the
  // name may contain a dot too. In this case user needs to escape it with a backslash. Also the
  // backslash symbols in the name must be escaped. So a real separator is unescaped dot and
  // separatorIndex() is used to locate it.
  //

  sep = HelperFunctionChest.separatorIndex(attributeName);

  if (-1 != sep) {
    LOGGER.trace("'{}' contains composite data", attributeName);

    realAttributeName = attributeName.substring(0, sep);
    fieldNames = attributeName.substring(sep + 1);
  } else {
    realAttributeName = attributeName;
  }

  // unescape possible dots or backslashes that were escaped by user
  realAttributeName = HelperFunctionChest.unescapeUserInput(realAttributeName);

  LOGGER.trace("attributeName:'{}'", realAttributeName);
  LOGGER.trace("fieldNames:'{}'", fieldNames);

  return getPrimitiveAttributeValue(mbsc.getAttribute(objectName, realAttributeName),
                fieldNames);
    } else if (item.getKeyId().equals("jmx.discovery")) {
  if (0 != item.getArgumentCount()) {
    throw new MonitorException("required key format: jmx.discovery");
  }

  JsonArray counters = new JsonArray();

  for (ObjectName name : mbsc.queryNames(null, null)) {
    LOGGER.trace("discovered object '{}'", name);

    for (MBeanAttributeInfo attrInfo : mbsc.getMBeanInfo(name).getAttributes()) {
      LOGGER.trace("discovered attribute '{}'", attrInfo.getName());

      if (!attrInfo.isReadable()) {
    LOGGER.trace("attribute not readable, skipping");
    continue;
      }

      try {
    LOGGER.trace("looking for attributes of primitive types");
    String
        descr =
        (attrInfo.getName().equals(attrInfo.getDescription()) ? null
                          : attrInfo
         .getDescription());
    findPrimitiveAttributes(counters, name, descr, attrInfo.getName(),
            mbsc.getAttribute(name, attrInfo.getName()));
      } catch (Exception e) {
    Object[] logInfo = {name, attrInfo.getName(), e};
    LOGGER.trace("processing '{},{}' failed", logInfo);
      }
    }
  }

  JsonObject mapping = new JsonObject();
  mapping.add(MonitorConst.JSON_TAG_DATA, counters);
  return mapping.toString();
    } else {
  throw new MonitorException("key ID '%s' is not supported", item.getKeyId());
    }
  }

  private String getPrimitiveAttributeValue(Object dataObject, String fieldNames) throws
                              MonitorException {
    LOGGER
    .trace("drilling down with data object '{}' and field names '{}'", dataObject,
       fieldNames);

    if (null == dataObject) {
  throw new MonitorException("data object is null");
    }

    if (fieldNames.equals("")) {
  if (isPrimitiveAttributeType(dataObject.getClass())) {
    return dataObject.toString();
  } else {
    throw new MonitorException(
    "data object type is not primitive: %s" + dataObject.getClass());
  }
    }

    if (dataObject instanceof CompositeData) {
  LOGGER.trace("'{}' contains composite data", dataObject);

  CompositeData comp = (CompositeData) dataObject;

  String dataObjectName;
  String newFieldNames = "";

  int sep = HelperFunctionChest.separatorIndex(fieldNames);

  if (-1 != sep) {
    dataObjectName = fieldNames.substring(0, sep);
    newFieldNames = fieldNames.substring(sep + 1);
  } else {
    dataObjectName = fieldNames;
  }

  // unescape possible dots or backslashes that were escaped by user
  dataObjectName = HelperFunctionChest.unescapeUserInput(dataObjectName);

  return getPrimitiveAttributeValue(comp.get(dataObjectName), newFieldNames);
    } else {
  throw new MonitorException("unsupported data object type along the path: %s",
             dataObject.getClass());
    }
  }

  private void findPrimitiveAttributes(JsonArray counters, ObjectName name, String descr,
               String attrPath, Object attribute) {
    LOGGER.trace("drilling down with attribute path '{}'", attrPath);

    if (isPrimitiveAttributeType(attribute.getClass())) {
  LOGGER.trace("found attribute of a primitive type: {}", attribute.getClass());

  JsonObject counter = new JsonObject();

  counter.addProperty("{#JMXDESC}", null == descr ? name + "," + attrPath : descr);
  counter.addProperty("{#JMXOBJ}", name.toString());
  counter.addProperty("{#JMXATTR}", attrPath);
  counter.addProperty("{#JMXTYPE}", attribute.getClass().getName());
  counter.addProperty("{#JMXVALUE}", attribute.toString());

  counters.add(counter);
    } else if (attribute instanceof CompositeData) {
  LOGGER.trace("found attribute of a composite type: {}", attribute.getClass());

  CompositeData comp = (CompositeData) attribute;

  for (String key : comp.getCompositeType().keySet()) {
    findPrimitiveAttributes(counters, name, descr, attrPath + "." + key, comp.get(key));
  }
    } else if (attribute instanceof TabularDataSupport || attribute.getClass().isArray()) {
  LOGGER.trace("found attribute of a known, unsupported type: {}", attribute.getClass());
    } else {
  LOGGER
      .trace("found attribute of an unknown, unsupported type: {}", attribute.getClass());
    }
  }

  private boolean isPrimitiveAttributeType(Class<?> clazz) {
    Class<?>[]
    clazzez =
    {Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class,
     Float.class, Double.class, String.class, java.math.BigDecimal.class,
     java.math.BigInteger.class,
     java.util.Date.class, ObjectName.class};

    return HelperFunctionChest.arrayContains(clazzez, clazz);
  }

// 使用示例
获取:ProcessCpuTime,Uptime,AvailableProcessors,然后结合上一次获取到的数据得出,算式为:
String processCpuTime=getStringValue(mbsc, "jmx["java.lang:type=OperatingSystem",ProcessCpuTime]")
String uptime=getStringValue(mbsc, "jmx["java.lang:type=Runtime",Uptime]", #1)-last("jmx["java.lang:type=Runtime",Uptime]")
String availableProcessors=getStringValue(mbsc, "jmx["java.lang:type=OperatingSystem",AvailableProcessors]")

方式三、zabbix 1、clone一个Template JMX Generic,修改添加相应的item的配置,添加的Template JMX Consumer

<template>
      <template>Template JMX Consumer</template>
      <name>Template JMX Consumer</name>
      <groups>
        <group>
          <name>Templates</name>
        </group>
      </groups>
      <applications/>
      <items>
        <item>
          <name>AvailableProcessors</name>
          <type>16</type>
          <snmp_community/>
          <multiplier>0</multiplier>
          <snmp_oid/>
          <key>jmx["java.lang:type=OperatingSystem",AvailableProcessors]</key>
          <delay>60</delay>
          <history>7</history>
          <trends>365</trends>
          <status>0</status>
          <value_type>3</value_type>
          <allowed_hosts/>
          <units/>
          <delta>0</delta>
          <snmpv3_contextname/>
          <snmpv3_securityname/>
          <snmpv3_securitylevel>0</snmpv3_securitylevel>
          <snmpv3_authprotocol>0</snmpv3_authprotocol>
          <snmpv3_authpassphrase/>
          <snmpv3_privprotocol>0</snmpv3_privprotocol>
          <snmpv3_privpassphrase/>
          <formula>1</formula>
          <delay_flex/>
          <params/>
          <ipmi_sensor/>
          <data_type>0</data_type>
          <authtype>0</authtype>
          <username/>
          <password/>
          <publickey/>
          <privatekey/>
          <port/>
          <description/>
          <inventory_link>0</inventory_link>
          <applications>
            <application>
              <name>Operating System</name>
            </application>
          </applications>
          <valuemap/>
        </item>
        <item>
          <name>Cpu Usage</name>
          <type>15</type>
          <snmp_community/>
          <multiplier>0</multiplier>
          <snmp_oid/>
          <key>CpuUsage</key>
          <delay>30</delay>
          <history>7</history>
          <trends>365</trends>
          <status>0</status>
          <value_type>0</value_type>
          <allowed_hosts/>
          <units>%</units>
          <delta>0</delta>
          <snmpv3_contextname/>
          <snmpv3_securityname/>
          <snmpv3_securitylevel>0</snmpv3_securitylevel>
          <snmpv3_authprotocol>0</snmpv3_authprotocol>
          <snmpv3_authpassphrase/>
          <snmpv3_privprotocol>0</snmpv3_privprotocol>
          <snmpv3_privpassphrase/>
          <formula>1</formula>
          <delay_flex/>
          <params>(last("jmx["java.lang:type=OperatingSystem",ProcessCpuTime]", #1)-last("jmx["java.lang:type=OperatingSystem",ProcessCpuTime]", #2))/((last("jmx["java.lang:type=Runtime",Uptime]", #1)-last("jmx["java.lang:type=Runtime",Uptime]", #2))*10000*last("jmx["java.lang:type=OperatingSystem",AvailableProcessors]", 0))</params>
          <ipmi_sensor/>
          <data_type>0</data_type>
          <authtype>0</authtype>
          <username/>
          <password/>
          <publickey/>
          <privatekey/>
          <port/>
          <description/>
          <inventory_link>0</inventory_link>
          <applications>
            <application>
              <name>Runtime</name>
            </application>
          </applications>
          <valuemap/>
        </item>
        <item>
          <name>ProcessCpuTime</name>
          <type>16</type>
          <snmp_community/>
          <multiplier>0</multiplier>
          <snmp_oid/>
          <key>jmx["java.lang:type=OperatingSystem",ProcessCpuTime]</key>
          <delay>60</delay>
          <history>7</history>
          <trends>365</trends>
          <status>0</status>
          <value_type>3</value_type>
          <allowed_hosts/>
          <units/>
          <delta>0</delta>
          <snmpv3_contextname/>
          <snmpv3_securityname/>
          <snmpv3_securitylevel>0</snmpv3_securitylevel>
          <snmpv3_authprotocol>0</snmpv3_authprotocol>
          <snmpv3_authpassphrase/>
          <snmpv3_privprotocol>0</snmpv3_privprotocol>
          <snmpv3_privpassphrase/>
          <formula>1</formula>
          <delay_flex/>
          <params/>
          <ipmi_sensor/>
          <data_type>0</data_type>
          <authtype>0</authtype>
          <username/>
          <password/>
          <publickey/>
          <privatekey/>
          <port/>
          <description/>
          <inventory_link>0</inventory_link>
          <applications>
            <application>
              <name>Operating System</name>
            </application>
          </applications>
          <valuemap/>
        </item>
      </items>
      <discovery_rules/>
      <macros/>
      <templates>
        <template>
          <name>Template JMX Generic</name>
        </template>
      </templates>
      <screens/>
    </template>
// 修改原来的模板
<item>
          <name>jvm Uptime</name>
          <type>15</type>
          <snmp_community/>
          <multiplier>1</multiplier>
          <snmp_oid/>
          <key>jmxUptime</key>
          <delay>60</delay>
          <history>7</history>
          <trends>365</trends>
          <status>0</status>
          <value_type>3</value_type>
          <allowed_hosts/>
          <units>uptime</units>
          <delta>0</delta>
          <snmpv3_contextname/>
          <snmpv3_securityname/>
          <snmpv3_securitylevel>0</snmpv3_securitylevel>
          <snmpv3_authprotocol>0</snmpv3_authprotocol>
          <snmpv3_authpassphrase/>
          <snmpv3_privprotocol>0</snmpv3_privprotocol>
          <snmpv3_privpassphrase/>
          <formula>0.001</formula>
          <delay_flex/>
          <params>jmx["java.lang:type=Runtime",Uptime]</params>
          <ipmi_sensor/>
          <data_type>0</data_type>
          <authtype>0</authtype>
          <username/>
          <password/>
          <publickey/>
          <privatekey/>
          <port/>
          <description/>
          <inventory_link>0</inventory_link>
          <applications>
            <application>
              <name>Runtime</name>
            </application>
          </applications>
          <valuemap/>
        </item>
        <item>
          <name>jvm Uptime Microsecond</name>
          <type>16</type>
          <snmp_community/>
          <multiplier>0</multiplier>
          <snmp_oid/>
          <key>jmx["java.lang:type=Runtime",Uptime]</key>
          <delay>60</delay>
          <history>7</history>
          <trends>365</trends>
          <status>0</status>
          <value_type>3</value_type>
          <allowed_hosts/>
          <units>uptime</units>
          <delta>0</delta>
          <snmpv3_contextname/>
          <snmpv3_securityname/>
          <snmpv3_securitylevel>0</snmpv3_securitylevel>
          <snmpv3_authprotocol>0</snmpv3_authprotocol>
          <snmpv3_authpassphrase/>
          <snmpv3_privprotocol>0</snmpv3_privprotocol>
          <snmpv3_privpassphrase/>
          <formula>1</formula>
          <delay_flex/>
          <params/>
          <ipmi_sensor/>
          <data_type>0</data_type>
          <authtype>0</authtype>
          <username/>
          <password/>
          <publickey/>
          <privatekey/>
          <port/>
          <description/>
          <inventory_link>0</inventory_link>
          <applications>
            <application>
              <name>Runtime</name>
            </application>
          </applications>
          <valuemap/>
        </item>
 
原文地址:https://www.cnblogs.com/zhengah/p/4941958.html