1. 程式人生 > 程式設計 >聊聊dubbo的DubboHealthIndicator

聊聊dubbo的DubboHealthIndicator

本文主要研究一下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,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("[email protected]()",statusCheckerNamesMap.get("registry"));
        Assert.assertEquals("[email protected]()",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