面试宝典-Nacos源码解析(一)

229 阅读3分钟

Nacos服务的注册需要具备哪些能力

  • 服务的提供者需要把自己的协议注册到Nacos Server上。
  • 服务的消费者需要在Nacos Server查询提供者所提供的地址。
  • Nacos Server需要知道服务提供者的上下线的变化
  • 服务消费者需要动态的知道Nacos Server端服务地址的变化

Nacos的实现原理

图片

如上图所示,服务在进行注册的时候会通过轮询这一种方式来对注册中心的集群节点进行服务注册。在注册中心里采用了Map来存储实例的具体信息,如果配置了持久化那么服务就会被保存在数据库当中。在服务的调用者,就是为了保证服务的实例能够被动态的感知,Nacos采用Pull/push同时运行的方式。

微服务的注册

服务注册这一个动作,它把服务注册到哪里了呢?注册中心通过了一个叫ServiceHolder来处理每一个服务,当各个服务启动后并且注册到注册中心之后,就可以通过心跳模式来保证服务的存活状态。如果发现有无心跳的服务的话,注册中心就会提出失效。Nacos服务端就会觉得实例不健康,在30s没收到心跳就会把这个临时实例给摘除掉。

图片

微服务是如何发现的

服务到注册中心之后,服务的消费者就可以开始向注册中心来订阅服务了,当注册中心发生变换的时候,监听器会接收到通知,然后消费者就开始更新本地的服务实例列表,这样来保证所有的服务都是可用的。

图片

两者是如何进行调用的

服务提供者跟服务消费者之间呢是通过feign+ribbon进行配合使用的,feign是提供了http请求的封装以及调用,ribbon就提供了负载均衡。负载均衡的方式有很多种,比如随机方法、轮询、hash取模这些等等。在Nacos的客户端获取到服务的完整实例之后,就会在客户端进行负载均衡了。默认使用随机获取。

图片

Nacos源码解析

org.springframework.cloud.client.serviceregistry包下面有三个接口,这是服务注册的核心接口:

  1. AutoServiceRegistration接口
  2. Registration接口
  3. ServiceRegistry接口

首先看AutoServiceRegistration接口

public interface AutoServiceRegistration {

}

AutoServiceRegistration用在服务自动注册。服务启动后自动把服务注册到注册中心。这个接口没有定义方法,它的存在就是要规范实现必须要有自动注册。Spring Cloud中有一个抽象类AbstractAutoServiceRegistration实现了这个接口。

接着来看Registration接口

Registration继承ServiceInstance接口,ServiceInstance接口定义了一个服务实例应该具有哪些服务信息

public interface ServiceInstance {

 // 返回服务实例唯一ID
 default String getInstanceId() {
  return null;
 }

 // 返回服务ID,服务名称
 String getServiceId();

 // 返回服务实例所在的主机的host值
 String getHost();

 // 返回服务实例的port
 int getPort();

 // 返回服务的实例port是否启用了https协议
 boolean isSecure();

 // 返回服务的URI地址
 URI getUri();

 // 返回服务实力的元数据
 Map<String, String> getMetadata();

 // 返回服务实例的scheme
 default String getScheme() {
  return null;
 }
}

ServiceRegistry接口

ServiceRegistry是服务注册接口,用来向注册中心注册服务

public interface ServiceRegistry<R extends Registration> {

 // 注册服务,registration保存了服务的信息
 void register(R registration);

 // 反注册,也就是从注册中心移除注册的服务信息
 void deregister(R registration);

    // 关闭ServiceRegistry,这是一个生命周期函数
 void close();

    /**
     * 设置服务的状态,status的值取决于具体的实现。
     * 查看org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
     */
 void setStatus(R registration, String status);

 /**
  * 获取服务状态值。
  * 查看org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
  */
 <T> getStatus(R registration);
}

\