将一个普通的Spring Boot应用注册到Eureka Server或是从Eureka Server中获取服务列表,主要做了两件事:
1 在应用主类中配置了@EnableDiscoveryClient注解。
2 在application.properties中用eureka.client.serviceurl.defualtZone参数指定了服务注册中心的位置。
顺着上面的线索,我们看看@EnableDiscoveryClient的源码,具体代码如下:
/**
* Annotation to enable a DiscoveryClient implementation.
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
}
从该注解的注释中我们可以知道,它主要用来开启DiscoveryClient的实例。通过搜索DiscoveryClient,我们梳理出如下关系图:
其中左边的org.springframework.cloud.client.discovery.DiscoveryClient是Spring Cloud的接口,它定义了用来发现服务的常用抽象方法,通过该接口可以有效地屏蔽服务治理的实现细节,所有使用Spring Cloud构建的微服务应用可以方便地切换不同服务治理框架,而不改动代码。org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient是对该接口的实现,从命名判断,它实现的是对Eureka发现服务的封装。所以EurekaDiscoveryClient依赖了Netflix Eureka的com.netflix.discovery.EurekaClient接口,EurekaClient继承了LookupService接口,它们都是Netflix开源包中的内容,主要定义了Eureka的发现服务的抽象方法,而真正实现发现服务的则是Netflix包中的com.netflix.discovery.DiscoveryClient类。
先看看DiscoveryClient类的注释:
这个类用于帮助与Eureka Server互相协作
Eureka Client负责下面任务:
-向Eureka Server注册服务实例
-向Eureka Server服务租约
-当服务关闭,向Eureka Serve取消租约
-查询Eureka Server中的服务实例列表
Eureka Client还需要配置一个Eureka Server的URL列表。
我们看看在哪里对Eureka Server的URL列表进行配置。
public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) {
Map<String, List<String>> orderedUrls = new LinkedHashMap<>();
String region = getRegion(clientConfig);
String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
if (availZones == null || availZones.length == 0) {
availZones = new String[1];
availZones[0] = DEFAULT_ZONE;
}
logger.debug("The availability zone for the given region {} are {}", region, availZones);
int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);
String zone = availZones[myZoneOffset];
List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
if (serviceUrls != null) {
orderedUrls.put(zone, serviceUrls);
}
int currentOffset = myZoneOffset == (availZones.length - 1) ? 0 : (myZoneOffset + 1);
while (currentOffset != myZoneOffset) {
zone = availZones[currentOffset];
serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
if (serviceUrls != null) {
orderedUrls.put(zone, serviceUrls);
}
if (currentOffset == (availZones.length - 1)) {
currentOffset = 0;
} else {
currentOffset++;
}
}
if (orderedUrls.size() < 1) {
throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!");
}
return orderedUrls;
}