Skip to content

Commit 5fab473

Browse files
authored
Merge pull request #1534 from lilai23/1.4.x
[1.4.x] fix issue of plugin config reload dynamically failure
2 parents ba82cb6 + 3a92774 commit 5fab473

File tree

6 files changed

+90
-16
lines changed

6 files changed

+90
-16
lines changed

sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/ConfigManager.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private static synchronized void doLoadConfig(File configFile,
143143
final String typeKey = ConfigKeyUtil.getTypeKey(config.getClass());
144144
final BaseConfig retainedConfig = CONFIG_MAP.get(typeKey);
145145
if (retainedConfig == null) {
146-
CONFIG_MAP.put(typeKey, doLoad(configFile, config));
146+
CONFIG_MAP.put(typeKey, doLoad(configFile, config, false));
147147
} else if (retainedConfig.getClass() == config.getClass()) {
148148
LOGGER.fine(String.format(Locale.ROOT, "Skip load config [%s] repeatedly. ",
149149
config.getClass().getName()));
@@ -159,14 +159,15 @@ private static synchronized void doLoadConfig(File configFile,
159159
*
160160
* @param configFile 配置文件
161161
* @param baseConfig 配置类
162+
* @param isDynamic is the config loaded dynamically
162163
* @return 加载后的配置类
163164
*/
164-
public static BaseConfig doLoad(File configFile, BaseConfig baseConfig) {
165+
public static BaseConfig doLoad(File configFile, BaseConfig baseConfig, boolean isDynamic) {
165166
// 通过FrameworkClassLoader 获取配置加载策略
166167
final LoadConfigStrategy<?> loadConfigStrategy = getLoadConfigStrategy(configFile,
167168
ClassLoaderManager.getFrameworkClassLoader());
168169
final Object holder = loadConfigStrategy.getConfigHolder(configFile, argsMap);
169-
return ((LoadConfigStrategy) loadConfigStrategy).loadConfig(holder, baseConfig);
170+
return ((LoadConfigStrategy) loadConfigStrategy).loadConfig(holder, baseConfig, isDynamic);
170171
}
171172

172173
/**

sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/strategy/LoadConfigStrategy.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* <p>加载配置信息主要分两步:
3131
* <pre>
3232
* 1.加载配置文件为配置信息{@link #getConfigHolder(File, Map)}
33-
* 2.将配置信息加载到配置对象中{@link #loadConfig(Object, BaseConfig)}
33+
* 2.将配置信息加载到配置对象中{@link #loadConfig(Object, BaseConfig, boolean)}
3434
* </pre>
3535
*
3636
* @param <T> 配置主体
@@ -70,9 +70,10 @@ public interface LoadConfigStrategy<T> {
7070
* @param holder 配置信息主要承载对象
7171
* @param config 配置对象
7272
* @param <R> 配置对象类型
73+
* @param isDynamic is the config loaded dynamically
7374
* @return 配置对象
7475
*/
75-
<R extends BaseConfig> R loadConfig(T holder, R config);
76+
<R extends BaseConfig> R loadConfig(T holder, R config, boolean isDynamic);
7677

7778
/**
7879
* 默认的{@link LoadConfigStrategy},不做任何逻辑操作
@@ -96,7 +97,7 @@ public Object getConfigHolder(File config, Map<String, Object> argsMap) {
9697
}
9798

9899
@Override
99-
public <R extends BaseConfig> R loadConfig(Object holder, R config) {
100+
public <R extends BaseConfig> R loadConfig(Object holder, R config, boolean isDynamic) {
100101
LOGGER.log(Level.WARNING, String.format(Locale.ROOT, "[%s] will do nothing when loading config. ",
101102
DefaultLoadConfigStrategy.class.getName()));
102103
return config;

sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/config/PluginConfigManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ public static void loadPluginConfigs(Plugin plugin) {
6868
final BaseConfig retainedConfig = PLUGIN_CONFIG_MAP.get(pluginConfigKey);
6969
if (pluginConfigFile.exists() && pluginConfigFile.isFile()) {
7070
if (retainedConfig == null) {
71-
PLUGIN_CONFIG_MAP.put(pluginConfigKey, ConfigManager.doLoad(pluginConfigFile, config));
71+
PLUGIN_CONFIG_MAP.put(pluginConfigKey,
72+
ConfigManager.doLoad(pluginConfigFile, config, plugin.isDynamic()));
7273
plugin.getConfigs().add(pluginConfigKey);
7374
} else if (retainedConfig.getClass() == pluginConfigCls) {
7475
LOGGER.fine(String.format(Locale.ROOT, "Skip load config [%s] repeatedly. ",

sermant-agentcore/sermant-agentcore-implement/src/main/java/com/huaweicloud/sermant/implement/config/LoadPropertiesStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public Properties getConfigHolder(File config, Map<String, Object> bootArgsMap)
104104
* @return 配置对象泛型
105105
*/
106106
@Override
107-
public <R extends BaseConfig> R loadConfig(Properties holder, R config) {
107+
public <R extends BaseConfig> R loadConfig(Properties holder, R config, boolean isDynamic) {
108108
return loadConfig(holder, config.getClass(), config);
109109
}
110110

sermant-agentcore/sermant-agentcore-implement/src/main/java/com/huaweicloud/sermant/implement/config/LoadYamlStrategy.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,16 @@ public class LoadYamlStrategy implements LoadConfigStrategy<Map> {
8585
*/
8686
private Map<String, Object> argsMap;
8787

88+
private final SermantYamlConstructor constructor;
89+
8890
/**
8991
* 构造函数
9092
*/
9193
public LoadYamlStrategy() {
9294
Representer representer = new Representer(new DumperOptions());
9395
representer.getPropertyUtils().setSkipMissingProperties(true);
94-
this.yaml = new Yaml(representer);
96+
this.constructor = new SermantYamlConstructor();
97+
this.yaml = new Yaml(constructor, representer);
9598
}
9699

97100
@Override
@@ -107,7 +110,7 @@ public Map getConfigHolder(File config, Map<String, Object> bootstreapArgsMap) {
107110
}
108111

109112
@Override
110-
public <R extends BaseConfig> R loadConfig(Map holder, R config) {
113+
public <R extends BaseConfig> R loadConfig(Map holder, R config, boolean isDynamic) {
111114
final Class<R> cls = (Class<R>) config.getClass();
112115
final String typeKey = ConfigKeyUtil.getTypeKey(cls);
113116
final Object typeVal = holder.get(typeKey);
@@ -124,13 +127,11 @@ public <R extends BaseConfig> R loadConfig(Map holder, R config) {
124127
configMap.put(field.getName(), null);
125128
}
126129
}
127-
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
128-
try {
129-
Thread.currentThread().setContextClassLoader(cls.getClassLoader());
130-
return (R) yaml.loadAs(yaml.dump(fixEntry(configMap, cls)), cls);
131-
} finally {
132-
Thread.currentThread().setContextClassLoader(classLoader);
130+
constructor.setLoader(cls.getClassLoader());
131+
if (isDynamic) {
132+
constructor.clearCache();
133133
}
134+
return (R) yaml.loadAs(yaml.dump(fixEntry(configMap, cls)), cls);
134135
}
135136

136137
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.huaweicloud.sermant.implement.config;
18+
19+
import org.yaml.snakeyaml.LoaderOptions;
20+
import org.yaml.snakeyaml.constructor.Constructor;
21+
22+
/**
23+
* Yaml constructor for sermant config load
24+
*
25+
* @author lilai
26+
* @since 2024-05-22
27+
*/
28+
public class SermantYamlConstructor extends Constructor {
29+
private ClassLoader loader;
30+
31+
/**
32+
* constructor
33+
*/
34+
public SermantYamlConstructor() {
35+
super(Object.class, new LoaderOptions());
36+
loader = Thread.currentThread().getContextClassLoader();
37+
}
38+
39+
/**
40+
* Load class with specific classLoader
41+
*
42+
* @param name class name
43+
* @return created class
44+
* @throws ClassNotFoundException class not found
45+
*/
46+
@Override
47+
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
48+
return Class.forName(name, true, loader);
49+
}
50+
51+
/**
52+
* set classLoader
53+
*
54+
* @param classLoader the classLoader for config object
55+
* @throws NullPointerException no classloader is provided
56+
*/
57+
public void setLoader(ClassLoader classLoader) {
58+
if (classLoader == null) {
59+
throw new NullPointerException("classLoader must be provided.");
60+
}
61+
this.loader = classLoader;
62+
}
63+
64+
/**
65+
* clear snakeyaml class cache
66+
*/
67+
public void clearCache() {
68+
typeTags.clear();
69+
}
70+
}

0 commit comments

Comments
 (0)