avoid json object creation and live beans model parsing if raw data is unchanged

This commit is contained in:
Martin Lippert
2018-08-14 10:41:23 +02:00
parent d88f8fddfa
commit 34a1168b75

View File

@@ -14,6 +14,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.PlatformManagedObject;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -59,6 +60,9 @@ public abstract class AbstractSpringBootApp implements SpringBootApp {
private String jmxMbeanActuatorDomain;
private LiveBeansModel cachedBeansModel;
private String cachedBeansModelMD5;
// NOTE: Gson-based serialisation replaces the old Jackson ObjectMapper. Not sure if this makes a difference in the long run, but to retain the same output that Jackson Object Mapper
// was generating during serialisation, some configuration in Gson is required, as the default behaviour of Gson is different than Object Mapper.
// Namely: Object Mapper does not escape Html, whereas Gson does by default (for example
@@ -74,11 +78,14 @@ public abstract class AbstractSpringBootApp implements SpringBootApp {
@Override
public abstract String getProcessID();
@Override
public abstract String getProcessName() throws Exception;
@Override
public abstract boolean isSpringBootApp();
private final MemoizingDisposableSupplier<JMXConnector> jmxConnector = new MemoizingDisposableSupplier<JMXConnector>(
//creating jmx connector:
() -> {
@@ -198,30 +205,37 @@ public abstract class AbstractSpringBootApp implements SpringBootApp {
public LiveBeansModel getBeans() {
try {
String domain = getDomainForActuator();
String json = getBeansFromActuator(domain);
LiveBeansModel beans = LiveBeansModel.parse(json);
logger.debug("Got {} beans for {}", beans.getBeanNames().size(), this);
return beans;
Object json = getBeansFromActuator(domain);
MessageDigest md = MessageDigest.getInstance("MD5");
String md5 = new String(md.digest(json.toString().getBytes("UTF-8")));
synchronized(this) {
if (cachedBeansModel == null || !md5.equals(cachedBeansModelMD5)) {
cachedBeansModel = LiveBeansModel.parse(gson.toJson(json));
cachedBeansModelMD5 = md5;
logger.debug("Got {} beans for {}", cachedBeansModel.getBeanNames().size(), this);
}
else {
logger.debug("Got {} beans for {} - from cache", cachedBeansModel.getBeanNames().size(), this);
}
}
return cachedBeansModel;
} catch (Exception e) {
logger.error("Error parsing beans", e);
return LiveBeansModel.builder().build();
}
}
private String getBeansFromActuator(String domain) throws Exception {
Object result = getActuatorDataFromAttribute(getObjectName(domain, "type=Endpoint,name=beansEndpoint"), "Data");
if (result != null) {
String beans = gson.toJson(result);
return beans;
}
private Object getBeansFromActuator(String domain) throws Exception {
Object result = getActuatorDataFromOperation(getObjectName(domain, "type=Endpoint,name=Beans"), "beans");
if (result != null) return result;
result = getActuatorDataFromOperation(getObjectName(domain, "type=Endpoint,name=Beans"), "beans");
if (result != null) {
String beans = gson.toJson(result);
return beans;
}
return null;
return getActuatorDataFromAttribute(getObjectName(domain, "type=Endpoint,name=beansEndpoint"), "Data");
}
/**
@@ -242,8 +256,8 @@ public abstract class AbstractSpringBootApp implements SpringBootApp {
// To be more efficient in finding the domain containing actuator information,
// and avoid many JMX connections
// first check the default springframework boot domain:
String beansJson = getBeansFromActuator(SPRINGFRAMEWORK_BOOT_DOMAIN);
if (StringUtil.hasText(beansJson)) {
Object beansJson = getBeansFromActuator(SPRINGFRAMEWORK_BOOT_DOMAIN);
if (beansJson != null) {
jmxMbeanActuatorDomain = SPRINGFRAMEWORK_BOOT_DOMAIN;
}
@@ -256,7 +270,7 @@ public abstract class AbstractSpringBootApp implements SpringBootApp {
// domain contains actuator Beans (for example, "Admin" will be under default spring framework domain)
if (!SPRINGFRAMEWORK_BOOT_DOMAIN.equals(domain)) {
beansJson = getBeansFromActuator(domain);
if (StringUtil.hasText(beansJson)) {
if (beansJson != null) {
jmxMbeanActuatorDomain = domain;
break;
}