序
本文主要研究一下 dubbo 的 DubboHealthIndicator
DubboHealthIndicator
dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicator.java
public class DubboHealthIndicator extends AbstractHealthIndicator {
@Autowired
private DubboHealthIndicatorProperties dubboHealthIndicatorProperties;
@Autowired(required = false)
private Map<String, ProtocolConfig> protocolConfigs = Collections.emptyMap();
@Autowired(required = false)
private Map<String, ProviderConfig> providerConfigs = Collections.emptyMap();
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {ExtensionLoader<StatusChecker> extensionLoader = getExtensionLoader(StatusChecker.class);
Map<String, String> statusCheckerNamesMap = resolveStatusCheckerNamesMap();
boolean hasError = false;
boolean hasUnknown = false;
// Up first
builder.up();
for (Map.Entry<String, String> entry : statusCheckerNamesMap.entrySet()) {String statusCheckerName = entry.getKey();
String source = entry.getValue();
StatusChecker checker = extensionLoader.getExtension(statusCheckerName);
org.apache.dubbo.common.status.Status status = checker.check();
org.apache.dubbo.common.status.Status.Level level = status.getLevel();
if (!hasError && level.equals(org.apache.dubbo.common.status.Status.Level.ERROR)) {
hasError = true;
builder.down();}
if (!hasError && !hasUnknown && level.equals(org.apache.dubbo.common.status.Status.Level.UNKNOWN)) {
hasUnknown = true;
builder.unknown();}
Map<String, Object> detail = new LinkedHashMap<>();
detail.put("source", source);
detail.put("status", status);
builder.withDetail(statusCheckerName, detail);
}
}
/**
* Resolves the map of {@link StatusChecker}'s name and its' source.
*
* @return non-null {@link Map}
*/
protected Map<String, String> resolveStatusCheckerNamesMap() {Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProtocolConfigs());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProviderConfig());
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties() {
DubboHealthIndicatorProperties.Status status =
dubboHealthIndicatorProperties.getStatus();
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (String statusName : status.getDefaults()) {statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.defaults");
}
for (String statusName : status.getExtras()) {statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.extras");
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProtocolConfigs() {Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProtocolConfig> entry : protocolConfigs.entrySet()) {String beanName = entry.getKey();
ProtocolConfig protocolConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(protocolConfig);
for (String statusCheckerName : statusCheckerNames) {String source = buildSource(beanName, protocolConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProviderConfig() {Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProviderConfig> entry : providerConfigs.entrySet()) {String beanName = entry.getKey();
ProviderConfig providerConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(providerConfig);
for (String statusCheckerName : statusCheckerNames) {String source = buildSource(beanName, providerConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Set<String> getStatusCheckerNames(ProtocolConfig protocolConfig) {String status = protocolConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private Set<String> getStatusCheckerNames(ProviderConfig providerConfig) {String status = providerConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private String buildSource(String beanName, Object bean) {return beanName + "@" + bean.getClass().getSimpleName() + ".getStatus()";
}
}
- DubboHealthIndicator 继承了 AbstractHealthIndicator,这里注入了 dubboHealthIndicatorProperties、protocolConfigs、providerConfigs
- doHealthCheck 方法会先获取 StatusChecker 的 ExtensionLoader,然后通过 resolveStatusCheckerNamesMap 方法获取 statusCheckerNamesMap,之后遍历该 map 根据 statusCheckerName 获取 checker,然后执行 check 获取 status 及 level,构建 detail
- resolveStatusCheckerNamesMap 方法分别通过 resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties、resolveStatusCheckerNamesMapFromProtocolConfigs、resolveStatusCheckerNamesMapFromProviderConfig 来组装 statusCheckerNamesMap
DubboHealthIndicatorTest
dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorTest.java
@RunWith(SpringRunner.class)
@TestPropertySource(properties = {
"dubbo.protocol.id = dubbo-protocol",
"dubbo.protocol.name = dubbo",
"dubbo.protocol.port = 12345",
"dubbo.protocol.status = registry",
"dubbo.provider.id = dubbo-provider",
"dubbo.provider.status = server",
"management.health.dubbo.status.defaults = memory",
"management.health.dubbo.status.extras = load,threadpool"
})
@SpringBootTest(
classes = {
DubboHealthIndicator.class,
DubboHealthIndicatorTest.class
}
)
@EnableConfigurationProperties(DubboHealthIndicatorProperties.class)
@EnableDubboConfig
public class DubboHealthIndicatorTest {
@Autowired
private DubboHealthIndicator dubboHealthIndicator;
@Test
public void testResolveStatusCheckerNamesMap() {Map<String, String> statusCheckerNamesMap = dubboHealthIndicator.resolveStatusCheckerNamesMap();
Assert.assertEquals(5, statusCheckerNamesMap.size());
Assert.assertEquals("dubbo-protocol@ProtocolConfig.getStatus()", statusCheckerNamesMap.get("registry"));
Assert.assertEquals("dubbo-provider@ProviderConfig.getStatus()", statusCheckerNamesMap.get("server"));
Assert.assertEquals("management.health.dubbo.status.defaults", statusCheckerNamesMap.get("memory"));
Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("load"));
Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("threadpool"));
}
@Test
public void testHealth() {Health health = dubboHealthIndicator.health();
Assert.assertEquals(Status.UNKNOWN, health.getStatus());
}
}
- DubboHealthIndicatorTest 验证了 resolveStatusCheckerNamesMap 及 dubboHealthIndicator.health() 方法
DubboHealthIndicatorProperties
dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorProperties.java
@ConfigurationProperties(prefix = PREFIX, ignoreUnknownFields = false)
public class DubboHealthIndicatorProperties {
/**
* The prefix of {@link DubboHealthIndicatorProperties}
*/
public static final String PREFIX = "management.health.dubbo";
private Status status = new Status();
public Status getStatus() {return status;}
public void setStatus(Status status) {this.status = status;}
/**
* The nested class for {@link StatusChecker}'s names
* <pre>
* registry= org.apache.dubbo.registry.status.RegistryStatusChecker
* spring= org.apache.dubbo.config.spring.status.SpringStatusChecker
* datasource= org.apache.dubbo.config.spring.status.DataSourceStatusChecker
* memory= org.apache.dubbo.common.status.support.MemoryStatusChecker
* load= org.apache.dubbo.common.status.support.LoadStatusChecker
* server= org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker
* threadpool= org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker
* </pre>
*
* @see StatusChecker
*/
public static class Status {
/**
* The defaults names of {@link StatusChecker}
* <p>
* The defaults : "memory", "load"
*/
private Set<String> defaults = new LinkedHashSet<>(Arrays.asList("memory", "load"));
/**
* The extra names of {@link StatusChecker}
*/
private Set<String> extras = new LinkedHashSet<>();
public Set<String> getDefaults() {return defaults;}
public void setDefaults(Set<String> defaults) {this.defaults = defaults;}
public Set<String> getExtras() {return extras;}
public void setExtras(Set<String> extras) {this.extras = extras;}
}
}
- DubboHealthIndicatorProperties 定义了 Status,其定义了 defaults、extras 字段
小结
- DubboHealthIndicator 继承了 AbstractHealthIndicator,这里注入了 dubboHealthIndicatorProperties、protocolConfigs、providerConfigs
- doHealthCheck 方法会先获取 StatusChecker 的 ExtensionLoader,然后通过 resolveStatusCheckerNamesMap 方法获取 statusCheckerNamesMap,之后遍历该 map 根据 statusCheckerName 获取 checker,然后执行 check 获取 status 及 level,构建 detail
- resolveStatusCheckerNamesMap 方法分别通过 resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties、resolveStatusCheckerNamesMapFromProtocolConfigs、resolveStatusCheckerNamesMapFromProviderConfig 来组装 statusCheckerNamesMap
doc
- DubboHealthIndicator