config是一个微服务配置组件,为微服务提供集中化的配置管理服务。config包含服务端和客户端,客户端在启动服务时从服务端拉取配置信息,服务端响应客户端的请求提供具体的配置。本章分析config组件的实现原理
1、config服务端
服务端响应请求的过程比较简单,主要由spring-cloud-config-server包下EnvironmentController负责
@RestController
@RequestMapping(
method = {RequestMethod.GET},
path = {"${spring.cloud.config.server.prefix:}"}
)
public class EnvironmentController {
/**
* 根据环境类型和文件名拉取信息
**/
@RequestMapping(
path = {"/{name}/{profiles:.*[^-].*}"},
produces = {"application/json"}
)
public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) {
return this.getEnvironment(name, profiles, (String)null, false);
}
public Environment getEnvironment(String name, String profiles, String label, boolean includeOrigin) {
name = this.normalize(name);
label = this.normalize(label);
Environment environment = this.repository.findOne(name, profiles, label, includeOrigin);
if (this.acceptEmpty || environment != null && !environment.getPropertySources().isEmpty()) {
return environment;
} else {
throw new EnvironmentNotFoundException("Profile Not found");
}
}
}
getEnvironment方法会调用EnvironmentRepository接口的实现类来查找环境信息,类似dao层
public interface EnvironmentRepository {
Environment findOne(String application, String profile, String label);
default Environment findOne(String application, String profile, String label, boolean includeOrigin) {
return this.findOne(application, profile, label);
}
}
2、config客户端
springboot在启动时会调用applyInitializers方法,这个方法会遍历ApplicationContextInitializer接口的实现类并调用它们的initialize方法
【SpringBoot】SpringBoot源码解析第二章 SpringBoot的run方法-优快云博客
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
config客户端中的PropertySourceBootstrapConfiguration类实现了ApplicationContextInitializer接口,它的承担的任务是拉取远程的配置信息并与本地信息整合
public void initialize(ConfigurableApplicationContext applicationContext) {
...
while(true) {
Collection source;
do {
do {
...
PropertySourceLocator locator = (PropertySourceLocator)var5.next();
// 拉取远程配置信息
source = locator.locateCollection(environment);
} while(source == null);
} while(source.size() == 0);
...
}
}
ConfigServicePropertySourceLocator是PropertySourceLocator接口的实现类,查看它的locate方法
@Retryable(
interceptor = "configServerRetryInterceptor"
)
public PropertySource<?> locate(Environment environment) {
...
for(int var11 = 0; var11 < var10; ++var11) {
String label = var9[var11];
...
// 发送请求
org.springframework.cloud.config.environment.Environment result
= this.getRemoteEnvironment(restTemplate, properties, label.trim(), state);
...
}
}
private Environment getRemoteEnvironment(RestTemplate restTemplate, ConfigClientProperties properties, String label, String state) {
String path = "/{name}/{profile}";
String name = properties.getName();
String profile = properties.getProfile();
String token = properties.getToken();
...
response = restTemplate.exchange(uri + path, HttpMethod.GET, entity, org.springframework.cloud.config.environment.Environment.class, args);
...
}
}
locate方法发送具体的请求,拉取过来的远程信息会与本地整合
3、总结
config服务端负责响应请求,config客户端在服务启动时会从服务端拉取配置信息