准备
使用分支:2022.x
配置使用【服务注册中心与配置中心都有】
- 在父工程的pom文件中声明spring-cloud-alibaba的依赖【控制版本】
- 在子工程的pom文件中添加具体依赖
- 在配置文件中配置nacos信息【这里使用的是yml配置文件。properties需自行转换】
- 确保nacos服务正常,启动服务后nacos的服务列表显示服务信息
Spring-Cloud-Alibaba源码解析
- nacos-discovery模块
- 自动装配配置文件
spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 自动装配配置文件
java
com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration//创建NacosDiscoveryProperties、NacosServiceDiscovery
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration//创建NacosServiceRegistry、NacosRegistration、NacosAutoServiceRegistration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryHeartBeatConfiguration
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration
com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration
2、自动注册
核心在于NacosAutoServiceRegistration的父类AbstractAutoServiceRegistration。在父类中实现了ApplicationListener的onApplicationEvent方法。当ApplicationContext初始化或刷新时触发开始注册方法
- spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java
- org\springframework\cloud\spring-cloud-commons\4.0.0\spring-cloud-commons-4.0.0.jar!\org\springframework\cloud\client\serviceregistry\AbstractAutoServiceRegistration.class【这是spring-cloud提供的,不是alibaba的】
java
public void onApplicationEvent(WebServerInitializedEvent event) {
//ApplicationContext初始化或刷新时触发
ApplicationContext context = event.getApplicationContext();
if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
this.port.compareAndSet(0, event.getWebServer().getPort());
this.start();//※启动
}
}
public void start() {
if (!this.isEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Discovery Lifecycle disabled. Not starting");
}
} else {
if (!this.running.get()) {
this.context.publishEvent(new InstancePreRegisteredEvent(this, this.getRegistration()));
this.registrationLifecycles.forEach((registrationLifecycle) -> {
registrationLifecycle.postProcessBeforeStartRegister(this.getRegistration());
});
this.register();//※开始注册
this.registrationLifecycles.forEach((registrationLifecycle) -> {
registrationLifecycle.postProcessAfterStartRegister(this.getRegistration());
});
if (this.shouldRegisterManagement()) {
this.registrationManagementLifecycles.forEach((registrationManagementLifecycle) -> {
registrationManagementLifecycle.postProcessBeforeStartRegisterManagement(this.getManagementRegistration());
});
this.registerManagement();
this.registrationManagementLifecycles.forEach((registrationManagementLifecycle) -> {
registrationManagementLifecycle.postProcessAfterStartRegisterManagement(this.getManagementRegistration());
});
}
this.context.publishEvent(new InstanceRegisteredEvent(this, this.getConfiguration()));
this.running.compareAndSet(false, true);
}
}
}
protected void register() {
//中间子类也做了逻辑处理,通过后才到这里
this.serviceRegistry.register(this.getRegistration());//※在注册表中注册
}
- spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java
java
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
NamingService namingService = namingService();//获取命名服务
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
Instance instance = getNacosInstanceFromRegistration(registration);//获取实例
try {
namingService.registerInstance(serviceId, group, instance);//※注册实例
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
instance.getIp(), instance.getPort());
}
catch (Exception e) {
if (nacosDiscoveryProperties.isFailFast()) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
rethrowRuntimeException(e);
}
else {
log.warn("Failfast is false. {} register failed...{},", serviceId,
registration.toString(), e);
}
}
}
再往后就是nacos内部的机制了。想看的可以看nacos服务管理学习《实例注册与注销》
- nacos-config模块
-
创建nacos的ConfigService
通过spring自动装配文件触发NacosConfigAutoConfiguration自动装配类
spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
java
com.alibaba.cloud.nacos.NacosConfigAutoConfiguration//nacos配置中心的自动配置
com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration
创建NacosConfigManager的Bean并为ConfigService属性赋值
java
@Bean
public NacosConfigManager nacosConfigManager(
NacosConfigProperties nacosConfigProperties) {
return new NacosConfigManager(nacosConfigProperties);
}
java
public NacosConfigManager(NacosConfigProperties nacosConfigProperties) {
this.nacosConfigProperties = nacosConfigProperties;
// Compatible with older code in NacosConfigProperties,It will be deleted in the
// future.
createConfigService(nacosConfigProperties);
}
/**
* Compatible with old design,It will be perfected in the future.
*/
static ConfigService createConfigService(
NacosConfigProperties nacosConfigProperties) {
if (Objects.isNull(service)) {
synchronized (NacosConfigManager.class) {
try {
if (Objects.isNull(service)) {
service = NacosFactory.createConfigService(
nacosConfigProperties.assembleConfigServiceProperties());//※通过nacos工厂获取配置服务类
}
}
catch (NacosException e) {
log.error(e.getMessage());
throw new NacosConnectionFailureException(
nacosConfigProperties.getServerAddr(), e.getMessage(), e);
}
}
}
return service;
}
再往后就是nacos的内部机制了,想看的可以看nacos-config模块学习《配置中心》
- 使用ConfigService获取配置
通过spring核心配置文件META-INF/spring.factories触发NacosConfigDataLoader获取配置
java
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer,\
com.alibaba.cloud.nacos.configdata.NacosConfigDataMissingEnvironmentPostProcessor.ImportExceptionFailureAnalyzer
org.springframework.boot.env.PropertySourceLoader=\
com.alibaba.cloud.nacos.parser.NacosJsonPropertySourceLoader,\
com.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader
org.springframework.boot.SpringApplicationRunListener=\
com.alibaba.cloud.nacos.logging.NacosLoggingAppRunListener
org.springframework.boot.env.EnvironmentPostProcessor=\
com.alibaba.cloud.nacos.configdata.NacosConfigDataMissingEnvironmentPostProcessor
# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=\
com.alibaba.cloud.nacos.configdata.NacosConfigDataLocationResolver
# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=\
com.alibaba.cloud.nacos.configdata.NacosConfigDataLoader//nacos配置数据的加载器
spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLoader.java
java
@Override
public ConfigData load(ConfigDataLoaderContext context,
NacosConfigDataResource resource) {
return doLoad(context, resource);
}
public ConfigData doLoad(ConfigDataLoaderContext context,
NacosConfigDataResource resource) {
try {
ConfigService configService = getBean(context, NacosConfigManager.class)
.getConfigService();//获取配置服务类
NacosConfigProperties properties = getBean(context,
NacosConfigProperties.class);
NacosItemConfig config = resource.getConfig();
// pull config from nacos
List<PropertySource<?>> propertySources = pullConfig(configService,
config.getGroup(), config.getDataId(), config.getSuffix(),
properties.getTimeout());//※获取配置
NacosPropertySource propertySource = new NacosPropertySource(propertySources,
config.getGroup(), config.getDataId(), new Date(),
config.isRefreshEnabled());
NacosPropertySourceRepository.collectNacosPropertySource(propertySource);
return new ConfigData(propertySources, getOptions(context, resource));
}
catch (Exception e) {
log.error("Error getting properties from nacos: " + resource, e);
if (!resource.isOptional()) {
throw new ConfigDataResourceNotFoundException(resource, e);
}
}
return null;
}
private List<PropertySource<?>> pullConfig(ConfigService configService, String group,
String dataId, String suffix, long timeout)
throws NacosException, IOException {
String config = configService.getConfig(dataId, group, timeout);//※通过nacos获取配置信息
logLoadInfo(group, dataId, config);
// fixed issue: https://github.com/alibaba/spring-cloud-alibaba/issues/2906 .
String configName = group + "@" + dataId;
return NacosDataParserHandler.getInstance().parseNacosData(configName, config, suffix);//配置处理
}
再往后就是nacos的内部机制了,想看的可以看nacos-config模块学习《配置中心》