回想一下,对于微服务架构中,所有的服务需要到注册中心去注册服务,并将服务的信息发送给注册中心,然后它会按照一定的周期从服务中心获取服务信息列表,默认的时间为30秒,并且会将自身的服务按照一定的时间间隔向注册中心续约,这个时间默认也是30秒。那么抽象一下,服务客户端需要做这么几件事情:
1、向注册中心提交注册
2、从注册中心获取服务列表
3、按照一定的时间续约
4、如果下线了,则告诉注册中心,我要下线了。
Spring 对于发现服务服务客户端提供了顶级的接口,接口隐藏了实现的具体细节,以保障Spring Cloud可以任意的切换成任何服务治理框架。
public interface DiscoveryClient {
//获取描述
String description();
//根据服务的ID获取服务实例列表
//由于是微服务的架构,每个服务的实例有可能不只一个,所以这里会返回一个列表
List<ServiceInstance> getInstances(String serviceId);
//获取所有服务的集合
List<String> getServices();
}
查看它的Eureka实现类如下
public class EurekaDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
private final EurekaInstanceConfig config;
private final EurekaClient eurekaClient;
public EurekaDiscoveryClient(EurekaInstanceConfig config, EurekaClient eurekaClient) {
this.config = config;
this.eurekaClient = eurekaClient;
}
public String description() {
return "Spring Cloud Eureka Discovery Client";
}
public List<ServiceInstance> getInstances(String serviceId) {
//从eurekaClient对象中获取实例的地址信息
List<InstanceInfo> infos = this.eurekaClient.getInstancesByVipAddress(serviceId, false);
List<ServiceInstance> instances = new ArrayList();
Iterator var4 = infos.iterator();
while(var4.hasNext()) {
InstanceInfo info = (InstanceInfo)var4.next();
instances.add(new EurekaDiscoveryClient.EurekaServiceInstance(info));
}
return instances;
}
public List<String> getServices() {
//首先从eurekaClient获取所有的应用
Applications applications = this.eurekaClient.getApplications();
if (applications == null) {
return Collections.emptyList();
} else {
//获取所有已经注册的应用
List<Application> registered = applications.getRegisteredApplications();
List<String> names = new ArrayList();
Iterator var4 = registered.iterator();
//遍历已经注册的应用的名称
while(var4.hasNext()) {
Application app = (Application)var4.next();
if (!app.getInstances().isEmpty()) {
names.add(app.getName().toLowerCase());
}
}
return names;
}
}
从代码中不难发现,所有的操作都依赖一个对象,那就是EurekaClient。查看它的实现方式。
//向服务中心注册服务
boolean register() throws Throwable {
logger.info("DiscoveryClient_{}: registering service...", this.appPathIdentifier);
EurekaHttpResponse httpResponse;
try {
httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo);
} catch (Exception var3) {
logger.warn("DiscoveryClient_{} - registration failed {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});
throw var3;
}
if (logger.isInfoEnabled()) {
logger.info("DiscoveryClient_{} - registration status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
}