序
本文主要研究一下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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。