专栏首页码匠的流水账聊聊ZookeeperDiscoveryAutoConfiguration

聊聊ZookeeperDiscoveryAutoConfiguration

本文主要研究一下ZookeeperDiscoveryAutoConfiguration

ZookeeperDiscoveryAutoConfiguration

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryAutoConfiguration.java

@Configuration
@ConditionalOnBean(ZookeeperDiscoveryClientConfiguration.Marker.class)
@ConditionalOnZookeeperDiscoveryEnabled
@AutoConfigureBefore({ CommonsClientAutoConfiguration.class,
        NoopDiscoveryClientAutoConfiguration.class })
@AutoConfigureAfter({ ZookeeperDiscoveryClientConfiguration.class })
public class ZookeeperDiscoveryAutoConfiguration {

@Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies;

@Autowired
private CuratorFramework curator;

@Bean
@ConditionalOnMissingBean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(
            InetUtils inetUtils) {
        return new ZookeeperDiscoveryProperties(inetUtils);
}

@Bean
@ConditionalOnMissingBean
// currently means auto-registration is false. That will change when
// ZookeeperServiceDiscovery is gone
public ZookeeperDiscoveryClient zookeeperDiscoveryClient(
            ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
            ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
        return new ZookeeperDiscoveryClient(serviceDiscovery, this.zookeeperDependencies,
                zookeeperDiscoveryProperties);
}

@Bean
public ZookeeperServiceWatch zookeeperServiceWatch(
            ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
        return new ZookeeperServiceWatch(this.curator, zookeeperDiscoveryProperties);
}

@Configuration
@ConditionalOnEnabledHealthIndicator("zookeeper")
@ConditionalOnClass(Endpoint.class)
protected static class ZookeeperDiscoveryHealthConfig {

        @Autowired(required = false)
        private ZookeeperDependencies zookeeperDependencies;

        @Bean
        @ConditionalOnMissingBean
        public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator(
                CuratorFramework curatorFramework,
                ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
                ZookeeperDiscoveryProperties properties) {
            return new ZookeeperDiscoveryHealthIndicator(curatorFramework,
                    serviceDiscovery, this.zookeeperDependencies, properties);
        }

}

}
  • ZookeeperDiscoveryAutoConfiguration注册了ZookeeperDiscoveryProperties、ZookeeperDiscoveryClient、ZookeeperServiceWatch、ZookeeperDiscoveryHealthIndicator

ZookeeperDiscoveryProperties

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryProperties.java

@ConfigurationProperties("spring.cloud.zookeeper.discovery")
public class ZookeeperDiscoveryProperties {

/**
 * Default URI spec.
 */
public static final String DEFAULT_URI_SPEC = "{scheme}://{address}:{port}";

private InetUtils.HostInfo hostInfo;

private boolean enabled = true;

/**
 * Root Zookeeper folder in which all instances are registered.
 */
private String root = "/services";

/**
 * The URI specification to resolve during service registration in Zookeeper.
 */
private String uriSpec = DEFAULT_URI_SPEC;

/** Id used to register with zookeeper. Defaults to a random UUID. */
private String instanceId;

/**
 * Predefined host with which a service can register itself in Zookeeper. Corresponds
 * to the {code address} from the URI spec.
 */
private String instanceHost;

/**
 * IP address to use when accessing service (must also set preferIpAddress to use).
 */
private String instanceIpAddress;

/**
 * Use ip address rather than hostname during registration.
 */
private boolean preferIpAddress = false;

/** Port to register the service under (defaults to listening port). */
private Integer instancePort;

/** Ssl port of the registered service. */
private Integer instanceSslPort;

/**
 * Register as a service in zookeeper.
 */
private boolean register = true;

/**
 * Gets the metadata name/value pairs associated with this instance. This information
 * is sent to zookeeper and can be used by other instances.
 */
private Map<String, String> metadata = new HashMap<>();

/**
 * The initial status of this instance (defaults to
 * {@link StatusConstants#STATUS_UP}).
 */
private String initialStatus = StatusConstants.STATUS_UP;

/**
 * Order of the discovery client used by `CompositeDiscoveryClient` for sorting
 * available clients.
 */
private int order = 0;

//......
}
  • ZookeeperDiscoveryProperties定义了enabled、root、uriSpec、instanceId、instanceHost、instanceIpAddress、preferIpAddress、instancePort、instanceSslPort、register、metadata、initialStatus、order属性

ZookeeperDiscoveryClient

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClient.java

public class ZookeeperDiscoveryClient implements DiscoveryClient {

private static final Log log = LogFactory.getLog(ZookeeperDiscoveryClient.class);

private final ZookeeperDependencies zookeeperDependencies;

private final ServiceDiscovery<ZookeeperInstance> serviceDiscovery;

private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;

public ZookeeperDiscoveryClient(ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
            ZookeeperDependencies zookeeperDependencies,
            ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
        this.serviceDiscovery = serviceDiscovery;
        this.zookeeperDependencies = zookeeperDependencies;
        this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
}

@Override
public String description() {
        return "Spring Cloud Zookeeper Discovery Client";
}

private static org.springframework.cloud.client.ServiceInstance createServiceInstance(
            String serviceId, ServiceInstance<ZookeeperInstance> serviceInstance) {
        return new ZookeeperServiceInstance(serviceId, serviceInstance);
}

@Override
public List<org.springframework.cloud.client.ServiceInstance> getInstances(
            final String serviceId) {
        try {
            if (getServiceDiscovery() == null) {
                return Collections.EMPTY_LIST;
            }
            String serviceIdToQuery = getServiceIdToQuery(serviceId);
            Collection<ServiceInstance<ZookeeperInstance>> zkInstances = getServiceDiscovery()
                    .queryForInstances(serviceIdToQuery);
            List<org.springframework.cloud.client.ServiceInstance> instances = new ArrayList<>();
            for (ServiceInstance<ZookeeperInstance> instance : zkInstances) {
                instances.add(createServiceInstance(serviceIdToQuery, instance));
            }
            return instances;
        }
        catch (KeeperException.NoNodeException e) {
            if (log.isDebugEnabled()) {
                log.debug(
                        "Error getting instances from zookeeper. Possibly, no service has registered.",
                        e);
            }
            // this means that nothing has registered as a service yes
            return Collections.emptyList();
        }
        catch (Exception exception) {
            rethrowRuntimeException(exception);
        }
        return new ArrayList<>();
}

private ServiceDiscovery<ZookeeperInstance> getServiceDiscovery() {
        return this.serviceDiscovery;
}

private String getServiceIdToQuery(String serviceId) {
        if (this.zookeeperDependencies != null
                && this.zookeeperDependencies.hasDependencies()) {
            String pathForAlias = this.zookeeperDependencies.getPathForAlias(serviceId);
            return pathForAlias.isEmpty() ? serviceId : pathForAlias;
        }
        return serviceId;
}

@Override
public List<String> getServices() {
        List<String> services = null;
        if (getServiceDiscovery() == null) {
            log.warn(
                    "Service Discovery is not yet ready - returning empty list of services");
            return Collections.emptyList();
        }
        try {
            Collection<String> names = getServiceDiscovery().queryForNames();
            if (names == null) {
                return Collections.emptyList();
            }
            services = new ArrayList<>(names);
        }
        catch (KeeperException.NoNodeException e) {
            if (log.isDebugEnabled()) {
                log.debug(
                        "Error getting services from zookeeper. Possibly, no service has registered.",
                        e);
            }
            // this means that nothing has registered as a service yes
            return Collections.emptyList();
        }
        catch (Exception e) {
            rethrowRuntimeException(e);
        }
        return services;
}

@Override
public int getOrder() {
        return this.zookeeperDiscoveryProperties.getOrder();
}

}
  • ZookeeperDiscoveryClient实现了org.springframework.cloud.client.discovery.DiscoveryClient接口,其getInstances使用curator的ServiceDiscovery.queryForInstances获取服务实例信息,然后转换为org.springframework.cloud.client.ServiceInstance类型;getServices则是使用curator的ServiceDiscovery.queryForNames获取服务名信息

ZookeeperServiceWatch

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceWatch.java

public class ZookeeperServiceWatch
        implements ApplicationListener<InstanceRegisteredEvent<?>>, TreeCacheListener,
        ApplicationEventPublisherAware {

private final CuratorFramework curator;

private final ZookeeperDiscoveryProperties properties;

private final AtomicLong cacheChange = new AtomicLong(0);

private ApplicationEventPublisher publisher;

private TreeCache cache;

public ZookeeperServiceWatch(CuratorFramework curator,
            ZookeeperDiscoveryProperties properties) {
        this.curator = curator;
        this.properties = properties;
}

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
}

public TreeCache getCache() {
        return this.cache;
}

@Override
public void onApplicationEvent(InstanceRegisteredEvent<?> event) {
        this.cache = TreeCache.newBuilder(this.curator, this.properties.getRoot())
                .build();
        this.cache.getListenable().addListener(this);
        try {
            this.cache.start();
        }
        catch (Exception e) {
            ReflectionUtils.rethrowRuntimeException(e);
        }
}

@PreDestroy
public void stop() throws Exception {
        if (this.cache != null) {
            this.cache.close();
        }
}

@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event)
            throws Exception {
        if (event.getType().equals(TreeCacheEvent.Type.NODE_ADDED)
                || event.getType().equals(TreeCacheEvent.Type.NODE_REMOVED)
                || event.getType().equals(TreeCacheEvent.Type.NODE_UPDATED)) {
            long newCacheChange = this.cacheChange.incrementAndGet();
            this.publisher.publishEvent(new HeartbeatEvent(this, newCacheChange));
        }
}

}
  • ZookeeperServiceWatch实现了ApplicationListener、TreeCacheListener、ApplicationEventPublisherAware接口;其childEvent方法在event类型是NODE_ADDED、NODE_REMOVED、NODE_UPDATED类型时会发布HeartbeatEvent事件

ZookeeperDiscoveryHealthIndicator

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryHealthIndicator.java

public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicator {

private static final Log log = LogFactory
            .getLog(ZookeeperDiscoveryHealthIndicator.class);

private CuratorFramework curatorFramework;

private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;

private final ZookeeperDependencies zookeeperDependencies;

private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;

public ZookeeperDiscoveryHealthIndicator(CuratorFramework curatorFramework,
            ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
            ZookeeperDependencies zookeeperDependencies,
            ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
        this.curatorFramework = curatorFramework;
        this.serviceDiscovery = serviceDiscovery;
        this.zookeeperDependencies = zookeeperDependencies;
        this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
}

@Override
public String getName() {
        return "zookeeper";
}

@Override
public Health health() {
        Health.Builder builder = Health.unknown();
        try {
            Iterable<ServiceInstance<ZookeeperInstance>> allInstances = new ZookeeperServiceInstances(
                    this.curatorFramework, this.serviceDiscovery,
                    this.zookeeperDependencies, this.zookeeperDiscoveryProperties);
            builder.up().withDetail("services", allInstances);
        }
        catch (Exception e) {
            log.error("Error", e);
            builder.down(e);
        }

        return builder.build();
}

}
  • ZookeeperDiscoveryHealthIndicator实现了DiscoveryHealthIndicator接口,其health方法创建ZookeeperServiceInstances

ZookeeperServiceInstances

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/ZookeeperServiceInstances.java

public class ZookeeperServiceInstances
        implements Iterable<ServiceInstance<ZookeeperInstance>> {

private static final Log log = LogFactory.getLog(ZookeeperServiceInstances.class);

private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;

private final ZookeeperDependencies zookeeperDependencies;

private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;

private final List<ServiceInstance<ZookeeperInstance>> allInstances;

private final CuratorFramework curator;

public ZookeeperServiceInstances(CuratorFramework curator,
            ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
            ZookeeperDependencies zookeeperDependencies,
            ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
        this.curator = curator;
        this.serviceDiscovery = serviceDiscovery;
        this.zookeeperDependencies = zookeeperDependencies;
        this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties;
        this.allInstances = getZookeeperInstances();
}

private List<ServiceInstance<ZookeeperInstance>> getZookeeperInstances() {
        ArrayList<ServiceInstance<ZookeeperInstance>> allInstances = new ArrayList<>();
        try {
            Collection<String> namesToQuery = getNamesToQuery();
            if (log.isDebugEnabled()) {
                log.debug("Querying the following names [" + namesToQuery + "]");
            }
            for (String name : namesToQuery) {
                allInstances.addAll(nestedInstances(allInstances, name));
            }
            return allInstances;
        }
        catch (Exception e) {
            log.debug("Exception occurred while trying to build the list of instances",
                    e);
            return allInstances;
        }
}

//......
}
  • ZookeeperServiceInstances的构造器会调用getZookeeperInstances拉取ServiceInstance

小结

ZookeeperDiscoveryAutoConfiguration注册了ZookeeperDiscoveryProperties、ZookeeperDiscoveryClient、ZookeeperServiceWatch、ZookeeperDiscoveryHealthIndicator

doc

  • ZookeeperDiscoveryAutoConfiguration

本文分享自微信公众号 - 码匠的流水账(geek_luandun),作者:码匠乱炖

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊聊ZookeeperDiscoveryAutoConfiguration

    本文主要研究一下ZookeeperDiscoveryAutoConfiguration

    codecraft
  • 聊聊maxwell的BinlogConnectorDiagnostic

    本文主要研究一下maxwell的BinlogConnectorDiagnostic

    codecraft
  • 聊聊maxwell的BinlogConnectorDiagnostic

    本文主要研究一下maxwell的BinlogConnectorDiagnostic

    codecraft
  • 聊聊ZookeeperDiscoveryAutoConfiguration

    本文主要研究一下ZookeeperDiscoveryAutoConfiguration

    codecraft
  • Lombok介绍、使用方法和总结

    1 Lombok背景介绍 官方介绍如下: Project Lombok makes java a spicier language by adding 'han...

    猿人谷
  • 聊聊maxwell的BinlogConnectorDiagnostic

    本文主要研究一下maxwell的BinlogConnectorDiagnostic

    codecraft
  • 聊聊maxwell的BinlogConnectorDiagnostic

    本文主要研究一下maxwell的BinlogConnectorDiagnostic

    codecraft
  • 微信一次性订阅消息

    http请求方式: post https://api.weixin.qq.com/cgi-bin/message/template/subscribe?acc...

    Javen
  • 猿实战05——手把手教你拥有自己的代码生成器

    哈哈,猿设计终于讲完了,接下来的一段时间,工厂君打算和大家一起来实现我们之间的设计——构建一个自己的电商系统来玩耍。嗯,这个可是一个大工程,代码量很大,业务也比...

    山旮旯的胖子
  • 首页JavaThymeleaf 模板引擎与Spring Boot

    1,Thymeleaf是什么 ? Thymeleaf 是一个Java类库,是一个xml/xhtml/html5的模板引擎,可以作为MVC的Web应用的Vie...

    cherishspring

扫码关注云+社区

领取腾讯云代金券