Spring Cloud Alibaba致力于提供微服务开发的一站式解决方案,它是Spring Cloud组件被植入Alibaba元素之后的产物。利用Spring Cloud Alibaba,可以快速搭建微服务架构并完成技术升级。中小企业如果需要快速落地业务中台和技术中台,并向数字化业务转型,那Spring Cloud Alibaba绝对是一个“神器”。
本系列将带着大家一起鸟瞰Spring Cloud Alibaba注册中心,从而熟悉它的注册中心架构及相关原理。
回忆一下什么是元数据
咱们试着这样想一下,无论是我们使用Dubbo还是Spring Cloud,又或是Spring Cloud Alibaba,甚至很多公司自研的服务治理的框架,当然还有一些中间件框架,比如RocketMQ。它们都有一个统一的领域概念“元数据”,其实了可以将元数据理解为框架的基础数据,其他任何功能模块的业务都是长在“元数据”之上的。
我们就用Nacos注册中心来举例子,Nacos的元数据主要包含Nacos数据(如配置和服务)的描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义的标签(label)。从作用范围来看,元数据分为服务元数据、集群元数据及实例元数据。
Spring Cloud只是一个基础的微服务框架,它底层是整合了Consul、Zookeeper以及Eureka的注册中心,所以为了兼容这个三个注册中心,Spring Cloud定义了一套“基于Spring Cloud”的元数据中心标准。
这么说,Nacos注册中心的元数据和Spring Cloud的元数据是不兼容的,试着想一下也是这个道理,Nacos是一个独立的云原生服务治理和分布式配置管理的平台,它不可能单独的为Spring Cloud做定制化的开发,所以呢需要有框架去解决这些问题。
于是Spring Cloud Alibaba来了,它专门是来解决Nacos元数据和Spring Cloud元数据的兼容性问题的。
如何适配Spring Cloud 和Nacos的元数据
好吧,既然我们已经知道Spring Cloud Alibaba已经解决了元数据适配的问题,我们先从方法论的角度来看。
既然Spring Cloud定义了一套元数据标准,那么肯定要在它的基础之上去扩展,那么从Java语言的角度去看,能够满足扩展的最快的方式是接口和接口的实现,也就是说Spring Cloud肯定是定义了接口,让开发人员自己去实现,然后将实现类注入到Spring IOC容器中,这样才能满足Spring Cloud兼容不同注册中心的元数据标准。
好吧,听起来确实是很有道理,我们还是看看部分源码,毕竟我们是35岁程序员。
我们仔细的看看Spring Cloud Alibaba封装的两个NacosRegistration类和NacosServiceRegistry类,这个是非常关键的适配类,要仔细阅读源码。
第一步看看NacosServiceRegistry类,如下。
代码语言:javascript复制//为了方便大家看代码设计的思想,这里就省略了大部分代码,保留代码骨架
public class NacosServiceRegistry implements ServiceRegistry<Registration> { //实现了Spring Cloud的ServiceRegistry类的register()方法
@Override
public void register(Registration registration) {}
//实现了Spring Cloud的ServiceRegistry类的deregister()方法
@Override
public void deregister(Registration registration) {}
}
我们重点看register()方法和deregister()方法的入参,它是Spring Cloud的Registration 类。
第二步,我们再仔细看看NacosRegistration类,如下。
代码语言:javascript复制//为了方便大家看代码设计的思想,这里就省略了大部分代码,保留代码骨架
public class NacosRegistration implements Registration, ServiceInstance {
//NacosRegistration类实现了Spring Cloud的Registration类和ServiceInstance 类
//下面这些就更加熟悉,这个不就是服务元数据的属性吗。
//什么服务ID、host、port等,这些太熟悉了
@Override
public String getServiceId() {
return nacosDiscoveryProperties.getService();
}
@Override
public String getHost() {
return nacosDiscoveryProperties.getIp();
}
@Override
public int getPort() {
return nacosDiscoveryProperties.getPort();
}
public void setPort(int port) {
this.nacosDiscoveryProperties.setPort(port);
}
...
}
那么看到NacosRegistration类之后是不是就恍然大悟,会不会NacosRegistration类注入到Spring IOC容器之后,会作为NacosServiceRegistry类的入参呢?好吧,带着问题我们再看看确认下是不是这样的设计原理。
于是我们打开Spring Cloud的AbstractAutoServiceRegistration类
代码语言:javascript复制public abstract class AbstractAutoServiceRegistration<R extends Registration>
implements AutoServiceRegistration, ApplicationContextAware,
ApplicationListener<WebServerInitializedEvent> {
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
AutoServiceRegistrationProperties properties) {
this.serviceRegistry = serviceRegistry;
this.properties = properties;
}
//使用接口ServiceRegistry的实现类的方法register()完成注册,元数据是通过方法getRegistration()获取的
/**
* Register the local service with the {@link ServiceRegistry}.
*/
protected void register() {
this.serviceRegistry.register(getRegistration());
}
//使用接口ServiceRegistry的实现类的方法deregister()完成注册,元数据是通过方法getRegistration()获取的
/**
* De-register the local service with the {@link ServiceRegistry}.
*/
protected void deregister() {
this.serviceRegistry.deregister(getRegistration());
}
...
}
我们再回过头看看这个不就是Spring Cloud Alibaba定义的两个实现类NacosRegistration类和NacosServiceRegistry类。
好吧我们再看看是如何注入到Spring Cloud的AbstractAutoServiceRegistration类中的。
我们可以打开Spring Cloud Alibaba的NacosAutoServiceRegistration类,它继承了Spring Cloud的AbstractAutoServiceRegistration类。
代码语言:javascript复制public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory
.getLogger(NacosAutoServiceRegistration.class);
private NacosRegistration registration;
//通过构造函数注入了NacosRegistration类和和NacosServiceRegistry类
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
//重写了AbstractAutoServiceRegistration类的getRegistration()方法,让Spring Cloud能够获取Spring Cloud Alibaba自定义的NacosRegistration类
@Override
protected NacosRegistration getRegistration() {
if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
this.registration.setPort(this.getPort().get());
}
Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
return this.registration;
}
}
这样大家是不是就非常熟悉Nacos和Spring Cloud的元数据是如何整合和适配的了。
总结
本文带着大家熟悉了Nacos和Spring Cloud的元数据整合的代码细节。
下一期:将会从架构设计的角度去分析Nacos和Spring Cloud的元数据整合。