From 675362b1e44ce89a935286ef57b13ae397fbf529 Mon Sep 17 00:00:00 2001 From: "liurong.liu" Date: Mon, 18 Mar 2024 20:32:05 +0800 Subject: [PATCH 1/3] add client labels collect and attach labels to conn --- .../alibaba/nacos/api/common/Constants.java | 42 +++++ .../client/config/impl/ClientWorker.java | 2 +- .../nacos/common/labels/LabelsCollector.java | 66 ++++++++ .../common/labels/LabelsCollectorManager.java | 47 ++++++ .../labels/impl/AbstractLabelsCollector.java | 44 ++++++ .../labels/impl/DefaultLabelsCollector.java | 69 +++++++++ .../impl/DefaultLabelsCollectorManager.java | 141 +++++++++++++++++ .../impl/utils/AbstractConfigGetter.java | 57 +++++++ .../impl/utils/ConfigGetterManager.java | 58 +++++++ .../labels/impl/utils/EnvConfigGetter.java | 53 +++++++ .../labels/impl/utils/JvmConfigGetter.java | 53 +++++++ .../impl/utils/OrderedConfigGetter.java | 52 +++++++ .../impl/utils/PropertiesConfigGetter.java | 60 ++++++++ .../remote/client/RpcClientFactory.java | 41 ++++- .../nacos/common/utils/ConnLabelsUtils.java | 144 ++++++++++++++++++ ...libaba.nacos.common.labels.LabelsCollector | 19 +++ .../labels/impl/ConfigGetterManagerTest.java | 57 +++++++ .../DefaultLabelsCollectorManagerTest.java | 53 +++++++ .../labels/impl/Test1LabelsCollector.java | 44 ++++++ .../labels/impl/Test2LabelsCollector.java | 44 ++++++ .../common/utils/ConnLabelsUtilsTest.java | 68 +++++++++ ...libaba.nacos.common.labels.LabelsCollector | 21 +++ .../alibaba/nacos/core/remote/Connection.java | 4 + .../nacos/core/remote/ConnectionMeta.java | 25 +++ 24 files changed, 1262 insertions(+), 2 deletions(-) create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollector.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollectorManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/AbstractLabelsCollector.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollector.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/AbstractConfigGetter.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/ConfigGetterManager.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/EnvConfigGetter.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/JvmConfigGetter.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/OrderedConfigGetter.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/PropertiesConfigGetter.java create mode 100644 common/src/main/java/com/alibaba/nacos/common/utils/ConnLabelsUtils.java create mode 100644 common/src/main/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector create mode 100644 common/src/test/java/com/alibaba/nacos/common/labels/impl/ConfigGetterManagerTest.java create mode 100644 common/src/test/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManagerTest.java create mode 100644 common/src/test/java/com/alibaba/nacos/common/labels/impl/Test1LabelsCollector.java create mode 100644 common/src/test/java/com/alibaba/nacos/common/labels/impl/Test2LabelsCollector.java create mode 100644 common/src/test/java/com/alibaba/nacos/common/utils/ConnLabelsUtilsTest.java create mode 100644 common/src/test/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index bbc0d39e429..f7cdb292ad7 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -33,6 +33,8 @@ public class Constants { public static final String APPNAME = "AppName"; + public static final String CLIENT_VERSION_KEY = "ClientVersion"; + public static final String UNKNOWN_APP = "UnknownApp"; public static final String DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com"; @@ -223,6 +225,46 @@ public class Constants { public static final int DEFAULT_REDO_THREAD_COUNT = 1; + public static final String APP_CONN_LABELS_PREFIX = "nacos.app.conn.labels"; + + public static final String GRAY = "gray"; + + public static final String DOT = "."; + + public static final String WEIGHT = "weight"; + + public static final String PROPERTIES_KEY = "properties"; + + public static final String JVM_KEY = "jvm"; + + public static final String ENV_KEY = "env"; + + public static final String APP_CONN_LABELS_PROPERTIES_WEIGHT_KEY = APP_CONN_LABELS_PREFIX + DOT + WEIGHT + DOT + PROPERTIES_KEY; + + public static final int APP_CONN_LABELS_PROPERTIES_DEFAULT_WEIGHT = 3; + + public static final String APP_CONN_LABELS_JVM_WEIGHT_KEY = APP_CONN_LABELS_PREFIX + DOT + WEIGHT + DOT + JVM_KEY; + + public static final int APP_CONN_LABELS_JVM_DEFAULT_WEIGHT = 2; + + public static final String APP_CONN_LABELS_ENV_WEIGHT_KEY = APP_CONN_LABELS_PREFIX + DOT + WEIGHT + DOT + ENV_KEY; + + public static final int APP_CONN_LABELS_ENV_DEFAULT_WEIGHT = 1; + + public static final String APP_CONN_PREFIX = "app_"; + + public static final String BETA_IPS = "betaIps"; + + public static final String TAG_V1 = "tag"; + + public static final String TAG_V2 = "tagv2"; + + public static final String TAG_V2_PREFIX = "tagv2_"; + + public static final int CONFIG_GRAY_DEFAULT_ORDER_WEIGHT = 100; + + public static final String CONFIG_GRAY = "nacos.config" + DOT + GRAY; + /** * The constants in config directory. */ diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index 17da028449a..7e57162fcb6 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -1071,7 +1071,7 @@ private RpcClient ensureRpcClient(String taskId) throws NacosException { Map newLabels = new HashMap<>(labels); newLabels.put("taskId", taskId); RpcClient rpcClient = RpcClientFactory.createClient(uuid + "_config-" + taskId, getConnectionType(), - newLabels, RpcClientTlsConfig.properties(this.properties)); + newLabels, this.properties, RpcClientTlsConfig.properties(this.properties)); if (rpcClient.isWaitInitiated()) { initRpcClientHandler(rpcClient); rpcClient.setTenant(getTenant()); diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollector.java b/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollector.java new file mode 100644 index 00000000000..520ffa478b7 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollector.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels; + +import java.util.Map; +import java.util.Properties; + +/** + * LabelsCollector. + * + * @author rong + * @date 2024/2/4 + */ +public interface LabelsCollector { + + /** + * init labels. + * + * @param properties Properties + * @date 2024/2/4 + * @description init labels + */ + void init(Properties properties); + + /** + * getLabels. + * + * @return Map + * @date 2024/2/4 + * @description get all labels + */ + Map getLabels(); + + /** + * getOrder. + * + * @return the order value + * @date 2024/2/4 + * @description get order value of labels in case of multiple labels + */ + int getOrder(); + + /** + * get collector name. + * + * @return name of collector + * @date 2024/2/4 + * @description name of collector + */ + String getName(); + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollectorManager.java b/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollectorManager.java new file mode 100644 index 00000000000..05350c2d9bb --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollectorManager.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels; + +import java.util.Map; +import java.util.Properties; + +/** +* LabelsCollectorManager. + * +* @author rong +* @date 2024/2/4 +*/ +public interface LabelsCollectorManager { + + /** + * get all labels collected. + * + * @date 2024/2/4 + * @description + * @return all labels + */ + Map getAllLabels(); + + /** + * refresh all labels. + * + * @date 2024/3/7 + * @param properties Properties. + * @return all labels. + */ + Map refreshAllLabels(Properties properties); +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/AbstractLabelsCollector.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/AbstractLabelsCollector.java new file mode 100644 index 00000000000..abd79a8de85 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/AbstractLabelsCollector.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.common.labels.LabelsCollector; + +import java.util.HashMap; +import java.util.Map; + +/** + * AbstractLabelsCollector. + * + * @author rong + */ +public abstract class AbstractLabelsCollector implements LabelsCollector { + + protected Map labels = new HashMap<>(2); + + private static final int DEFAULT_INITIAL_ORDER = 100; + + @Override + public Map getLabels() { + return labels; + } + + @Override + public int getOrder() { + return DEFAULT_INITIAL_ORDER; + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollector.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollector.java new file mode 100644 index 00000000000..d1aafa4130c --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollector.java @@ -0,0 +1,69 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.common.labels.LabelsCollector; +import com.alibaba.nacos.common.labels.impl.utils.ConfigGetterManager; +import com.alibaba.nacos.common.utils.ConnLabelsUtils; +import com.alibaba.nacos.common.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Properties; + +/** + * DefaultLabelsCollector. + * + * @author rong + */ +public class DefaultLabelsCollector extends AbstractLabelsCollector implements LabelsCollector { + + protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultLabelsCollector.class); + + private final String customName = "defaultLabelsCollector"; + + /** + * init labels. + * + * @date 2024/2/4 + *@description will init from properties, JVM OPTIONS, ENV by order of properties > JVM OPTIONS > ENV by default. + * which will use the next level value when the current level value isn't setup (you also can set the level by env). + *

eg: if the value of "nacos.app.conn.labels"(properties' key) is "k1=v1,k2=v2"(properties' value), the result will be + * a Map with value{k1=v1,k2=v2}.

+ * @param properties Properties + */ + @Override + public void init(Properties properties) { + ConfigGetterManager configGetterManager = new ConfigGetterManager(properties); + labels.putAll(ConnLabelsUtils.parseRawLabels(configGetterManager.getConfig(Constants.APP_CONN_LABELS_PREFIX))); + + String grayLabelValue = configGetterManager.getConfig(Constants.CONFIG_GRAY); + if (StringUtils.isNotBlank(grayLabelValue)) { + labels.put(Constants.GRAY, grayLabelValue); + } + for (Map.Entry entry : labels.entrySet()) { + LOGGER.info("init labels: {}={}", entry.getKey(), entry.getValue()); + } + } + + @Override + public String getName() { + return customName; + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManager.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManager.java new file mode 100644 index 00000000000..e789c103636 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManager.java @@ -0,0 +1,141 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.common.labels.LabelsCollector; +import com.alibaba.nacos.common.labels.LabelsCollectorManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; + +/** + * DefaultLabelsCollectorManager. + * + * @author rong + */ +public class DefaultLabelsCollectorManager implements LabelsCollectorManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLabelsCollectorManager.class); + + private ArrayList labelsCollectorsList = new ArrayList<>(); + + private Map labels = new HashMap<>(); + + private static final int MAX_TRY_COUNT = 3; + + private volatile boolean isLabelsInit = false; + + public DefaultLabelsCollectorManager(Properties properties) { + init(properties); + } + + private void init(Properties properties) { + if (isLabelsInit) { + return; + } + synchronized (this) { + if (isLabelsInit) { + return; + } + isLabelsInit = true; + LOGGER.info("DefaultLabelsCollectorManager init labels....."); + initLabels(properties); + LOGGER.info("DefaultLabelsCollectorManager init labels finished, labels:{}", labels); + + } + } + + public Map getAllLabels() { + for (int tryTimes = 0; tryTimes < MAX_TRY_COUNT && !isLabelsInit; tryTimes++) { + try { + Thread.sleep(100); + } catch (Exception e) { + //do nothing + } + } + return labels; + } + + @Override + public Map refreshAllLabels(Properties properties) { + for (int tryTimes = 0; tryTimes < MAX_TRY_COUNT && !isLabelsInit; tryTimes++) { + try { + Thread.sleep(100); + } catch (Exception e) { + //do nothing + } + } + if (!isLabelsInit) { + return new HashMap<>(2); + } + LOGGER.info("DefaultLabelsCollectorManager refresh labels....."); + initLabels(properties); + LOGGER.info("DefaultLabelsCollectorManager refresh labels finished,labels :{}", labels); + return labels; + } + + private ArrayList loadLabelsCollectors() { + ServiceLoader labelsCollectors = ServiceLoader.load(LabelsCollector.class); + ArrayList labelsCollectorsList = new ArrayList<>(); + for (LabelsCollector labelsCollector : labelsCollectors) { + labelsCollectorsList.add(labelsCollector); + } + labelsCollectorsList.sort((o1, o2) -> o2.getOrder() - o1.getOrder()); + return labelsCollectorsList; + } + + private void initLabels(Properties properties) { + labelsCollectorsList = loadLabelsCollectors(); + this.labels = getLabels(labelsCollectorsList, properties); + } + + Map getLabels(ArrayList labelsCollectorsList, Properties properties) { + Map labels = new HashMap<>(8); + for (LabelsCollector labelsCollector : labelsCollectorsList) { + try { + LOGGER.info("LabelsCollector with name [{}] initializing......", labelsCollector.getName()); + labelsCollector.init(properties); + LOGGER.info("LabelsCollector with name [{}] initialize finished......", labelsCollector.getName()); + } catch (Exception e) { + LOGGER.error("init LabelsCollector with [name:{}] failed", labelsCollector.getName(), e); + continue; + } + LOGGER.info("Process LabelsCollector with [name:{}]", labelsCollector.getName()); + for (Map.Entry entry : labelsCollector.getLabels().entrySet()) { + if (innerAddLabel(labels, entry.getKey(), entry.getValue())) { + LOGGER.info("pick label with [key:{}, value:{}] of collector [name:{}]", entry.getKey(), + entry.getValue(), labelsCollector.getName()); + } else { + LOGGER.info( + " ignore label with [key:{}, value:{}] of collector [name:{}]," + + "already existed in LabelsCollectorManager with previous [value:{}],", + entry.getKey(), entry.getValue(), labelsCollector.getName(), labels.get(entry.getKey())); + } + } + } + return labels; + } + + private boolean innerAddLabel(Map labels, String key, String value) { + return null == labels.putIfAbsent(key, value); + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/AbstractConfigGetter.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/AbstractConfigGetter.java new file mode 100644 index 00000000000..43a5b5ab6f0 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/AbstractConfigGetter.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import com.alibaba.nacos.common.utils.StringUtils; +import org.slf4j.Logger; + +import java.util.Properties; + +/** + * AbstractConfigGetter. + * + * @author rong + * @date 2024-03-06 17:42 + */ +public abstract class AbstractConfigGetter implements OrderedConfigGetter { + + protected Logger logger; + + protected int order; + + @Override + public void init(Properties properties) { + String weightKey = getWeightKey(); + String weight = properties.getProperty(weightKey, System.getProperty(weightKey, System.getenv(weightKey))); + if (StringUtils.isBlank(weight)) { + return; + } + try { + order = Integer.parseInt(weight); + } catch (NumberFormatException e) { + logger.error("parse weight error, weight={}", weight, e); + } + } + + /** + * get weight key which will be used to get weight from properties/env/jvm. + * + * @date 2024/3/7 + * @return String weight key. + */ + protected abstract String getWeightKey(); +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/ConfigGetterManager.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/ConfigGetterManager.java new file mode 100644 index 00000000000..e5887845e43 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/ConfigGetterManager.java @@ -0,0 +1,58 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + +/** + * description. + * + * @author rong + * @date 2024-03-07 10:02 + */ +public class ConfigGetterManager { + + private final List priorityList = new ArrayList<>(); + + public String getConfig(String key) { + for (OrderedConfigGetter getter : priorityList) { + String config = getter.getConfig(key); + if (config != null) { + return config; + } + } + return null; + } + + public ConfigGetterManager(Properties properties) { + Properties temp = new Properties(); + temp.putAll(properties); + init(temp); + } + + private void init(Properties properties) { + priorityList.add(new PropertiesConfigGetter()); + priorityList.add(new JvmConfigGetter()); + priorityList.add(new EnvConfigGetter()); + priorityList.stream().filter(Objects::nonNull).forEach(getter -> getter.init(properties)); + priorityList.sort((o1, o2) -> o2.order() - o1.order()); + } + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/EnvConfigGetter.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/EnvConfigGetter.java new file mode 100644 index 00000000000..40a3f8a1d1b --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/EnvConfigGetter.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import com.alibaba.nacos.api.common.Constants; +import org.slf4j.LoggerFactory; + +import java.util.Properties; + +/** + * EnvConfigGetter. + * + * @author rong + * @date 2024-03-06 17:42 + */ +public class EnvConfigGetter extends AbstractConfigGetter implements OrderedConfigGetter { + + @Override + public void init(Properties properties) { + order = Constants.APP_CONN_LABELS_ENV_DEFAULT_WEIGHT; + logger = LoggerFactory.getLogger(EnvConfigGetter.class); + super.init(properties); + } + + @Override + protected String getWeightKey() { + return Constants.APP_CONN_LABELS_ENV_WEIGHT_KEY; + } + + @Override + public int order() { + return order; + } + + @Override + public String getConfig(String key) { + return System.getenv(key); + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/JvmConfigGetter.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/JvmConfigGetter.java new file mode 100644 index 00000000000..0d65a4e505c --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/JvmConfigGetter.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import com.alibaba.nacos.api.common.Constants; +import org.slf4j.LoggerFactory; + +import java.util.Properties; + +/** + * JvmConfigGetter. + * + * @author rong + * @date 2024-03-06 17:42 + */ +public class JvmConfigGetter extends AbstractConfigGetter implements OrderedConfigGetter { + + @Override + public void init(Properties properties) { + order = Constants.APP_CONN_LABELS_JVM_DEFAULT_WEIGHT; + logger = LoggerFactory.getLogger(JvmConfigGetter.class); + super.init(properties); + } + + @Override + protected String getWeightKey() { + return Constants.APP_CONN_LABELS_JVM_WEIGHT_KEY; + } + + @Override + public int order() { + return order; + } + + @Override + public String getConfig(String key) { + return System.getProperty(key); + } +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/OrderedConfigGetter.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/OrderedConfigGetter.java new file mode 100644 index 00000000000..b65bb5ef5ca --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/OrderedConfigGetter.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import java.util.Properties; + +/** + * OrderedConfigGetter. + * + * @author rong + */ +public interface OrderedConfigGetter { + + /** + * init. + * + * @date 2024/3/6 + * @param properties properties. + */ + void init(Properties properties); + + /** + * get order. + * + * @date 2024/3/6 + * @return the order. + */ + int order(); + + /** + * get config by key. + * + * @date 2024/3/6 + * @param key key. + * @return the config. + */ + String getConfig(String key); +} diff --git a/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/PropertiesConfigGetter.java b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/PropertiesConfigGetter.java new file mode 100644 index 00000000000..720b33b6513 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/labels/impl/utils/PropertiesConfigGetter.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl.utils; + +import com.alibaba.nacos.api.common.Constants; +import org.slf4j.LoggerFactory; + +import java.util.Properties; + +/** + * PropertiesConfigGetter. + * + * @author rong + * @date 2024-03-06 17:42 + */ +public class PropertiesConfigGetter extends AbstractConfigGetter implements OrderedConfigGetter { + + private Properties properties; + + @Override + public void init(Properties properties) { + this.properties = properties; + order = Constants.APP_CONN_LABELS_PROPERTIES_DEFAULT_WEIGHT; + logger = LoggerFactory.getLogger(PropertiesConfigGetter.class); + super.init(properties); + } + + @Override + protected String getWeightKey() { + return Constants.APP_CONN_LABELS_PROPERTIES_WEIGHT_KEY; + } + + @Override + public int order() { + return order; + } + + @Override + public String getConfig(String key) { + if (properties == null) { + return null; + } + return properties.getProperty(key); + } + +} diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java index 6d850568e3c..366ecacdc6a 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java @@ -17,15 +17,21 @@ package com.alibaba.nacos.common.remote.client; import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.common.labels.impl.DefaultLabelsCollectorManager; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.grpc.GrpcClusterClient; import com.alibaba.nacos.common.remote.client.grpc.GrpcSdkClient; +import com.alibaba.nacos.common.utils.ConnLabelsUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; +import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + +import static com.alibaba.nacos.api.common.Constants.APP_CONN_PREFIX; /** * RpcClientFactory.to support multi client for different modules of usage. @@ -39,6 +45,8 @@ public class RpcClientFactory { private static final Map CLIENT_MAP = new ConcurrentHashMap<>(); + private static AtomicReference defaultLabelsCollectorManager; + /** * get all client. * @@ -78,7 +86,22 @@ public static RpcClient createClient(String clientName, ConnectionType connectio public static RpcClient createClient(String clientName, ConnectionType connectionType, Map labels, RpcClientTlsConfig tlsConfig) { return createClient(clientName, connectionType, null, null, labels, tlsConfig); - + } + + /** + * create client with properties. + * + * @date 2024/3/7 + * @return rpc client. + */ + public static RpcClient createClient(String clientName, ConnectionType connectionType, Map labels, + Properties properties, RpcClientTlsConfig tlsConfig) { + try { + labels = ConnLabelsUtils.mergeMapByOrder(labels, collectLabels(properties)); + } catch (Exception e) { + LOGGER.error("Collect labels error when creating config rpc client", e); + } + return createClient(clientName, connectionType, null, null, labels, tlsConfig); } public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize, @@ -109,6 +132,22 @@ public static RpcClient createClient(String clientName, ConnectionType connectio }); } + /** + * collect labels. + * + * @return the labels map + * @description will get labels map from properties, valueFromSpi, JVM OPTIONS or ENV by order of properties > + * valueFromSpi > JVM OPTIONS > ENV which will use the next level value when the key doesn't exist in current + * map + */ + private static Map collectLabels(Properties properties) { + //labels from spi + defaultLabelsCollectorManager.compareAndSet(null, new DefaultLabelsCollectorManager(properties)); + Map allLabels = defaultLabelsCollectorManager.get().refreshAllLabels(properties); + allLabels = ConnLabelsUtils.addPrefixForEachKey(allLabels, APP_CONN_PREFIX); + return allLabels; + } + /** * create a rpc client. * diff --git a/common/src/main/java/com/alibaba/nacos/common/utils/ConnLabelsUtils.java b/common/src/main/java/com/alibaba/nacos/common/utils/ConnLabelsUtils.java new file mode 100644 index 00000000000..b2b150d5a85 --- /dev/null +++ b/common/src/main/java/com/alibaba/nacos/common/utils/ConnLabelsUtils.java @@ -0,0 +1,144 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.stream.Collectors; + +/** + * ConnLabelsUtils. + * + * @author rong + */ +public class ConnLabelsUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConnLabelsUtils.class); + + public static final String LABEL_EQUALS_OPERATOR = "="; + + public static final String LABEL_SPLIT_OPERATOR = ","; + + public static final int TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH = 2; + + public static final int TAG_V1_LABEL_KEY_VALUE_SPLIT_LENGTH = 1; + + /** + * parse property value to map. + * + * @date 2024/1/29 + * @description will get a key-value map from properties, JVM OPTIONS, ENV by order of properties > JVM OPTIONS > ENV + * which will use the next level value when the current level value isn't setup. + *

eg: if the value of "nacos.app.conn.labels"(properties' key) is "k1=v1,k2=v2"(properties' value), the result will be + * a Map with value{k1=v1,k2=v2}.

+ * @param properties Properties + * @param propertyName which key to get + * @return (String)key-(String)value map + */ + public static Map parsePropertyValue2Map(Properties properties, String propertyName) { + String rawLabels = properties.getProperty(propertyName, System.getProperty(propertyName, System.getenv(propertyName))); + if (StringUtils.isBlank(rawLabels)) { + LOGGER.info("no value found for property key: {}", propertyName); + return new HashMap<>(2); + } + return parseRawLabels(rawLabels); + } + + /** + * parse raw json labels into a key-value map. + * + * @date 2024/1/29 + * @description + * @param rawLabels rawLabels to parse + * @return map parsed from rawLabels + */ + public static Map parseRawLabels(String rawLabels) { + if (StringUtils.isBlank(rawLabels)) { + return new HashMap<>(2); + } + HashMap resultMap = new HashMap<>(2); + try { + Arrays.stream(rawLabels.split(LABEL_SPLIT_OPERATOR)) + .filter(Objects::nonNull) + .map(String::trim) + .filter(StringUtils::isNotBlank) + .forEach(label -> { + String[] kv = label.split(LABEL_EQUALS_OPERATOR); + if (kv.length == TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH) { + resultMap.put(kv[0].trim(), kv[1].trim()); + } else if (kv.length == TAG_V1_LABEL_KEY_VALUE_SPLIT_LENGTH) { + resultMap.put(kv[0].trim(), kv[0].trim()); + } else { + LOGGER.error("unknown label format: {}", label); + } + }); + } catch (Exception e) { + LOGGER.error("unknown label format: {}", rawLabels); + } + return resultMap; + } + + /** + * merge two map into one by using the former value when key is duplicated. + * + * @date 2024/1/29 + * @description merge two map into one preferring using the first one when key is duplicated + * @param preferredMap preferredMap + * @param backwardMap backwardMap + */ + public static Map mergeMapByOrder(Map preferredMap, Map backwardMap) { + if (preferredMap == null || preferredMap.isEmpty()) { + return new HashMap(8) { { + putAll(backwardMap); } }; + } + if (backwardMap == null || backwardMap.isEmpty()) { + return new HashMap(8) { { + putAll(preferredMap); } }; + } + HashMap resultMap = new HashMap(8) {{ + putAll(preferredMap); } }; + backwardMap.forEach((key, value) -> { + if (!resultMap.containsKey(key)) { + resultMap.put(key, value); + } + }); + return resultMap; + } + + /** + * add prefix for each key in map. + * + * @date 2024/1/29 + * @description add prefix for each key in map + * @param map map to add prefix + * @param prefix prefix + */ + public static Map addPrefixForEachKey(Map map, String prefix) { + if (map == null || map.isEmpty()) { + return map; + } + return map.entrySet().stream().filter(Objects::nonNull) + .filter(elem -> !elem.getKey().trim().isEmpty()) + .collect(Collectors.toMap(elem -> prefix + elem.getKey(), Map.Entry::getValue)); + } +} diff --git a/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector b/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector new file mode 100644 index 00000000000..ffe5bb9699b --- /dev/null +++ b/common/src/main/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector @@ -0,0 +1,19 @@ + # + # + # Copyright 1999-2023 Alibaba Group Holding Ltd. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # + # + +com.alibaba.nacos.common.labels.impl.DefaultLabelsCollector \ No newline at end of file diff --git a/common/src/test/java/com/alibaba/nacos/common/labels/impl/ConfigGetterManagerTest.java b/common/src/test/java/com/alibaba/nacos/common/labels/impl/ConfigGetterManagerTest.java new file mode 100644 index 00000000000..10e00f2bca8 --- /dev/null +++ b/common/src/test/java/com/alibaba/nacos/common/labels/impl/ConfigGetterManagerTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.common.labels.impl.utils.ConfigGetterManager; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Properties; + +/** + * description. + * + * @author rong + * @date 2024-03-07 11:10 + */ +public class ConfigGetterManagerTest { + + @Test + public void testGetByOrder() { + Properties init = new Properties(); + init.put(Constants.APP_CONN_LABELS_PROPERTIES_WEIGHT_KEY, "1"); + init.put(Constants.APP_CONN_LABELS_ENV_WEIGHT_KEY, "2"); + init.put(Constants.APP_CONN_LABELS_JVM_WEIGHT_KEY, "3"); + System.setProperty(Constants.APP_CONN_LABELS_PREFIX, "gray=jvm_pre"); + init.put(Constants.APP_CONN_LABELS_PREFIX, "gray=properties_pre"); + + String result = new ConfigGetterManager(init).getConfig(Constants.APP_CONN_LABELS_PREFIX); + Assert.assertEquals("gray=jvm_pre", result); + + init.put(Constants.APP_CONN_LABELS_PROPERTIES_WEIGHT_KEY, "3"); + init.put(Constants.APP_CONN_LABELS_ENV_WEIGHT_KEY, "2"); + init.put(Constants.APP_CONN_LABELS_JVM_WEIGHT_KEY, "1"); + + result = new ConfigGetterManager(init).getConfig(Constants.APP_CONN_LABELS_PREFIX); + Assert.assertEquals("gray=properties_pre", result); + + init.remove(Constants.APP_CONN_LABELS_PREFIX); + result = new ConfigGetterManager(init).getConfig(Constants.APP_CONN_LABELS_PREFIX); + Assert.assertEquals("gray=jvm_pre", result); + } +} diff --git a/common/src/test/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManagerTest.java b/common/src/test/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManagerTest.java new file mode 100644 index 00000000000..9bddfb3ff56 --- /dev/null +++ b/common/src/test/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManagerTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.api.common.Constants; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; +import java.util.Properties; + +/** + * description. + * + * @author rong + * @date 2024-02-29 20:13 + */ +public class DefaultLabelsCollectorManagerTest { + @Test + public void tagV2LabelsCollectorTest() { + Properties properties = new Properties(); + properties.put(Constants.APP_CONN_LABELS_PREFIX, "k1=v1,gray=properties_pre"); + properties.put(Constants.CONFIG_GRAY, "properties_after"); + DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager(properties); + Map labels = defaultLabelsCollectorManager.getAllLabels(); + Assert.assertEquals("properties_after", labels.get(Constants.GRAY)); + Assert.assertEquals("v1", labels.get("k1")); + } + + @Test + public void tagV2LabelsCollectorOrderTest() { + Properties properties = new Properties(); + DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager(properties); + Map labels = defaultLabelsCollectorManager.getAllLabels(); + String test = labels.get("test"); + Assert.assertEquals("test2", test); + } + +} diff --git a/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test1LabelsCollector.java b/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test1LabelsCollector.java new file mode 100644 index 00000000000..338d09fdb27 --- /dev/null +++ b/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test1LabelsCollector.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.common.labels.LabelsCollector; + +import java.util.Properties; + +/** + * Test1LabelsCollector. + * + * @author rong + */ +public class Test1LabelsCollector extends AbstractLabelsCollector implements LabelsCollector { + + @Override + public String getName() { + return "test1"; + } + + @Override + public void init(Properties properties) { + labels.put("test", getName()); + } + + @Override + public int getOrder() { + return 1; + } +} \ No newline at end of file diff --git a/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test2LabelsCollector.java b/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test2LabelsCollector.java new file mode 100644 index 00000000000..266be160d6d --- /dev/null +++ b/common/src/test/java/com/alibaba/nacos/common/labels/impl/Test2LabelsCollector.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.labels.impl; + +import com.alibaba.nacos.common.labels.LabelsCollector; + +import java.util.Properties; + +/** + * TagV1LabelsCollector. + * + * @author rong + */ +public class Test2LabelsCollector extends AbstractLabelsCollector implements LabelsCollector { + + @Override + public String getName() { + return "test2"; + } + + @Override + public void init(Properties properties) { + labels.put("test", getName()); + } + + @Override + public int getOrder() { + return 2; + } +} \ No newline at end of file diff --git a/common/src/test/java/com/alibaba/nacos/common/utils/ConnLabelsUtilsTest.java b/common/src/test/java/com/alibaba/nacos/common/utils/ConnLabelsUtilsTest.java new file mode 100644 index 00000000000..0530f25c880 --- /dev/null +++ b/common/src/test/java/com/alibaba/nacos/common/utils/ConnLabelsUtilsTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.common.utils; + +import org.junit.Test; + +import java.util.Map; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * description. + * + * @author rong + * @date 2024-03-01 15:10 + */ +public class ConnLabelsUtilsTest { + + @Test + public void testParsePropertyValue2Map() { + Properties properties = new Properties(); + String property = "property"; + String rawValue = "k1 = v1, k2 = v2"; + properties.put(property, rawValue); + String property1 = "property2"; + String rawValue1 = "k1, kk2"; + properties.put(property1, rawValue1); + + Map m = ConnLabelsUtils.parsePropertyValue2Map(properties, property); + assertEquals(2, m.size()); + assertEquals("v1", m.get("k1")); + assertEquals("v2", m.get("k2")); + + Map m1 = ConnLabelsUtils.parsePropertyValue2Map(properties, property1); + assertEquals(2, m.size()); + assertEquals("k1", m1.get("k1")); + assertEquals("kk2", m1.get("kk2")); + + m = ConnLabelsUtils.mergeMapByOrder(m, m1); + assertEquals(3, m.size()); + assertEquals("v1", m.get("k1")); + assertEquals("v2", m.get("k2")); + assertEquals("kk2", m.get("kk2")); + + m = ConnLabelsUtils.addPrefixForEachKey(m, "test_prefix"); + assertEquals(3, m.size()); + m.forEach((k, v) -> { + assertTrue(k.startsWith("test_prefix")); + }); + } + +} diff --git a/common/src/test/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector b/common/src/test/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector new file mode 100644 index 00000000000..a6bbe6a5d28 --- /dev/null +++ b/common/src/test/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector @@ -0,0 +1,21 @@ + # + # + # Copyright 1999-2023 Alibaba Group Holding Ltd. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # + # + +com.alibaba.nacos.common.labels.impl.DefaultLabelsCollector +com.alibaba.nacos.common.labels.impl.Test1LabelsCollector +com.alibaba.nacos.common.labels.impl.Test2LabelsCollector diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java index 190787c5e4c..003556e8d2e 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/Connection.java @@ -43,6 +43,10 @@ public Map getLabels() { return metaInfo.getLabels(); } + public Map getAppLabels() { + return metaInfo.getAppLabels(); + } + public boolean isTraced() { return traced; } diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionMeta.java b/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionMeta.java index 6459053ead1..51e43f65564 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionMeta.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/ConnectionMeta.java @@ -16,11 +16,16 @@ package com.alibaba.nacos.core.remote; +import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.remote.RemoteConstants; +import com.alibaba.nacos.common.utils.ConnLabelsUtils; +import com.alibaba.nacos.common.utils.StringUtils; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; @@ -145,6 +150,26 @@ public Map getLabels() { return labels; } + /** + * get labels map with filter of starting with prefix #{@link Constants#APP_CONN_PREFIX} + * and return a new map trim the prefix #{@link Constants#APP_CONN_PREFIX}. + * @date 2024/2/29 + * @return map of labels. + */ + public Map getAppLabels() { + HashMap labelsMap = new HashMap(8) { + { + put(Constants.APPNAME, labels.get(Constants.APPNAME)); + put(Constants.CLIENT_VERSION_KEY, version); + } + }; + return ConnLabelsUtils.mergeMapByOrder(labelsMap, labels.entrySet().stream().filter(Objects::nonNull) + .filter(e -> e.getKey().startsWith(Constants.APP_CONN_PREFIX) + && e.getKey().length() > Constants.APP_CONN_PREFIX.length() + && StringUtils.isNotBlank(e.getValue())).collect( + Collectors.toMap(k -> k.getKey().substring(Constants.APP_CONN_PREFIX.length()), Map.Entry::getValue))); + } + /** * Setter method for property labels. * From 1631862fe00e13eb65e80a16bae4dae5e73bfc8d Mon Sep 17 00:00:00 2001 From: "liurong.liu" Date: Mon, 18 Mar 2024 20:37:50 +0800 Subject: [PATCH 2/3] remove some constants --- .../java/com/alibaba/nacos/api/common/Constants.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index f7cdb292ad7..8b636a7894f 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -253,16 +253,6 @@ public class Constants { public static final String APP_CONN_PREFIX = "app_"; - public static final String BETA_IPS = "betaIps"; - - public static final String TAG_V1 = "tag"; - - public static final String TAG_V2 = "tagv2"; - - public static final String TAG_V2_PREFIX = "tagv2_"; - - public static final int CONFIG_GRAY_DEFAULT_ORDER_WEIGHT = 100; - public static final String CONFIG_GRAY = "nacos.config" + DOT + GRAY; /** From efb27e3f4ce0d15323245569e806b69d39e77440 Mon Sep 17 00:00:00 2001 From: "liurong.liu" Date: Tue, 19 Mar 2024 17:14:51 +0800 Subject: [PATCH 3/3] fixup test case --- .../alibaba/nacos/client/config/impl/ClientWorkerTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java b/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java index 270d522bd87..4e0632351a3 100644 --- a/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java @@ -99,6 +99,9 @@ public void before() { rpcClientFactoryMockedStatic.when( () -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class), any(Map.class), any(RpcClientTlsConfig.class))).thenReturn(rpcClient); + rpcClientFactoryMockedStatic.when( + () -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class), any(Map.class), + any(Properties.class), any(RpcClientTlsConfig.class))).thenReturn(rpcClient); localConfigInfoProcessorMockedStatic = Mockito.mockStatic(LocalConfigInfoProcessor.class); Properties properties = new Properties(); properties.put(PropertyKeyConst.NAMESPACE, TEST_NAMESPACE); @@ -555,7 +558,7 @@ public void receiveConfigInfo(String configInfo) { Mockito.when(rpcClientInner.isWaitInitiated()).thenReturn(true, false); rpcClientFactoryMockedStatic.when( () -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class), any(Map.class), - any(RpcClientTlsConfig.class))).thenReturn(rpcClientInner); + any(Properties.class), any(RpcClientTlsConfig.class))).thenReturn(rpcClientInner); // mock listen and remove listen request Mockito.when(rpcClientInner.request(any(ConfigBatchListenRequest.class), anyLong())) .thenReturn(response, response);