Skip to content

Commit 7a3ffe1

Browse files
authored
Merge pull request #1780 from lilai23/2.2.x
Update 2.2.x
2 parents 2cdf00e + 3c1d5ec commit 7a3ffe1

File tree

7 files changed

+151
-36
lines changed

7 files changed

+151
-36
lines changed

sermant-agentcore/sermant-agentcore-config/config/config.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ agent.config.useContextLoader=true
1313
agent.config.ignoredPrefixes=io.sermant,io.opentelemetry
1414
# List of interfaces that need to be ignored when bytecode enhancement is used to search for a class. If all implementation classes of an interface do not want to be bytecode enhanced, you can configure this configuration item
1515
agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory
16+
# List of the ClassLoaders, used to ignore the classes loaded by specific ClassLoaders. This can resolve some issues caused by multiple JavaAgents
17+
agent.config.ignoredClassLoaders=
1618
# Specifies which classes in the plugins are allowed to be bytecode enhanced (classes in the plugins are not allowed to be bytecode enhanced by default)
1719
agent.config.serviceInjectList=io.sermant.discovery.service.lb.filter.NopInstanceFilter,io.sermant.discovery.service.lb.DiscoveryManager,io.sermant.discovery.service.util.ApplyUtil,io.sermant.discovery.service.lb.cache.InstanceCacheManager
1820
# Generate unmatched class name to file, used to reduce startup time for the second time and after

sermant-agentcore/sermant-agentcore-config/config/test/config.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ agent.config.useContextLoader=true
1313
agent.config.ignoredPrefixes=io.sermant,io.opentelemetry
1414
# List of interfaces that need to be ignored when bytecode enhancement is used to search for a class. If all implementation classes of an interface do not want to be bytecode enhanced, you can configure this configuration item
1515
agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory
16+
# List of the ClassLoaders, used to ignore the classes loaded by specific ClassLoaders. This can resolve some issues caused by multiple JavaAgents
17+
agent.config.ignoredClassLoaders=
1618
# Specifies which classes in the plugins are allowed to be bytecode enhanced (classes in the plugins are not allowed to be bytecode enhanced by default)
1719
agent.config.serviceInjectList=io.sermant.discovery.service.lb.filter.NopInstanceFilter,io.sermant.discovery.service.lb.DiscoveryManager,io.sermant.discovery.service.util.ApplyUtil,io.sermant.discovery.service.lb.cache.InstanceCacheManager
1820
# Generate unmatched class name to file, used to reduce startup time for the second time and after

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/agent/BufferedAgentBuilder.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2021-2024 Huawei Technologies Co., Ltd. All rights reserved.
2+
* Copyright (C) 2022-2025 Huawei Technologies Co., Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -301,8 +301,8 @@ public BufferedAgentBuilder addAction(BuilderAction action) {
301301
}
302302

303303
/**
304-
* Build {@link AgentBuilder},execute all {@link BuilderAction} and execute {@link
305-
* AgentBuilder#installOn(Instrumentation)}
304+
* Build {@link AgentBuilder},execute all {@link BuilderAction} and execute
305+
* {@link AgentBuilder#installOn(Instrumentation)}
306306
*
307307
* @param instrumentation Instrumentation
308308
* @return Install result, ResettableClassFileTransformer. If the class metadata is not changed, call the reset
@@ -329,6 +329,8 @@ private static class IgnoredMatcher implements AgentBuilder.RawMatcher {
329329

330330
private final Set<String> ignoredInterfaces;
331331

332+
private final Set<String> ignoredClassLoaders;
333+
332334
/**
333335
* unMatched Class Cache
334336
*/
@@ -338,6 +340,7 @@ private static class IgnoredMatcher implements AgentBuilder.RawMatcher {
338340
ignoredPrefixes = config.getIgnoredPrefixes();
339341
serviceInjectList = config.getServiceInjectList();
340342
ignoredInterfaces = config.getIgnoredInterfaces();
343+
ignoredClassLoaders = config.getIgnoredClassLoaders();
341344
}
342345

343346
@Override
@@ -355,7 +358,7 @@ public boolean matches(TypeDescription typeDesc, ClassLoader classLoader, JavaMo
355358
return false;
356359
}
357360

358-
return isArrayOrPrimitive(typeDesc) || checkClassLoader(typeDesc, classLoader)
361+
return isArrayOrPrimitive(typeDesc) || checkClassLoader(classLoader)
359362
|| isIgnoredPrefixes(typeDesc) || isIgnoredInterfaces(typeDesc);
360363
}
361364

@@ -370,7 +373,7 @@ private boolean checkInjectList(TypeDescription typeDesc, ClassLoader classLoade
370373
return true;
371374
}
372375

373-
private boolean checkClassLoader(TypeDescription typeDesc, ClassLoader classLoader) {
376+
private boolean checkClassLoader(ClassLoader classLoader) {
374377
if (classLoader instanceof SermantClassLoader) {
375378
return true;
376379
}
@@ -380,7 +383,10 @@ private boolean checkClassLoader(TypeDescription typeDesc, ClassLoader classLoad
380383
if (classLoader instanceof PluginClassLoader) {
381384
return true;
382385
}
383-
return false;
386+
387+
// "null" means bootstrap classloader
388+
String classLoaderName = classLoader == null ? "null" : classLoader.getClass().getCanonicalName();
389+
return ignoredClassLoaders.contains(classLoaderName);
384390
}
385391

386392
private boolean isIgnoredPrefixes(TypeDescription typeDesc) {

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/agent/config/AgentConfig.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2021-2024 Huawei Technologies Co., Ltd. All rights reserved.
2+
* Copyright (C) 2022-2025 Huawei Technologies Co., Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,6 +50,12 @@ public class AgentConfig implements BaseConfig {
5050
*/
5151
private Set<String> ignoredInterfaces = Collections.singleton("org.springframework.cglib.proxy.Factory");
5252

53+
/**
54+
* Ignored ClassLoaders, used to ignore the classes loaded by specific ClassLoaders. This can resolve some issues
55+
* caused by multiple JavaAgents
56+
*/
57+
private Set<String> ignoredClassLoaders = Collections.singleton("");
58+
5359
/**
5460
* Whether to output a search log during the enhancement process
5561
*/
@@ -205,4 +211,12 @@ public String getExternalAgentFile() {
205211
public void setExternalAgentFile(String externalAgentFile) {
206212
this.externalAgentFile = externalAgentFile;
207213
}
214+
215+
public Set<String> getIgnoredClassLoaders() {
216+
return ignoredClassLoaders;
217+
}
218+
219+
public void setIgnoredClassLoaders(Set<String> ignoredClassLoaders) {
220+
this.ignoredClassLoaders = ignoredClassLoaders;
221+
}
208222
}

sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/dynamicconfig/nacos/NacosBufferedClient.java

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131

3232
import java.io.Closeable;
3333
import java.io.IOException;
34-
import java.util.HashMap;
34+
import java.util.Collections;
3535
import java.util.List;
3636
import java.util.Map;
3737
import java.util.Optional;
3838
import java.util.Properties;
39+
import java.util.function.Function;
3940
import java.util.logging.Level;
4041
import java.util.logging.Logger;
4142

@@ -46,7 +47,6 @@
4647
* @since 2023-08-17
4748
*/
4849
public class NacosBufferedClient implements Closeable {
49-
5050
/**
5151
* logger
5252
*/
@@ -59,7 +59,9 @@ public class NacosBufferedClient implements Closeable {
5959

6060
private NacosClient nacosClient;
6161

62-
private final String namepase;
62+
private Function<String, Map<String, List<String>>> groupKeysFunction;
63+
64+
private final String namespace;
6365

6466
/**
6567
* Create a NacosBufferedClient and initialize the Nacos client
@@ -71,9 +73,10 @@ public class NacosBufferedClient implements Closeable {
7173
* Sermant needs to be interrupted
7274
*/
7375
public NacosBufferedClient(String connectString, int sessionTimeout, String namespace) {
74-
Properties properties = createProperties(connectString, sessionTimeout, namespace);
75-
this.namepase = namespace;
76+
this.namespace = namespace;
77+
Properties properties = createProperties(connectString, sessionTimeout);
7678
createNacosClient(connectString, properties);
79+
getGroupKeysFunction();
7780
}
7881

7982
/**
@@ -89,9 +92,10 @@ public NacosBufferedClient(String connectString, int sessionTimeout, String name
8992
*/
9093
public NacosBufferedClient(String connectString, int sessionTimeout, String namespace, String userName,
9194
String password) {
92-
Properties properties = createProperties(connectString, sessionTimeout, namespace, userName, password);
93-
this.namepase = namespace;
95+
this.namespace = namespace;
96+
Properties properties = createProperties(connectString, sessionTimeout, userName, password);
9497
createNacosClient(connectString, properties);
98+
getGroupKeysFunction();
9599
}
96100

97101
/**
@@ -100,12 +104,7 @@ public NacosBufferedClient(String connectString, int sessionTimeout, String name
100104
* @return A Map of the groups and all its keys
101105
*/
102106
public Map<String, List<String>> getGroupKeys() {
103-
try {
104-
return this.nacosClient.getGroupKeys(null, null, this.namepase, true);
105-
} catch (IOException e) {
106-
LOGGER.log(Level.SEVERE, "Nacos http request exception.");
107-
return new HashMap<>();
108-
}
107+
return groupKeysFunction.apply(this.namespace);
109108
}
110109

111110
/**
@@ -182,10 +181,9 @@ public void removeListener(String key, String group, Listener listener) {
182181
*
183182
* @param connectString connect string, must be in the following format: {@code host:port[(,host:port)...]}
184183
* @param sessionTimeout session timeout
185-
* @param namespace namespace
186184
* @return Properties
187185
*/
188-
private Properties createProperties(String connectString, int sessionTimeout, String namespace) {
186+
private Properties createProperties(String connectString, int sessionTimeout) {
189187
Properties properties = new Properties();
190188
properties.setProperty(NacosAuthLoginConstant.SERVER, connectString);
191189
properties.setProperty(PropertyKeyConst.SERVER_ADDR, connectString);
@@ -199,14 +197,12 @@ private Properties createProperties(String connectString, int sessionTimeout, St
199197
*
200198
* @param connectString connect string, must be in the following format: {@code host:port[(,host:port)...]}
201199
* @param sessionTimeout session timeout
202-
* @param namespace namespace
203200
* @param userName username
204201
* @param password encrypted password
205202
* @return Properties
206203
*/
207-
private Properties createProperties(String connectString, int sessionTimeout, String namespace, String userName,
208-
String password) {
209-
Properties properties = this.createProperties(connectString, sessionTimeout, namespace);
204+
private Properties createProperties(String connectString, int sessionTimeout, String userName, String password) {
205+
Properties properties = this.createProperties(connectString, sessionTimeout);
210206
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password) || StringUtils.isEmpty(
211207
CONFIG.getPrivateKey())) {
212208
LOGGER.log(Level.SEVERE, "Nacos username, password or privateKey is Empty");
@@ -242,6 +238,32 @@ private void createNacosClient(String connectString, Properties properties) {
242238
}
243239
}
244240

241+
private void getGroupKeysFunction() {
242+
try {
243+
if (nacosClient.hasHistoryConfigApi()) {
244+
groupKeysFunction = ns -> {
245+
try {
246+
return nacosClient.getGroupKeysWithoutContent(ns);
247+
} catch (IOException e) {
248+
LOGGER.log(Level.SEVERE, "Nacos http request exception.");
249+
return Collections.emptyMap();
250+
}
251+
};
252+
return;
253+
}
254+
} catch (IOException ex) {
255+
LOGGER.log(Level.SEVERE, "get group keys function has error.", ex);
256+
}
257+
groupKeysFunction = ns -> {
258+
try {
259+
return nacosClient.getGroupKeys(null, null, ns, true);
260+
} catch (IOException e) {
261+
LOGGER.log(Level.SEVERE, "Nacos http request exception.");
262+
return Collections.emptyMap();
263+
}
264+
};
265+
}
266+
245267
@Override
246268
public void close() {
247269
try {

sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/dynamicconfig/nacos/NacosClient.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;
2828
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
2929

30+
import io.sermant.core.utils.StringUtils;
3031
import io.sermant.implement.service.dynamicconfig.ConfigClient;
3132
import io.sermant.implement.service.dynamicconfig.common.DynamicConstants;
3233

@@ -42,6 +43,7 @@
4243

4344
import java.io.IOException;
4445
import java.util.ArrayList;
46+
import java.util.Collections;
4547
import java.util.HashMap;
4648
import java.util.List;
4749
import java.util.Map;
@@ -81,6 +83,8 @@ public class NacosClient implements ConfigClient {
8183

8284
private static final String URL = "/nacos/v1/cs/configs?appName=&config_tags=&pageNo=1&pageSize=";
8385

86+
private static final String URL_WITHOUT_CONTENT = "/nacos/v1/cs/history/configs?tenant=";
87+
8488
private final Properties properties;
8589

8690
private final ConfigService configService;
@@ -226,6 +230,35 @@ public String getServerStatus() {
226230
return configService.getServerStatus();
227231
}
228232

233+
/**
234+
* Get all keys for all Nacos groups without content
235+
*
236+
* @param namespace configuration namespace
237+
* @return A Map of the groups and all its keys
238+
* @throws IOException IO exception during service invocation process
239+
*/
240+
public Map<String, List<String>> getGroupKeysWithoutContent(String namespace) throws IOException {
241+
final String httpResult = doRequest(buildUrlWithoutContent(namespace), false);
242+
if ("".equals(httpResult)) {
243+
return Collections.emptyMap();
244+
}
245+
JSONArray data = JSONArray.parseArray(httpResult);
246+
return getGroupKeys(data);
247+
}
248+
249+
/**
250+
* whether the /nacos/v1/cs/history/configs interface exists.
251+
* This API will return the dataId and group of all configurations in the current namespace, but not the content.
252+
* since nacos 2.0.4
253+
*
254+
* @return exists
255+
* @throws IOException IO exception during service invocation process
256+
*/
257+
public boolean hasHistoryConfigApi() throws IOException {
258+
final String httpResult = doRequest(buildUrlWithoutContent(StringUtils.EMPTY), true);
259+
return !String.valueOf(HttpStatus.SC_NOT_FOUND).equals(httpResult);
260+
}
261+
229262
/**
230263
* Get all keys for all Nacos groups
231264
*
@@ -238,16 +271,19 @@ public String getServerStatus() {
238271
*/
239272
public Map<String, List<String>> getGroupKeys(String key, String group, String namespace, boolean exactMatchFlag)
240273
throws IOException {
241-
final String httpResult = doRequest(buildUrl(key, group, namespace, exactMatchFlag));
274+
final String httpResult = doRequest(buildUrl(key, group, namespace, exactMatchFlag), false);
242275
if ("".equals(httpResult)) {
243-
return new HashMap<>();
276+
return Collections.emptyMap();
244277
}
245-
Map<String, List<String>> groupKeys = new HashMap<>();
246278
JSONObject jsonObject = JSONObject.parseObject(httpResult);
247279
JSONArray pageItems = jsonObject.getJSONArray(KEY_PAGE_ITEMS);
280+
return getGroupKeys(pageItems);
281+
}
248282

249-
for (int i = 0; i < pageItems.size(); i++) {
250-
JSONObject itemObject = pageItems.getJSONObject(i);
283+
private Map<String, List<String>> getGroupKeys(JSONArray dataArr) {
284+
Map<String, List<String>> groupKeys = new HashMap<>();
285+
for (int i = 0; i < dataArr.size(); i++) {
286+
JSONObject itemObject = dataArr.getJSONObject(i);
251287
String dataId = itemObject.getString(KEY_DATA_ID);
252288
String dataGroup = itemObject.getString(KEY_GROUP);
253289
List<String> dataIdList = groupKeys.getOrDefault(dataGroup, new ArrayList<>());
@@ -257,6 +293,26 @@ public Map<String, List<String>> getGroupKeys(String key, String group, String n
257293
return groupKeys;
258294
}
259295

296+
/**
297+
* Build urls for Nacos http request to query all groups and keys without content
298+
* This API will return the dataId and group of all configurations in the current namespace, but not the content.
299+
* since nacos 2.0.4
300+
*
301+
* @param namespace configuration namespace
302+
* @return url
303+
*/
304+
private String buildUrlWithoutContent(String namespace) {
305+
final StringBuilder requestUrl = new StringBuilder().append(HTTP_PROTOCOL);
306+
requestUrl.append(properties.getProperty(PropertyKeyConst.SERVER_ADDR)).append(URL_WITHOUT_CONTENT)
307+
.append(namespace);
308+
if (properties.get(PropertyKeyConst.USERNAME) != null && properties.get(PropertyKeyConst.PASSWORD) != null) {
309+
String accessToken = getToken();
310+
requestUrl.append("&accessToken=").append(accessToken).append("&username=")
311+
.append(properties.get(PropertyKeyConst.USERNAME));
312+
}
313+
return requestUrl.toString();
314+
}
315+
260316
/**
261317
* Build urls for Nacos http request to query all groups and keys
262318
*
@@ -313,7 +369,7 @@ private String getToken() {
313369
* @return response body
314370
* @throws IOException IO exception during service invocation process
315371
*/
316-
private String doRequest(String url) throws IOException {
372+
private String doRequest(String url, boolean returnStatusWhenHasError) throws IOException {
317373
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
318374
int timeOut = Integer.parseInt(properties.getProperty(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT));
319375
RequestConfig requestConfig = RequestConfig.custom()
@@ -324,12 +380,13 @@ private String doRequest(String url) throws IOException {
324380
HttpGet httpGet = new HttpGet(url);
325381
httpGet.setConfig(requestConfig);
326382
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
327-
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
383+
int statusCode = response.getStatusLine().getStatusCode();
384+
if (statusCode == HttpStatus.SC_OK) {
328385
return EntityUtils.toString(response.getEntity());
329386
}
330387
LOGGER.error("Http request for getting all nacos keys error, the message is: {}",
331388
EntityUtils.toString(response.getEntity()));
332-
return "";
389+
return returnStatusWhenHasError ? String.valueOf(statusCode) : "";
333390
}
334391
}
335392
}

0 commit comments

Comments
 (0)