Skip to content

Commit

Permalink
调整profile的加载逻辑,允许在application.yaml中配置nop.profile
Browse files Browse the repository at this point in the history
  • Loading branch information
entropy-cloud committed Aug 11, 2024
1 parent 3468608 commit 4b171d5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 40 deletions.
28 changes: 16 additions & 12 deletions docs/dev-guide/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,31 @@

先加载的配置优先级更高,会被优先使用。

1. classpath:bootstrap.yaml 应用的启动配置,其中的所有变量都是固定值,不会被动态覆盖
2. 配置中心的`{nop.application.name}-{nop.profile}.yaml`
3. 配置中心的`{nop.application.name}.yaml`
4. nop.config.key-config-source.paths参数指定k8s SecretMap映射文件,定时扫描检测是否已更新
5. nop.config.props-config-source.paths参数指定k8s ConfigMap映射文件,定时扫描检测是否已更新
6. 如果配置了nop.config.jdbc.jdbc-url等参数,则会从数据库配置表中加载配置,定时扫描检测是否已更新
7. java的System.getProperties()
8. java的System.getenv(): StringHelper.envToConfigVar(envName)负责把环境变量名转换为配置项名称
9. nop.config.additional-location参数指定的配置文件
10. nop.config.location参数指定的配置文件,它的缺省值为 classpath:application.yaml
11. 识别quarkus配置规范规定的`'%dev.'`等profile配置前缀,根据当前的profile配置调整专属于profile的配置项的访问顺序。例如
1. java的System.getenv(): StringHelper.envToConfigVar(envName)负责把环境变量名转换为配置项名称
2. java的System.getProperties()
3. classpath:bootstrap.yaml 应用的启动配置, 可以通过`nop.config.bootstrap-location`来指定位置
4. 配置中心的`{nop.application.name}-{nop.profile}.yaml`
5. 配置中心的`{nop.application.name}.yaml`
6. 配置中心的`{nop.product.name}.yaml`
7. `nop.config.key-config-source.paths`参数指定k8s SecretMap映射文件,定时扫描检测是否已更新
8. `nop.config.props-config-source.paths`参数指定k8s ConfigMap映射文件,定时扫描检测是否已更新
9. 如果配置了`nop.config.jdbc.jdbc-url`等参数,则会从数据库配置表中加载配置,定时扫描检测是否已更新
10. `nop.config.additional-location`参数指定的扩展配置文件
11. `nop.config.location`参数指定的配置文件,它的缺省值为`classpath:application.yaml`
12. `nop.profile``nop.profile.parent`指定的profile配置,它们的优先级高于application.yaml
13. 识别quarkus配置规范规定的`'%dev.'`等profile配置前缀,根据当前的profile配置调整专属于profile的配置项的访问顺序。例如
dev模式下,`%dev.a.b.c`的值将会覆盖配置项`a.b.c`的值

>
具体配置加载逻辑全部集中在[ConfigStarter.java](https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-config/src/main/java/io/nop/config/starter/ConfigStarter.java)
类中

* **在bootstrap.yaml中可以配置nop.profile=dev来启用application-dev.yaml配置,类似于spring中的profile概念。**
* **在bootstrap.yaml或者application.yaml中可以配置nop.profile=dev来启用application-dev.yaml配置,类似于spring中的profile概念。**
也可以通过java property或者env机制类配置profile,例如-Dnop.profile=dev或者配置环境变量`NOP_PROFILE=dev`
* 优先加载yaml后缀的配置文件,如果找不到,会尝试加载后缀名为yml的同名文件。也就是说,如果同时存在`application.yaml``application.yml`,则会优先使用前者
* 可以通过`nop.profile.parent`来指定多个active的profile,它们的优先级为从左到右。例如`nop.profile=dev`, `nop.profile.parent=mysql,nacos`,则
对应于如下加载顺序 `application-dev.yaml -> application-mysql.yaml -> application-nacos.yaml -> application.yaml`

## 自动更新

Expand Down
6 changes: 4 additions & 2 deletions nop-api-core/src/main/java/io/nop/api/core/ApiConfigs.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import io.nop.api.core.config.IConfigReference;
import io.nop.api.core.util.SourceLocation;

import java.util.Set;

import static io.nop.api.core.config.AppConfig.varRef;

@Locale("zh-CN")
Expand All @@ -23,8 +25,8 @@ public interface ApiConfigs {
varRef(s_loc, "nop.profile", String.class, null);

@Description("当前profile的父配置。配置查找顺序为 profile --> profile.parent --> standard")
IConfigReference<String> CFG_PROFILE_PARENT =
varRef(s_loc, "nop.profile.parent", String.class, null);
IConfigReference<Set> CFG_PROFILE_PARENT =
varRef(s_loc, "nop.profile.parent", Set.class, null);

@Description("在NopException中记录的xpl堆栈的最大深度")
IConfigReference<Integer> CFG_EXCEPTION_MAX_XPL_STACK_SIZE =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
package io.nop.config.source;

import io.nop.commons.util.CollectionHelper;
import io.nop.commons.util.objects.ValueWithLocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -27,7 +28,7 @@ public class ProfileConfigSource implements IConfigSource {
private final IConfigSource source;

public ProfileConfigSource(List<String> profiles, IConfigSource source) {
this.profiles = profiles;
this.profiles = CollectionHelper.reverseList(profiles);
this.source = source;
}

Expand Down
75 changes: 50 additions & 25 deletions nop-config/src/main/java/io/nop/config/starter/ConfigStarter.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/
package io.nop.config.starter;

import io.nop.api.core.ApiConfigs;
import io.nop.api.core.config.AppConfig;
import io.nop.api.core.config.IConfigExecutor;
import io.nop.api.core.config.IConfigProvider;
Expand Down Expand Up @@ -61,7 +60,10 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static io.nop.api.core.ApiConfigs.CFG_PROFILE;
import static io.nop.api.core.ApiConfigs.CFG_PROFILE_PARENT;
import static io.nop.config.ConfigConstants.CFG_KEY_FILE_CONFIG_SOURCE_PATHS;
import static io.nop.config.ConfigConstants.CFG_KEY_FILE_CONFIG_SOURCE_REFRESH_INTERVAL;
import static io.nop.config.ConfigConstants.CFG_PROPS_FILE_CONFIG_SOURCE_PATHS;
Expand Down Expand Up @@ -90,6 +92,8 @@ public static ConfigStarter instance() {

private DefaultVirtualFileSystem vfs;

private List<String> profiles;

private Cancellable cancellable = new Cancellable();

private List<IConfigSource> closeableSources = new ArrayList<>();
Expand All @@ -99,11 +103,11 @@ protected void doStart() {
// 1. 装载boostrap.yaml
IConfigSource propsSource = new SysPropertyConfigSourceLoader().loadConfigSource(null);
IConfigSource envSource = new EnvConfigSourceLoader().loadConfigSource(null);
IConfigSource bootstrapSource = loadBootstrapSource(propsSource, envSource);
IConfigSource bootstrapSource = loadBootstrapSource();

// 优先级从高到低 System.properties --> bootstrap.yaml --> System.env
// 优先级从高到低 System.env --> System.properties --> bootstrap.yaml, 与spring保持一致
CompositeConfigSource baseSource = new CompositeConfigSource(
Arrays.asList(propsSource, bootstrapSource, envSource));
Arrays.asList(envSource, propsSource, bootstrapSource));

initConfigProvider(baseSource);

Expand Down Expand Up @@ -174,11 +178,16 @@ protected void doStart() {
configSource = new CompositeConfigSource(configSources);

// 8. 装载应用配置 application.yaml
List<IConfigSource> appSources = loadAppConfigs(configSource);
IConfigSource appSource = loadAppConfigSource(configSource);

List<IConfigSource> appSources = loadAppConfigs(configSource, appSource);

configSources.addAll(appSources);

List<String> profiles = getProfiles(configSource);
List<String> profiles = getProfiles(configSource, appSource);

LOG.info("nop.profiles.active:{}", profiles);

configSource = new CompositeConfigSource(configSources);
if (!profiles.isEmpty()) {
configSource = new ProfileConfigSource(profiles, configSource);
Expand Down Expand Up @@ -215,7 +224,7 @@ public void deactivate() {
this.changeApplier.deactivate();
}

private IConfigSource loadBootstrapSource(IConfigSource propsSource, IConfigSource envSource) {
private IConfigSource loadBootstrapSource() {
IResource resource = CoreInitialization.getBootstrapResource();
if (!resource.exists()) {
LOG.warn("nop.config.no-bootstrap-config-file:path{}", resource.getPath());
Expand Down Expand Up @@ -251,48 +260,58 @@ protected IResource buildConfigResource(String path) {
return ResourceHelper.buildConfigResource(path);
}

protected List<String> getProfiles(IConfigSource baseSource) {
String profile = baseSource.getConfigValue(ApiConfigs.CFG_PROFILE.getName(), "");
protected List<String> getProfiles(IConfigSource baseSource, IConfigSource appSource) {
if (this.profiles != null)
return this.profiles;

String profile = appSource.getConfigValue(CFG_PROFILE.get(), null);
if (StringHelper.isEmpty(profile))
profile = baseSource.getConfigValue(CFG_PROFILE.getName(), "");

String profileParent = baseSource.getConfigValue(ApiConfigs.CFG_PROFILE_PARENT.getName(), "");
if (StringHelper.isEmpty(profile) && StringHelper.isEmpty(profileParent))
Set<String> profileParent = ConvertHelper.toCsvSet(appSource.getConfigValue(CFG_PROFILE_PARENT.getName()));
if (CollectionHelper.isEmpty(profileParent))
profileParent = ConvertHelper.toCsvSet(baseSource.getConfigValue(CFG_PROFILE_PARENT.getName()));

if (StringHelper.isEmpty(profile) && CollectionHelper.isEmpty(profileParent))
return Collections.emptyList();

List<String> profiles = new ArrayList<>();
if (!StringHelper.isEmpty(profile)) {
profiles.add(profile);
}

if (!StringHelper.isEmpty(profileParent))
profiles.add(profileParent);
if (profileParent != null)
profiles.addAll(profileParent);

this.profiles = profiles;
return profiles;
}

protected List<IConfigSource> loadFromConfigCenter(IConfigSource baseSource) {
if (configService == null)
return Collections.emptyList();

String productName = baseSource.getConfigValue(ConfigConstants.CFG_PRODUCT_NAME, "");

String appName = baseSource.getConfigValue(ConfigConstants.CFG_APPLICATION_NAME, "");
if (StringHelper.isEmpty(appName))
throw new NopException(ERR_CONFIG_MISSING_APPLICATION_NAME);

List<IConfigSource> serviceSources = new ArrayList<>(2);

try {
List<String> profiles = getProfiles(baseSource);
IConfigSource appSource = configService.getConfigSource(baseSource, appName);

List<String> profiles = getProfiles(baseSource, appSource);
for (String profile : profiles) {
String dataId = appName + '-' + profile;
IConfigSource profileSource = configService.getConfigSource(baseSource, dataId);
serviceSources.add(profileSource);
}

if (!StringHelper.isEmpty(appName)) {
String dataId = appName;
IConfigSource serviceSource = configService.getConfigSource(baseSource, dataId);
serviceSources.add(serviceSource);
}
serviceSources.add(appSource);

String productName = appSource.getConfigValue(ConfigConstants.CFG_PRODUCT_NAME, "");
if (StringHelper.isEmpty(productName))
productName = baseSource.getConfigValue(ConfigConstants.CFG_PRODUCT_NAME, "");

if (!StringHelper.isEmpty(productName)) {
String dataId = productName;
Expand Down Expand Up @@ -340,7 +359,7 @@ protected IConfigSource loadJdbcSource(IConfigSource configSource) {
return new JdbcConfigSource(config);
}

protected List<IConfigSource> loadAppConfigs(IConfigSource configSource) {
protected List<IConfigSource> loadAppConfigs(IConfigSource configSource, IConfigSource appSource) {
List<IConfigSource> appSources = new ArrayList<>(4);

String additional = configSource.getConfigValue(ConfigConstants.CFG_CONFIG_ADDITIONAL_LOCATION, "");
Expand All @@ -350,15 +369,22 @@ protected List<IConfigSource> loadAppConfigs(IConfigSource configSource) {
appSources.add(source);
}

List<String> profiles = getProfiles(configSource);
List<String> profiles = getProfiles(configSource, appSource);
for (String profile : profiles) {
IResource resource = getAppProfileFile(profile);
if (resource.exists()) {
IConfigSource source = new ResourceConfigSourceLoader(resource).loadConfigSource(configSource);
appSources.add(source);
} else {
LOG.warn("nop.profile.not-exists:{}", profile);
}
}

appSources.add(appSource);
return appSources;
}

protected IConfigSource loadAppConfigSource(IConfigSource configSource) {
String path = configSource.getConfigValue(ConfigConstants.CFG_CONFIG_LOCATION,
ConfigConstants.CFG_PATH_APPLICATION_YAML);
IResource resource = buildConfigResource(path);
Expand All @@ -369,8 +395,7 @@ protected List<IConfigSource> loadAppConfigs(IConfigSource configSource) {
}
}
IConfigSource source = new ResourceConfigSourceLoader(resource).loadConfigSource(configSource);
appSources.add(source);
return appSources;
return source;
}

protected IResource getAppProfileFile(String profile) {
Expand Down

0 comments on commit 4b171d5

Please sign in to comment.