Nacos服务注册原理解析

参考:Nacos服务注册源码分析

Spring Boot版本:2.2.9.RELEASE
Spring Cloud版本:Hoxton.SR6
Spring Cloud Alibaba版本:2.2.1.RELEASE
Nacos版本:1.3.1

1 @EnableDiscoveryClient

如果需要启用服务注册功能,需要在启动类上面添加@EnableDiscoveryClient注解。

查看@EnableDiscoveryClient的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
   

	/**
	 * 默认返回值为true。
	 * 如果返回值为true,ServiceRegistry将会自动将本服务注册到服务注册中心。
	 */
	boolean autoRegister() default true;
}

@EnableDiscoveryClient注解的源码中有一个方法autoRegister(),默认返回true,表示希望自动注册服务。

@EnableDiscoveryClient还通过@Import注解引入了EnableDiscoveryClientImportSelector类,查看源码:

@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
		extends SpringFactoryImportSelector<EnableDiscoveryClient> {
   

	@Override
	public String[] selectImports(AnnotationMetadata metadata) {
   
		String[] imports = super.selectImports(metadata);

		AnnotationAttributes attributes = AnnotationAttributes.fromMap(
				metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
        // 获取@EnableDiscoveryClient注解的属性autoRegister的值
		boolean autoRegister = attributes.getBoolean("autoRegister");
        // 如果autoRegister == true,加载AutoServiceRegistrationConfiguration配置类
		if (autoRegister) {
   
			List<String> importsList = new ArrayList<>(Arrays.asList(imports));
			importsList.add(
					"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
			imports = importsList.toArray(new String[0]);
		}
        // 如果autoRegister == false,设置spring.cloud.service-registry.auto-registration.enabled=false,关闭服务自动注册功能
		else {
   
			Environment env = getEnvironment();
			if (ConfigurableEnvironment.class.isInstance(env)) {
   
				ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env;
				LinkedHashMap<String, Object> map = new LinkedHashMap<>();
				map.put("spring.cloud.service-registry.auto-registration.enabled", false);
				MapPropertySource propertySource = new MapPropertySource(
						"springCloudDiscoveryClient", map);
				configEnv.getPropertySources().addLast(propertySource);
			}

		}

		return imports;
	}

	@Override
	protected boolean isEnabled() {
   
		return getEnvironment().getProperty("spring.cloud.discovery.enabled",
				Boolean.class, Boolean.TRUE);
	}

	@Override
	protected boolean hasDefaultFactory() {
   
		return true;
	}

}

主要关注selectImports(...)这个方法。首先获取@EnableDiscoveryClient注解的属性autoRegister的值。

  • 如果autoRegister == true,加载org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration配置类的配置。

  • 如果autoRegister == false,设置spring.cloud.service-registry.auto-registration.enabled=false,关闭自动服务注册功能。因为服务自动注册相关的类在注册到Spring容器的时候都有一个条件@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)

查看AutoServiceRegistrationConfiguration配置类源码:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
      matchIfMissing = true)
public class AutoServiceRegistrationConfiguration {
   

}

可以看到,这个类加载了AutoServiceRegistrationProperties这个属性类,这个类里面维护了所有spring.cloud.service-registry.auto-registration开头的属性的配置值。

@ConfigurationProperties("spring.cloud.service-registry.auto-registration")
public class AutoServiceRegistrationProperties {
   

	/** Whether service auto-registration is enabled. Defaults to true. */
	private boolean enabled = true;

	/** Whether to register the management as a service. Defaults to true. */
	private boolean registerManagement = true;

	/**
	 * Whether startup fails if there is no AutoServiceRegistration. Defaults to false.
	 */
	private boolean failFast = false;
    
    ...
}

可以看到,spring.cloud.service-registry.auto-registration.enabled默认值就是true。也就是说,如果没有使用@EnableDiscoveryClient注解,服务也会被自动注册,因为@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)这个条件默认情况下就是满足的。

但是如果不想自动注册服务,可以通过使用@EnableDiscoveryClient(autoRegister = false),或者直接在配置文件中设置spring.cloud.service-registry.auto-registration.enabled=false

2 Spring Cloud定义的服务发现的统一规范

拥有服务注册的中间件有很多,比如EuerkaConsulZooKeeperNacos等,想要接入Spring Cloud就必须遵守一套统一的规范,Spring Cloud将这套规范定义在了Spring Cloud Common中:

spring-cloud-commons
  -- org.springframework.cloud
    -- client
      -- discovery
      -- loadbalancer
      -- serviceregistry

discovery包下面定义了服务发现的规范,loadbalancer包下面定义了负载均衡的规范,serviceregistry包下面定义了服务注册的规范。

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

  • AutoServiceRegistration接口
  • Registration接口
  • ServiceRegistry接口

2.1 AutoServiceRegistration接口

AutoServiceRegistration用于服务自动注册。自动注册的意思就是,服务启动后自动把服务信息注册到注册中心。

public interface AutoServiceRegistration {
   

}

这个接口没有定义方法,它的存在就是要规范实现必须要有自动注册。

Spring Cloud中有一个抽象类AbstractAutoServiceRegistration实现了这个接口。

2.2 Registration接口

Registration存储服务信息,用于规范将什么信息注册到注册中心。

public interface Registration extends ServiceInstance {
   

}

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;
	}
}

2.3 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> T getStatus(R registration);
}

3 Nacos服务注册的实现

Nacos服务注册模块按照Spring Cloud的规范,实现了AutoServiceRegistrationRegistrationServiceRegistry三个接口,具体的实现了分别是:

  • NacosAutoServiceRegistration
  • NacosRegistration
  • NacosServiceRegistry

这三个类位于spring-cloud-starter-alibaba-nacos-discovery包中的com.alibaba.cloud.nacos.registry包路径下。

3.1 NacosRegistration

首先看看NacosRegistration,这个类管理了Nacos服务的基本信息,如服务名、服务地址和端口等信息。

它实现了Spring Cloud定义的规范接口Registration,同时也实现了ServiceInstance接口。

不过实际上Nacos服务的基本信息都是由NacosDiscoveryProperties这个类来保存的,NacosRegistration只是对NacosDiscoveryProperties进行了封装而已。

public class NacosRegistration implements Registration, ServiceInstance {
   

	/**
	 * management port
	 */
	public static final String MANAGEMENT_PORT = "management.port";

	/**
	 * management context-path.
	 */
	public static final String MANAGEMENT_CONTEXT_PATH = "management.context-path";

	/**
	 * management address.
	 */
	public static final String MANAGEMENT_ADDRESS = "management.address";

	/**
	 * management endpoints web base path.
	 */
	public static final String MANAGEMENT_ENDPOINT_BASE_PATH = "management.endpoints.web.base-path";

    // 配置文件中spring.cloud.nacos.discovery开头的配置的映射类
	private NacosDiscoveryProperties nacosDiscoveryProperties;
    
    // 应用上下文
	private ApplicationContext context;

    // 构造函数注入
	public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties,
			ApplicationContext context) {
   
		this.nacosDiscoveryProperties = nacosDiscoveryProperties;
		this.context = context;
	}

    // 当构造函数执行之后执行的初始化
	@PostConstruct
	public void init() {
   
        
		Map<String, String> metadata = nacosDiscoveryProperties.getMetadata();
		Environment env = context.getEnvironment();

		String endpointBasePath = env.getProperty(MANAGEMENT_ENDPOINT_BASE_PATH);
		if 
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值