Spring Cloud 的服务发现和注册的接口

云原生是一种编程方式,包含了一系列的特征,比如符合 12-factor 应用等,为了让一个应用具备云原生的架构,Spring Cloud 提供了不同的组件,但是首要的一点,是如何让分布式系统的的各个组件易于触达。为了达到这一点,Spring Boot 提供了很多的功能,而一些功能则需要 Spring Cloud 的两个依赖包提供:Spring Cloud Context 和 Spring Cloud Commons。那么本文着重介绍 Spring Cloud Commons 中的服务发现和注册接口。

服务的抽象

根据 12-factor 应用的特性,一个应用应当绑定一个或者多个端口对外提供服务,因此要触达不同的应用,我们只需要知道他的端口号,IP或者域名,通讯协议(比如HTTP)等即可。因此Spring Cloud 将一个服务实例抽象如下:

public interface ServiceInstance {
    default String getInstanceId() {return null;}
    String getServiceId();
    String getHost();
    int getPort();
    boolean isSecure();
    URI getUri();
    Map<String, String> getMetadata();
    default String getScheme() {return null;}
}

包含的信息如下:

  • 实例id
  • 服务id
  • 端口号
  • host
  • 是否安全(比如https)
  • URI
  • 元信息Map
  • Scheme协议(比如https/http)

其中,URI getUri(),可以由接口的其他信息构建。因此对于一个客户端来说,只需要知道一个服务的实例URI或者URI列表,就可以发起调用了。

服务发现的抽象

在对服务进行了抽象之后,如何获取服务,成为了第二个关键的问题。获取服务,也可以成为服务发现,定义如下:

public interface DiscoveryClient extends Ordered {
	int DEFAULT_ORDER = 0;
	String description();
	List<ServiceInstance> getInstances(String serviceId);
	List<String> getServices();
	default void probe() {getServices();}
	@Override
	default int getOrder() {return DEFAULT_ORDER;}
}

其定义的方法也很简单,核心在两个方法。

  1. 获取所有的服务名列表
  2. 根据服务名获取服务列表

服务发现的实现类

Spring Cloud Common 依赖包,提供了一个DiscoveryClient的实现类CompositeDiscoveryClient。具体实现如下:

public class CompositeDiscoveryClient implements DiscoveryClient {

	private final List<DiscoveryClient> discoveryClients;

	public CompositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
		AnnotationAwareOrderComparator.sort(discoveryClients);
		this.discoveryClients = discoveryClients;
	}

	@Override
	public List<ServiceInstance> getInstances(String serviceId) {
		if (this.discoveryClients != null) {
			for (DiscoveryClient discoveryClient : this.discoveryClients) {
				List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
				if (instances != null && !instances.isEmpty()) {
					return instances;
				}
			}
		}
		return Collections.emptyList();
	}

	@Override
	public List<String> getServices() {
		LinkedHashSet<String> services = new LinkedHashSet<>();
		if (this.discoveryClients != null) {
			for (DiscoveryClient discoveryClient : this.discoveryClients) {
				List<String> serviceForClient = discoveryClient.getServices();
				if (serviceForClient != null) {
					services.addAll(serviceForClient);
				}
			}
		}
		return new ArrayList<>(services);
	}

}

CompositeDiscoveryClient 并不复杂,其代码表明,Spring Cloud 是支持多注册中心的,在一个客户端系统中,可以存在多个 DiscoveryClient 的实现类,比如可以同时存在 Eureka 和 Nacos。 通过 Spring Cloud Common 中的 spring.factories,CompositeDiscoveryClientAutoConfiguration 自动化配置类会生成 CompositeDiscoveryClient 的spring bean, 所有的实现类都会组合到 CompositeDiscoveryClient 中。因此一般来说,在实现 DiscoveryClient 的时候,只需要将实现类交给 Spring 进行托管,就会注入到 CompositeDiscoveryClient 中,而需要使用 Spring Cloud 的 DiscoveryClient 功能的时候,应该使用 CompositeDiscoveryClient 而不是其他实现类。CompositeDiscoveryClientAutoConfiguration 的实现如下:

@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class CompositeDiscoveryClientAutoConfiguration {
	@Bean
	@Primary
	public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
		return new CompositeDiscoveryClient(discoveryClients);
	}
}

服务注册

public interface ServiceRegistry<R extends Registration> {
    void register(R registration);
    void deregister(R registration);
    void close();
    void setStatus(R registration, String status);
    <T> T getStatus(R registration);

}

public interface Registration extends ServiceInstance {
}

其中,Registration 继承了 ServiceInstance,是一个空的继承,没有任何实现。
ServiceRegistry 的功能很简单,就是将当前的服务注册到注册中心,并且可以修改状态和关闭。

总结

至此,Spring Cloud Common 依赖包中的服务发现和注册接口已经介绍完毕。Spring Cloud 将服务注册和发现高度抽象为了3个接口:DiscoveryClient,ServiceRegistry 和 ServiceInstance,其中 ServiceInstance 代表提供服务的实例的信息,而 DiscoveryClient,ServiceRegistry 代表服务发现行为和服务注册行为。ServiceRegistry 功能较为简单,只是将自身注册到注册中心,提供相应的服务。而 DiscoveryClient 和 ServiceInstance 的使用范围更加广泛,比如客户端段的负载均衡,需要 DiscoveryClient 提供服务提供者列表,用于不同策略的服务调用。 在学习Spring Cloud 的注册中心和客户端负载均衡组件前,记忆和理解这2个接口十分重要。

你可能感兴趣的:(Spring,Cloud,源码分析,spring,cloud,服务发现,java)