simplify nacos app labels collector and log fix. (#11867)
* remove batch * simplify label collector ,optimize log * simplify label collector ,optimize log * testcase fix
This commit is contained in:
parent
9db51e58ed
commit
6dc0a2109f
@ -225,9 +225,7 @@ 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 APP_CONN_LABELS_KEY = "nacos.app.conn.labels";
|
||||
|
||||
public static final String DOT = ".";
|
||||
|
||||
@ -239,21 +237,11 @@ public class Constants {
|
||||
|
||||
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_LABELS_PREFERRED = "nacos_app_conn_labels_preferred";
|
||||
|
||||
public static final String APP_CONN_PREFIX = "app_";
|
||||
|
||||
public static final String CONFIG_GRAY = "nacos.config" + DOT + GRAY;
|
||||
public static final String CONFIG_GRAY_LABEL = "nacos.config.gray.label";
|
||||
|
||||
/**
|
||||
* The constants in config directory.
|
||||
@ -269,9 +257,9 @@ public class Constants {
|
||||
* The constants in naming directory.
|
||||
*/
|
||||
public static class Naming {
|
||||
|
||||
|
||||
public static final String NAMING_MODULE = "naming";
|
||||
|
||||
|
||||
public static final String CMDB_CONTEXT_TYPE = "CMDB";
|
||||
}
|
||||
|
||||
@ -279,7 +267,7 @@ public class Constants {
|
||||
* The constants in remote directory.
|
||||
*/
|
||||
public static class Remote {
|
||||
|
||||
|
||||
public static final String INTERNAL_MODULE = "internal";
|
||||
}
|
||||
|
||||
@ -291,9 +279,9 @@ public class Constants {
|
||||
public static final int SERIALIZE_ERROR_CODE = 100;
|
||||
|
||||
public static final int DESERIALIZE_ERROR_CODE = 101;
|
||||
|
||||
|
||||
public static final int FIND_DATASOURCE_ERROR_CODE = 102;
|
||||
|
||||
|
||||
public static final int FIND_TABLE_ERROR_CODE = 103;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
|
||||
import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
|
||||
import com.alibaba.nacos.client.config.utils.ContentUtils;
|
||||
import com.alibaba.nacos.client.env.NacosClientProperties;
|
||||
import com.alibaba.nacos.client.env.SourceType;
|
||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.client.utils.AppNameUtils;
|
||||
@ -49,6 +50,7 @@ import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.client.utils.TenantUtil;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.common.labels.impl.DefaultLabelsCollectorManager;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
@ -60,6 +62,7 @@ import com.alibaba.nacos.common.remote.client.RpcClient;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientFactory;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;
|
||||
import com.alibaba.nacos.common.remote.client.ServerListFactory;
|
||||
import com.alibaba.nacos.common.utils.ConnLabelsUtils;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
@ -80,6 +83,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
@ -95,6 +99,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.APP_CONN_PREFIX;
|
||||
import static com.alibaba.nacos.api.common.Constants.ENCODE;
|
||||
|
||||
/**
|
||||
@ -123,6 +128,8 @@ public class ClientWorker implements Closeable {
|
||||
*/
|
||||
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<>(new HashMap<>());
|
||||
|
||||
private Map<String, String> appLables = new HashMap<>();
|
||||
|
||||
private final ConfigFilterChainManager configFilterChainManager;
|
||||
|
||||
private final String uuid = UUID.randomUUID().toString();
|
||||
@ -477,14 +484,18 @@ public class ClientWorker implements Closeable {
|
||||
init(properties);
|
||||
|
||||
agent = new ConfigRpcTransportClient(properties, serverListManager);
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(
|
||||
initWorkerThreadCount(properties),
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(initWorkerThreadCount(properties),
|
||||
new NameThreadFactory("com.alibaba.nacos.client.Worker"));
|
||||
agent.setExecutor(executorService);
|
||||
agent.start();
|
||||
|
||||
}
|
||||
|
||||
void initAppLabels(Properties properties) {
|
||||
this.appLables = ConnLabelsUtils.addPrefixForEachKey(defaultLabelsCollectorManager.getLabels(properties),
|
||||
APP_CONN_PREFIX);
|
||||
}
|
||||
|
||||
private int initWorkerThreadCount(NacosClientProperties properties) {
|
||||
int count = ThreadUtils.getSuitableThreadCount(THREAD_MULTIPLE);
|
||||
if (properties == null) {
|
||||
@ -505,6 +516,7 @@ public class ClientWorker implements Closeable {
|
||||
|
||||
this.enableRemoteSyncConfig = Boolean.parseBoolean(
|
||||
properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));
|
||||
initAppLabels(properties.getProperties(SourceType.PROPERTIES));
|
||||
}
|
||||
|
||||
Map<String, Object> getMetrics(List<ClientConfigMetricRequest.MetricsKey> metricsKeys) {
|
||||
@ -567,6 +579,8 @@ public class ClientWorker implements Closeable {
|
||||
return agent.isHealthServer();
|
||||
}
|
||||
|
||||
private static DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();
|
||||
|
||||
public class ConfigRpcTransportClient extends ConfigTransportClient {
|
||||
|
||||
Map<String, ExecutorService> multiTaskExecutor = new HashMap<>();
|
||||
@ -633,10 +647,17 @@ public class ClientWorker implements Closeable {
|
||||
labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);
|
||||
labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_CONFIG);
|
||||
labels.put(Constants.APPNAME, AppNameUtils.getAppName());
|
||||
labels.put(Constants.VIPSERVER_TAG, EnvUtil.getSelfVipserverTag());
|
||||
labels.put(Constants.AMORY_TAG, EnvUtil.getSelfAmoryTag());
|
||||
labels.put(Constants.LOCATION_TAG, EnvUtil.getSelfLocationTag());
|
||||
if (EnvUtil.getSelfVipserverTag() != null) {
|
||||
labels.put(Constants.VIPSERVER_TAG, EnvUtil.getSelfVipserverTag());
|
||||
}
|
||||
if (EnvUtil.getSelfAmoryTag() != null) {
|
||||
labels.put(Constants.AMORY_TAG, EnvUtil.getSelfAmoryTag());
|
||||
}
|
||||
if (EnvUtil.getSelfLocationTag() != null) {
|
||||
labels.put(Constants.LOCATION_TAG, EnvUtil.getSelfLocationTag());
|
||||
}
|
||||
|
||||
labels.putAll(appLables);
|
||||
return labels;
|
||||
}
|
||||
|
||||
|
@ -19,22 +19,19 @@ package com.alibaba.nacos.client.env;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* NacosClientProperties interface.
|
||||
* include all the properties from jvm args, system environment, default setting.
|
||||
* more details you can see https://github.com/alibaba/nacos/issues/8622
|
||||
* NacosClientProperties interface. include all the properties from jvm args, system environment, default setting. more
|
||||
* details you can see https://github.com/alibaba/nacos/issues/8622
|
||||
*
|
||||
* @author onewe
|
||||
*/
|
||||
public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* all the NacosClientProperties object must be created by PROTOTYPE,
|
||||
* so child NacosClientProperties can read properties from the PROTOTYPE.
|
||||
* it looks like this:
|
||||
* |-PROTOTYPE----------------> ip=127.0.0.1
|
||||
* |---|-child1---------------> port=6379
|
||||
* if you search key called "port" from child1, certainly you will get 6379
|
||||
* if you search key called "ip" from child1, you will get 127.0.0.1.
|
||||
* because the child can read properties from parent NacosClientProperties
|
||||
* all the NacosClientProperties object must be created by PROTOTYPE, so child NacosClientProperties can read
|
||||
* properties from the PROTOTYPE. it looks like this: |-PROTOTYPE----------------> ip=127.0.0.1
|
||||
* |---|-child1---------------> port=6379 if you search key called "port" from child1, certainly you will get 6379
|
||||
* if you search key called "ip" from child1, you will get 127.0.0.1. because the child can read properties from
|
||||
* parent NacosClientProperties
|
||||
*/
|
||||
NacosClientProperties PROTOTYPE = SearchableProperties.INSTANCE;
|
||||
|
||||
@ -48,7 +45,8 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get property, if the value can not be got by the special key, the default value will be returned.
|
||||
* @param key special key
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return string value or default value.
|
||||
*/
|
||||
@ -56,13 +54,23 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get property from special property source.
|
||||
*
|
||||
* @param source source type
|
||||
* @see SourceType
|
||||
* @param key special key
|
||||
* @param key special key
|
||||
* @return string value or null.
|
||||
* @see SourceType
|
||||
*/
|
||||
String getPropertyFrom(SourceType source, String key);
|
||||
|
||||
/**
|
||||
* get property from special property source.
|
||||
*
|
||||
* @param source source type
|
||||
* @return string value or null.
|
||||
* @see SourceType
|
||||
*/
|
||||
Properties getProperties(SourceType source);
|
||||
|
||||
/**
|
||||
* get boolean, if the value can not be got by the special key, the null will be returned.
|
||||
*
|
||||
@ -73,7 +81,8 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get boolean, if the value can not be got by the special key, the default value will be returned.
|
||||
* @param key special key
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return boolean value or defaultValue.
|
||||
*/
|
||||
@ -89,7 +98,8 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get integer, if the value can not be got by the special key, the default value will be returned.
|
||||
* @param key special key
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return integer value or default value
|
||||
*/
|
||||
@ -105,7 +115,8 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get long, if the value can not be got by the special key, the default value will be returned.
|
||||
* @param key special key
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return long value or default value
|
||||
*/
|
||||
@ -113,19 +124,22 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* set property.
|
||||
* @param key key
|
||||
*
|
||||
* @param key key
|
||||
* @param value value
|
||||
*/
|
||||
void setProperty(String key, String value);
|
||||
|
||||
/**
|
||||
* add properties.
|
||||
*
|
||||
* @param properties properties
|
||||
*/
|
||||
void addProperties(Properties properties);
|
||||
|
||||
/**
|
||||
* Tests if the specified object is a key in this NacosClientProperties.
|
||||
*
|
||||
* @param key key – possible key
|
||||
* @return true if and only if the specified object is a key in this NacosClientProperties, false otherwise.
|
||||
*/
|
||||
@ -133,18 +147,21 @@ public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* get properties from NacosClientProperties.
|
||||
*
|
||||
* @return properties
|
||||
*/
|
||||
Properties asProperties();
|
||||
|
||||
/**
|
||||
* create a new NacosClientProperties which scope is itself.
|
||||
*
|
||||
* @return NacosClientProperties
|
||||
*/
|
||||
NacosClientProperties derive();
|
||||
|
||||
/**
|
||||
* create a new NacosClientProperties from NacosClientProperties#PROTOTYPE and init.
|
||||
*
|
||||
* @param properties properties
|
||||
* @return NacosClientProperties
|
||||
*/
|
||||
|
@ -124,6 +124,23 @@ class SearchableProperties implements NacosClientProperties {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties(SourceType source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
switch (source) {
|
||||
case JVM:
|
||||
return JVM_ARGS_PROPERTY_SOURCE.asProperties();
|
||||
case ENV:
|
||||
return SYSTEM_ENV_PROPERTY_SOURCE.asProperties();
|
||||
case PROPERTIES:
|
||||
return this.propertiesPropertySource.asProperties();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(String key) {
|
||||
return getBoolean(key, null);
|
||||
|
@ -102,6 +102,11 @@
|
||||
additivity="false">
|
||||
<AppenderRef ref="ASYNC_REMOTE"/>
|
||||
</Logger>
|
||||
|
||||
<Logger name="com.alibaba.nacos.common.labels" level="${nacosClientProperty:com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
<AppenderRef ref="ASYNC_REMOTE"/>
|
||||
</Logger>
|
||||
|
||||
<Logger name="com.alibaba.nacos.client.config" level="${nacosClientProperty:com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
|
@ -99,6 +99,10 @@
|
||||
<appender-ref ref="ASYNC-CONFIG"/>
|
||||
</logger>
|
||||
|
||||
<Logger name="com.alibaba.nacos.common.labels" level="${nacosConfigLogLevel}"
|
||||
additivity="false">
|
||||
<appender-ref ref="ASYNC-REMOTE"/>
|
||||
</Logger>
|
||||
|
||||
<Logger name="com.alibaba.nacos.common.remote.client" level="${nacosConfigLogLevel}"
|
||||
additivity="false">
|
||||
|
@ -82,7 +82,7 @@ public class Log4J2NacosLoggingTest {
|
||||
loggerContext = (LoggerContext) LogManager.getContext(false);
|
||||
contextConfiguration = loggerContext.getConfiguration();
|
||||
Map<String, LoggerConfig> nacosClientLoggers = contextConfiguration.getLoggers();
|
||||
assertEquals(4, nacosClientLoggers.size());
|
||||
assertEquals(5, nacosClientLoggers.size());
|
||||
for (Map.Entry<String, LoggerConfig> loggerEntry : nacosClientLoggers.entrySet()) {
|
||||
String loggerName = loggerEntry.getKey();
|
||||
Assert.assertTrue(loggerName.startsWith(NACOS_LOGGER_PREFIX));
|
||||
|
@ -27,23 +27,15 @@ import java.util.Properties;
|
||||
*/
|
||||
public interface LabelsCollector {
|
||||
|
||||
/**
|
||||
* init labels.
|
||||
*
|
||||
* @param properties Properties
|
||||
* @date 2024/2/4
|
||||
* @description init labels
|
||||
*/
|
||||
void init(Properties properties);
|
||||
|
||||
/**
|
||||
* getLabels.
|
||||
*
|
||||
* @return Map
|
||||
* @param properties properties
|
||||
* @return Map labels.
|
||||
* @date 2024/2/4
|
||||
* @description get all labels
|
||||
*/
|
||||
Map<String, String> getLabels();
|
||||
Map<String, String> collectLabels(Properties properties);
|
||||
|
||||
/**
|
||||
* getOrder.
|
||||
|
@ -27,15 +27,6 @@ import java.util.Properties;
|
||||
*/
|
||||
public interface LabelsCollectorManager {
|
||||
|
||||
/**
|
||||
* get all labels collected.
|
||||
*
|
||||
* @date 2024/2/4
|
||||
* @description
|
||||
* @return all labels
|
||||
*/
|
||||
Map<String, String> getAllLabels();
|
||||
|
||||
/**
|
||||
* refresh all labels.
|
||||
*
|
||||
@ -43,5 +34,5 @@ public interface LabelsCollectorManager {
|
||||
* @param properties Properties.
|
||||
* @return all labels.
|
||||
*/
|
||||
Map<String, String> refreshAllLabels(Properties properties);
|
||||
Map<String, String> getLabels(Properties properties);
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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<String, String> labels = new HashMap<>(2);
|
||||
|
||||
private static final int DEFAULT_INITIAL_ORDER = 100;
|
||||
|
||||
@Override
|
||||
public Map<String, String> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return DEFAULT_INITIAL_ORDER;
|
||||
}
|
||||
}
|
@ -18,52 +18,109 @@ 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.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.DOT;
|
||||
import static com.alibaba.nacos.api.common.Constants.ENV_KEY;
|
||||
import static com.alibaba.nacos.api.common.Constants.JVM_KEY;
|
||||
|
||||
/**
|
||||
* DefaultLabelsCollector.
|
||||
*
|
||||
* @author rong
|
||||
*/
|
||||
public class DefaultLabelsCollector extends AbstractLabelsCollector implements LabelsCollector {
|
||||
public class DefaultLabelsCollector implements LabelsCollector {
|
||||
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultLabelsCollector.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("com.alibaba.nacos.common.labels");
|
||||
|
||||
private final String customName = "defaultLabelsCollector";
|
||||
private final String customName = "defaultNacosLabelsCollector";
|
||||
|
||||
private static final String UNDERSCORE = "_";
|
||||
|
||||
/**
|
||||
* init labels.
|
||||
*
|
||||
* @param properties Properties
|
||||
* @date 2024/2/4
|
||||
*@description will init from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS > ENV</tt> 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).
|
||||
* <p>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}.</p>
|
||||
* @param properties Properties
|
||||
* @description will init from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS > ENV</tt> 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).
|
||||
* <p>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}.</p>
|
||||
*/
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
ConfigGetterManager configGetterManager = new ConfigGetterManager(properties);
|
||||
labels.putAll(ConnLabelsUtils.parseRawLabels(configGetterManager.getConfig(Constants.APP_CONN_LABELS_PREFIX)));
|
||||
public Map<String, String> collectLabels(Properties properties) {
|
||||
|
||||
String grayLabelValue = configGetterManager.getConfig(Constants.CONFIG_GRAY);
|
||||
if (StringUtils.isNotBlank(grayLabelValue)) {
|
||||
labels.put(Constants.GRAY, grayLabelValue);
|
||||
//properties
|
||||
Map<String, String> propertiesLabels = ConnLabelsUtils.parseRawLabels(
|
||||
properties.getProperty(Constants.APP_CONN_LABELS_KEY));
|
||||
if (properties.containsKey(Constants.CONFIG_GRAY_LABEL)) {
|
||||
propertiesLabels.put(Constants.CONFIG_GRAY_LABEL, properties.getProperty(Constants.CONFIG_GRAY_LABEL));
|
||||
}
|
||||
for (Map.Entry<String, String> entry : labels.entrySet()) {
|
||||
LOGGER.info("init labels: {}={}", entry.getKey(), entry.getValue());
|
||||
LOGGER.info("default nacos collect properties labels: {}", propertiesLabels);
|
||||
|
||||
//jvm
|
||||
Map<String, String> jvmLabels = ConnLabelsUtils.parseRawLabels(
|
||||
System.getProperty(Constants.APP_CONN_LABELS_KEY));
|
||||
if (System.getProperty(Constants.CONFIG_GRAY_LABEL) != null) {
|
||||
jvmLabels.put(Constants.CONFIG_GRAY_LABEL, System.getProperty((Constants.CONFIG_GRAY_LABEL)));
|
||||
}
|
||||
LOGGER.info("default nacos collect jvm labels: {}", jvmLabels);
|
||||
|
||||
//env
|
||||
Map<String, String> envLabels = ConnLabelsUtils.parseRawLabels(
|
||||
System.getenv(Constants.APP_CONN_LABELS_KEY.replaceAll(DOT, UNDERSCORE)));
|
||||
if (System.getenv(Constants.CONFIG_GRAY_LABEL.replaceAll(DOT, UNDERSCORE)) != null) {
|
||||
envLabels.put(Constants.CONFIG_GRAY_LABEL,
|
||||
System.getenv(Constants.CONFIG_GRAY_LABEL.replaceAll(DOT, UNDERSCORE)));
|
||||
}
|
||||
LOGGER.info("default nacos collect env labels: {}", envLabels);
|
||||
|
||||
Map<String, String> finalLabels = new HashMap<>(4);
|
||||
String preferred = System.getenv(Constants.APP_CONN_LABELS_PREFERRED);
|
||||
boolean jvmPrefferred = false;
|
||||
boolean envPrefferred = false;
|
||||
|
||||
if (StringUtils.isNotBlank(preferred)) {
|
||||
LOGGER.info("default nacos labels collector preferred {} labels.", preferred);
|
||||
if (JVM_KEY.equals(preferred)) {
|
||||
finalLabels.putAll(jvmLabels);
|
||||
jvmPrefferred = true;
|
||||
} else if (ENV_KEY.equals(preferred)) {
|
||||
finalLabels.putAll(envLabels);
|
||||
envPrefferred = true;
|
||||
}
|
||||
}
|
||||
finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, propertiesLabels);
|
||||
if (!jvmPrefferred) {
|
||||
finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, jvmLabels);
|
||||
}
|
||||
if (!envPrefferred) {
|
||||
finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, envLabels);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : finalLabels.entrySet()) {
|
||||
LOGGER.info("default nacos init labels: {}={}", entry.getKey(), entry.getValue());
|
||||
}
|
||||
return finalLabels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return customName;
|
||||
}
|
||||
|
||||
private static final int DEFAULT_INITIAL_ORDER = 100;
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return DEFAULT_INITIAL_ORDER;
|
||||
}
|
||||
}
|
||||
|
@ -34,62 +34,42 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
public class DefaultLabelsCollectorManager implements LabelsCollectorManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLabelsCollectorManager.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("com.alibaba.nacos.common.labels");
|
||||
|
||||
private ArrayList<LabelsCollector> labelsCollectorsList = new ArrayList<>();
|
||||
|
||||
private Map<String, String> 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<String, String> getAllLabels() {
|
||||
for (int tryTimes = 0; tryTimes < MAX_TRY_COUNT && !isLabelsInit; tryTimes++) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
return labels;
|
||||
public DefaultLabelsCollectorManager() {
|
||||
labelsCollectorsList = loadLabelsCollectors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> refreshAllLabels(Properties properties) {
|
||||
for (int tryTimes = 0; tryTimes < MAX_TRY_COUNT && !isLabelsInit; tryTimes++) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
public Map<String, String> getLabels(Properties properties) {
|
||||
LOGGER.info("DefaultLabelsCollectorManager get labels.....");
|
||||
Map<String, String> labels = getLabels(labelsCollectorsList, properties);
|
||||
LOGGER.info("DefaultLabelsCollectorManager get labels finished,labels :{}", labels);
|
||||
return labels;
|
||||
}
|
||||
|
||||
Map<String, String> getLabels(ArrayList<LabelsCollector> labelsCollectorsList, Properties properties) {
|
||||
|
||||
if (properties == null) {
|
||||
properties = new Properties();
|
||||
}
|
||||
Map<String, String> labels = new HashMap<>(8);
|
||||
for (LabelsCollector labelsCollector : labelsCollectorsList) {
|
||||
|
||||
LOGGER.info("Process LabelsCollector with [name:{}]", labelsCollector.getName());
|
||||
for (Map.Entry<String, String> entry : labelsCollector.collectLabels(properties).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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isLabelsInit) {
|
||||
return new HashMap<>(2);
|
||||
}
|
||||
LOGGER.info("DefaultLabelsCollectorManager refresh labels.....");
|
||||
initLabels(properties);
|
||||
LOGGER.info("DefaultLabelsCollectorManager refresh labels finished,labels :{}", labels);
|
||||
return labels;
|
||||
}
|
||||
|
||||
@ -103,38 +83,6 @@ public class DefaultLabelsCollectorManager implements LabelsCollectorManager {
|
||||
return labelsCollectorsList;
|
||||
}
|
||||
|
||||
private void initLabels(Properties properties) {
|
||||
labelsCollectorsList = loadLabelsCollectors();
|
||||
this.labels = getLabels(labelsCollectorsList, properties);
|
||||
}
|
||||
|
||||
Map<String, String> getLabels(ArrayList<LabelsCollector> labelsCollectorsList, Properties properties) {
|
||||
Map<String, String> 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<String, String> 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<String, String> labels, String key, String value) {
|
||||
return null == labels.putIfAbsent(key, value);
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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<OrderedConfigGetter> 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());
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
@ -17,11 +17,9 @@
|
||||
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;
|
||||
|
||||
@ -29,9 +27,6 @@ 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.
|
||||
@ -45,8 +40,6 @@ public class RpcClientFactory {
|
||||
|
||||
private static final Map<String, RpcClient> CLIENT_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static AtomicReference<DefaultLabelsCollectorManager> defaultLabelsCollectorManager;
|
||||
|
||||
/**
|
||||
* get all client.
|
||||
*
|
||||
@ -89,18 +82,13 @@ public class RpcClientFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* create client with properties.
|
||||
*
|
||||
* @date 2024/3/7
|
||||
* @return rpc client.
|
||||
*/
|
||||
* create client with properties.
|
||||
*
|
||||
* @return rpc client.
|
||||
* @date 2024/3/7
|
||||
*/
|
||||
public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> 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);
|
||||
}
|
||||
|
||||
@ -132,22 +120,6 @@ public class RpcClientFactory {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<String, String> collectLabels(Properties properties) {
|
||||
//labels from spi
|
||||
defaultLabelsCollectorManager.compareAndSet(null, new DefaultLabelsCollectorManager(properties));
|
||||
Map<String, String> allLabels = defaultLabelsCollectorManager.get().refreshAllLabels(properties);
|
||||
allLabels = ConnLabelsUtils.addPrefixForEachKey(allLabels, APP_CONN_PREFIX);
|
||||
return allLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a rpc client.
|
||||
*
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -30,24 +30,25 @@ import java.util.Properties;
|
||||
* @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<String, String> labels = defaultLabelsCollectorManager.getAllLabels();
|
||||
Assert.assertEquals("properties_after", labels.get(Constants.GRAY));
|
||||
properties.put(Constants.APP_CONN_LABELS_KEY, "k1=v1,gray=properties_pre");
|
||||
properties.put(Constants.CONFIG_GRAY_LABEL, "properties_after");
|
||||
DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();
|
||||
Map<String, String> labels = defaultLabelsCollectorManager.getLabels(properties);
|
||||
Assert.assertEquals("properties_after", labels.get(Constants.CONFIG_GRAY_LABEL));
|
||||
Assert.assertEquals("v1", labels.get("k1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tagV2LabelsCollectorOrderTest() {
|
||||
Properties properties = new Properties();
|
||||
DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager(properties);
|
||||
Map<String, String> labels = defaultLabelsCollectorManager.getAllLabels();
|
||||
DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();
|
||||
Map<String, String> labels = defaultLabelsCollectorManager.getLabels(properties);
|
||||
String test = labels.get("test");
|
||||
Assert.assertEquals("test2", test);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package com.alibaba.nacos.common.labels.impl;
|
||||
|
||||
import com.alibaba.nacos.common.labels.LabelsCollector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@ -25,7 +27,7 @@ import java.util.Properties;
|
||||
*
|
||||
* @author rong
|
||||
*/
|
||||
public class Test1LabelsCollector extends AbstractLabelsCollector implements LabelsCollector {
|
||||
public class Test1LabelsCollector implements LabelsCollector {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -33,8 +35,10 @@ public class Test1LabelsCollector extends AbstractLabelsCollector implements Lab
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
public Map<String, String> collectLabels(Properties properties) {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put("test", getName());
|
||||
return labels;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,6 +18,8 @@ package com.alibaba.nacos.common.labels.impl;
|
||||
|
||||
import com.alibaba.nacos.common.labels.LabelsCollector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@ -25,7 +27,7 @@ import java.util.Properties;
|
||||
*
|
||||
* @author rong
|
||||
*/
|
||||
public class Test2LabelsCollector extends AbstractLabelsCollector implements LabelsCollector {
|
||||
public class Test2LabelsCollector implements LabelsCollector {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -33,8 +35,10 @@ public class Test2LabelsCollector extends AbstractLabelsCollector implements Lab
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
public Map<String, String> collectLabels(Properties properties) {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put("test", getName());
|
||||
return labels;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,18 +46,7 @@ public interface ConfigDiskService {
|
||||
* @throws IOException io exception.
|
||||
*/
|
||||
void saveBetaToDisk(String dataId, String group, String tenant, String content) throws IOException;
|
||||
|
||||
/**
|
||||
* Save batch information to disk.
|
||||
*
|
||||
* @param dataId dataId.
|
||||
* @param group group.
|
||||
* @param tenant tenant.
|
||||
* @param content content.
|
||||
* @throws IOException io exception.
|
||||
*/
|
||||
void saveBatchToDisk(String dataId, String group, String tenant, String content) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Save tag information to disk.
|
||||
*
|
||||
@ -88,15 +77,6 @@ public interface ConfigDiskService {
|
||||
*/
|
||||
void removeConfigInfo4Beta(String dataId, String group, String tenant);
|
||||
|
||||
/**
|
||||
* Deletes batch config file on disk.
|
||||
*
|
||||
* @param dataId dataId.
|
||||
* @param group group.
|
||||
* @param tenant tenant.
|
||||
*/
|
||||
void removeConfigInfo4Batch(String dataId, String group, String tenant);
|
||||
|
||||
/**
|
||||
* Deletes tag configuration files on disk.
|
||||
*
|
||||
@ -129,18 +109,6 @@ public interface ConfigDiskService {
|
||||
*/
|
||||
String getBetaContent(String dataId, String group, String tenant) throws IOException;
|
||||
|
||||
/**
|
||||
* get batch content.
|
||||
*
|
||||
* @param dataId dataId.
|
||||
* @param group group.
|
||||
* @param tenant tenant.
|
||||
* @return batch content, null if not exist.
|
||||
* @throws IOException io exception.
|
||||
*/
|
||||
String getBatchContent(String dataId, String group, String tenant) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the path of the tag cache file in server.
|
||||
*
|
||||
@ -153,18 +121,6 @@ public interface ConfigDiskService {
|
||||
*/
|
||||
String getTagContent(String dataId, String group, String tenant, String tag) throws IOException;
|
||||
|
||||
/**
|
||||
* get the md5 of config with encode.
|
||||
*
|
||||
* @param dataId dataId.
|
||||
* @param group group.
|
||||
* @param tenant tenant.
|
||||
* @param encode encode.
|
||||
* @return config md5.
|
||||
* @throws IOException io exception.
|
||||
*/
|
||||
String getLocalConfigMd5(String dataId, String group, String tenant, String encode) throws IOException;
|
||||
|
||||
/**
|
||||
* Clear all config file.
|
||||
*/
|
||||
@ -180,9 +136,4 @@ public interface ConfigDiskService {
|
||||
*/
|
||||
void clearAllTag();
|
||||
|
||||
/**
|
||||
* Clear all batch config file.
|
||||
*/
|
||||
void clearAllBatch();
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.config.server.service.dump.disk;
|
||||
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
@ -111,19 +110,6 @@ public class ConfigRawDiskService implements ConfigDiskService {
|
||||
return file;
|
||||
}
|
||||
|
||||
private static File targetBatchFile(String dataId, String group, String tenant) {
|
||||
File file = null;
|
||||
if (org.apache.commons.lang.StringUtils.isBlank(tenant)) {
|
||||
file = new File(EnvUtil.getNacosHome(), BATCH_DIR);
|
||||
} else {
|
||||
file = new File(EnvUtil.getNacosHome(), TENANT_BATCH_DIR);
|
||||
file = new File(file, tenant);
|
||||
}
|
||||
file = new File(file, group);
|
||||
file = new File(file, dataId);
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save beta information to disk.
|
||||
*/
|
||||
@ -132,14 +118,6 @@ public class ConfigRawDiskService implements ConfigDiskService {
|
||||
FileUtils.writeStringToFile(targetFile, content, ENCODE_UTF8);
|
||||
}
|
||||
|
||||
/**
|
||||
* save batch to disk.
|
||||
*/
|
||||
public void saveBatchToDisk(String dataId, String group, String tenant, String content) throws IOException {
|
||||
File targetFile = targetBatchFile(dataId, group, tenant);
|
||||
FileUtils.writeStringToFile(targetFile, content, ENCODE_UTF8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save tag information to disk.
|
||||
*/
|
||||
@ -163,13 +141,6 @@ public class ConfigRawDiskService implements ConfigDiskService {
|
||||
FileUtils.deleteQuietly(targetBetaFile(dataId, group, tenant));
|
||||
}
|
||||
|
||||
/**
|
||||
* remove config for batch.
|
||||
*/
|
||||
public void removeConfigInfo4Batch(String dataId, String group, String tenant) {
|
||||
FileUtils.deleteQuietly(targetBatchFile(dataId, group, tenant));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes tag configuration files on disk.
|
||||
*/
|
||||
@ -217,14 +188,6 @@ public class ConfigRawDiskService implements ConfigDiskService {
|
||||
}
|
||||
}
|
||||
|
||||
public String getLocalConfigMd5(String dataId, String group, String tenant, String encode) throws IOException {
|
||||
String content = getContent(dataId, group, tenant);
|
||||
if (content == null) {
|
||||
content = com.alibaba.nacos.common.utils.StringUtils.EMPTY;
|
||||
}
|
||||
return MD5Utils.md5Hex(content, encode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all config file.
|
||||
*/
|
||||
@ -280,26 +243,4 @@ public class ConfigRawDiskService implements ConfigDiskService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clear all batch.
|
||||
*/
|
||||
public void clearAllBatch() {
|
||||
File file = new File(EnvUtil.getNacosHome(), BATCH_DIR);
|
||||
if (!file.exists() || FileUtils.deleteQuietly(file)) {
|
||||
LogUtil.DEFAULT_LOG.info("clear all config-info-batch success");
|
||||
} else {
|
||||
LogUtil.DEFAULT_LOG.warn("clear all config-info-batch failed.");
|
||||
}
|
||||
File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_BATCH_DIR);
|
||||
if (!fileTenant.exists() || FileUtils.deleteQuietly(fileTenant)) {
|
||||
LogUtil.DEFAULT_LOG.info("clear all config-info-batch-tenant success.");
|
||||
} else {
|
||||
LogUtil.DEFAULT_LOG.warn("clear all config-info-batch-tenant failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getBatchContent(String dataId, String group, String tenant) throws IOException {
|
||||
File file = targetBatchFile(dataId, group, tenant);
|
||||
return file2String(file);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.dump.disk;
|
||||
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
@ -149,14 +148,6 @@ public class ConfigRocksDbDiskService implements ConfigDiskService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save batch information to disk.
|
||||
*/
|
||||
public void saveBatchToDisk(String dataId, String group, String tenant, String content) throws IOException {
|
||||
saveToDiskInner(BATCH_DIR, dataId, group, tenant, content);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save tag information to disk.
|
||||
*/
|
||||
@ -180,13 +171,6 @@ public class ConfigRocksDbDiskService implements ConfigDiskService {
|
||||
removeContentInner(BETA_DIR, dataId, group, tenant, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes batch configuration files on disk.
|
||||
*/
|
||||
public void removeConfigInfo4Batch(String dataId, String group, String tenant) {
|
||||
removeContentInner(BATCH_DIR, dataId, group, tenant, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes tag configuration files on disk.
|
||||
*/
|
||||
@ -202,7 +186,7 @@ public class ConfigRocksDbDiskService implements ConfigDiskService {
|
||||
return new String(bytes, ENCODE_UTF8);
|
||||
}
|
||||
|
||||
RocksDB initAndGetDB(String dir) throws IOException, RocksDBException {
|
||||
RocksDB initAndGetDB(String dir) throws RocksDBException {
|
||||
if (rocksDbMap.containsKey(dir)) {
|
||||
return rocksDbMap.get(dir);
|
||||
} else {
|
||||
@ -274,10 +258,6 @@ public class ConfigRocksDbDiskService implements ConfigDiskService {
|
||||
return getContentInner(BASE_DIR, dataId, group, tenant);
|
||||
}
|
||||
|
||||
public String getLocalConfigMd5(String dataId, String group, String tenant, String encode) throws IOException {
|
||||
return MD5Utils.md5Hex(getContentInner(BASE_DIR, dataId, group, tenant), encode);
|
||||
}
|
||||
|
||||
Options createOptions(String dir) {
|
||||
DBOptions dbOptions = new DBOptions();
|
||||
dbOptions.setMaxBackgroundJobs(Runtime.getRuntime().availableProcessors());
|
||||
@ -378,23 +358,4 @@ public class ConfigRocksDbDiskService implements ConfigDiskService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clear all batch.
|
||||
*/
|
||||
public void clearAllBatch() {
|
||||
try {
|
||||
if (rocksDbMap.containsKey(BATCH_DIR)) {
|
||||
rocksDbMap.get(BATCH_DIR).close();
|
||||
RocksDB.destroyDB(EnvUtil.getNacosHome() + BATCH_DIR, new Options());
|
||||
}
|
||||
deleteDirIfExist(BATCH_DIR);
|
||||
LogUtil.DEFAULT_LOG.info("clear all config-info-batch success.");
|
||||
} catch (RocksDBException e) {
|
||||
LogUtil.DEFAULT_LOG.warn("clear all config-info-batch failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBatchContent(String dataId, String group, String tenant) throws IOException {
|
||||
return getContentInner(BATCH_DIR, dataId, group, tenant);
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,6 @@ public class DumpChangeConfigWorkerTest {
|
||||
dynamicDataSourceMockedStatic.close();
|
||||
envUtilMockedStatic.close();
|
||||
ConfigDiskServiceFactory.getInstance().clearAll();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllBatch();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllBeta();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllTag();
|
||||
|
||||
|
@ -112,7 +112,6 @@ public class DumpProcessorTest {
|
||||
dynamicDataSourceMockedStatic.close();
|
||||
envUtilMockedStatic.close();
|
||||
ConfigDiskServiceFactory.getInstance().clearAll();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllBatch();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllBeta();
|
||||
ConfigDiskServiceFactory.getInstance().clearAllTag();
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.config.server.service.dump.disk;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ConfigDiskServiceFactoryTest {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
clearDiskInstance();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRawDiskInstance() {
|
||||
System.setProperty("config_disk_type", "rawdisk");
|
||||
ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();
|
||||
Assert.assertTrue(instance instanceof ConfigRawDiskService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRockDbDiskInstance() {
|
||||
System.setProperty("config_disk_type", "rocksdb");
|
||||
ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();
|
||||
Assert.assertTrue(instance instanceof ConfigRocksDbDiskService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultRawDiskInstance() {
|
||||
System.setProperty("config_disk_type", "123");
|
||||
ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();
|
||||
Assert.assertTrue(instance instanceof ConfigRawDiskService);
|
||||
}
|
||||
|
||||
private void clearDiskInstance() throws Exception {
|
||||
Field configDiskService = ConfigDiskServiceFactory.class.getDeclaredField("configDiskService");
|
||||
configDiskService.setAccessible(true);
|
||||
configDiskService.set(null, null);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user