From 92351f2813b6f65afadaccf91c05cf1774b4a069 Mon Sep 17 00:00:00 2001 From: Narziss Date: Sun, 29 Sep 2024 09:01:00 +0800 Subject: [PATCH] Optimize interface-level dynamic config --- .../bootstrap/DefaultConsumerBootstrap.java | 70 +++++++-------- .../apollo/ApolloDynamicConfigManager.java | 73 +++++++++------- .../nacos/NacosDynamicConfigManager.java | 87 ++++++++++--------- .../zk/ZookeeperDynamicConfigManager.java | 73 ++++++++-------- .../rpc/config/AbstractInterfaceConfig.java | 29 ++++++- .../sofa/rpc/dynamic/ConfigChangedEvent.java | 46 +--------- .../sofa/rpc/dynamic/DynamicConfigKeys.java | 10 ++- .../rpc/dynamic/DynamicConfigManager.java | 37 ++++++-- .../sofa/rpc/common/utils/StringUtils.java | 5 -- test/test-integration/pom.xml | 20 ++++- .../test/config/ApolloDynamicConfigTest.java | 76 ++++++++++++++++ .../test/config/NacosDynamicConfigTest.java | 72 +++++++++++++++ .../config/ZookeeperDynamicConfigTest.java | 80 +++++++++++++++++ .../sofa/rpc/test/config/base/BaseZkTest.java | 62 +++++++++++++ 14 files changed, 526 insertions(+), 214 deletions(-) create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ApolloDynamicConfigTest.java create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/NacosDynamicConfigTest.java create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ZookeeperDynamicConfigTest.java create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/base/BaseZkTest.java diff --git a/bootstrap/bootstrap-api/src/main/java/com/alipay/sofa/rpc/bootstrap/DefaultConsumerBootstrap.java b/bootstrap/bootstrap-api/src/main/java/com/alipay/sofa/rpc/bootstrap/DefaultConsumerBootstrap.java index 0c4bfc4af..9c4923243 100644 --- a/bootstrap/bootstrap-api/src/main/java/com/alipay/sofa/rpc/bootstrap/DefaultConsumerBootstrap.java +++ b/bootstrap/bootstrap-api/src/main/java/com/alipay/sofa/rpc/bootstrap/DefaultConsumerBootstrap.java @@ -20,6 +20,7 @@ import com.alipay.sofa.rpc.client.Cluster; import com.alipay.sofa.rpc.client.ClusterFactory; import com.alipay.sofa.rpc.client.ProviderGroup; +import com.alipay.sofa.rpc.common.RpcConstants; import com.alipay.sofa.rpc.common.SofaConfigs; import com.alipay.sofa.rpc.common.SofaOptions; import com.alipay.sofa.rpc.common.utils.CommonUtils; @@ -53,6 +54,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static com.alipay.sofa.rpc.common.RpcConstants.REGISTRY_PROTOCOL_DOMAIN; +import static com.alipay.sofa.common.config.SofaConfigs.getOrDefault; /** * Default consumer bootstrap. @@ -145,7 +147,8 @@ public T refer() { // build cluster cluster = ClusterFactory.getCluster(this); // build listeners - consumerConfig.setConfigListener(buildConfigListener(this)); + ConfigListener configListener = buildConfigListener(this); + consumerConfig.setConfigListener(configListener); consumerConfig.setProviderInfoListener(buildProviderInfoListener(this)); // init cluster cluster.init(); @@ -155,26 +158,23 @@ public T refer() { proxyIns = (T) ProxyFactory.buildProxy(consumerConfig.getProxy(), consumerConfig.getProxyClass(), proxyInvoker); - //启用请求级别动态配置 + //请求级别动态配置参数 final String dynamicAlias = consumerConfig.getParameter(DynamicConfigKeys.DYNAMIC_ALIAS); if (StringUtils.isNotBlank(dynamicAlias)) { final DynamicConfigManager dynamicManager = DynamicConfigManagerFactory.getDynamicManager( - consumerConfig.getAppName(), dynamicAlias); + consumerConfig.getAppName(), dynamicAlias); dynamicManager.initServiceConfiguration(consumerConfig.getInterfaceId()); } - //启用接口级别动态配置 - final String dynamicUrl = consumerConfig.getParameter(DynamicConfigKeys.DYNAMIC_URL); - if (StringUtils.isNotBlank(dynamicUrl)) { + //接口级别动态配置参数 + final String dynamicUrl = getOrDefault(DynamicConfigKeys.DYNAMIC_URL); + if ( StringUtils.isNotBlank(dynamicUrl)) { + //启用接口级别动态配置 final DynamicConfigManager dynamicManager = DynamicConfigManagerFactory.getDynamicManagerWithUrl( consumerConfig.getAppName(), dynamicUrl); - - //build listeners for dynamic config - consumerConfig.setConfigListener(buildConfigListener(this,dynamicManager)); + dynamicManager.addListener(consumerConfig.getInterfaceId(), configListener); + dynamicManager.initServiceConfiguration(consumerConfig.getInterfaceId(), configListener); } - - - } catch (Exception e) { if (cluster != null) { cluster.destroy(); @@ -214,17 +214,6 @@ protected ConfigListener buildConfigListener(ConsumerBootstrap bootstrap) { return new ConsumerAttributeListener(); } - /** - * Build ConfigListener for consumer bootstrap with dynamic config. - * - * @param bootstrap ConsumerBootstrap - * @param dynamicManager DynamicConfigManager - * @return ConfigListener - */ - protected ConfigListener buildConfigListener(ConsumerBootstrap bootstrap, DynamicConfigManager dynamicManager) { - return new ConsumerAttributeListener(dynamicManager); - } - /** * Build ProviderInfoListener for consumer bootstrap. * @@ -463,28 +452,20 @@ private class ConsumerAttributeListener implements ConfigListener { private Map newValueMap = new HashMap<>(); - ConsumerAttributeListener() { + // 动态配置项 + private List dynamicConfigKeys = Arrays.asList(RpcConstants.CONFIG_KEY_TIMEOUT, + RpcConstants.CONFIG_KEY_RETRIES, RpcConstants.CONFIG_KEY_LOADBALANCER); - } - - ConsumerAttributeListener(DynamicConfigManager dynamicManager) { - this.initWith(consumerConfig.getInterfaceId(),dynamicManager); - } + ConsumerAttributeListener() { - public void initWith(String key, DynamicConfigManager dynamicManager) { - dynamicManager.addListener(key, this); - // 初始化配置值 - String rawConfig = dynamicManager.getConfig(key); - if (!StringUtils.isEmpty(rawConfig)) { - process(new ConfigChangedEvent(key, "sofa-rpc",rawConfig)); - } } @Override - public void process(ConfigChangedEvent event){ - if (event.getChangeType().equals(ConfigChangeType.DELETED)) { - newValueMap = null; - } else { + public void process(ConfigChangedEvent event) { + for (String key : newValueMap.keySet()) { + newValueMap.put(key, ""); + } + if (!event.getChangeType().equals(ConfigChangeType.DELETED)) { // ADDED or MODIFIED String[] lines = event.getContent().split("\n"); for (String line : lines) { @@ -492,7 +473,14 @@ public void process(ConfigChangedEvent event){ if (keyValue.length == 2) { String key = keyValue[0].trim(); String value = keyValue[1].trim(); - newValueMap.put(key, value); + for (String dynamicConfigKey : dynamicConfigKeys) { + if (key.equals(dynamicConfigKey) || key.endsWith("." + dynamicConfigKey)) { + newValueMap.put(key, value); + break; + } + } + } else { + LOGGER.warn("Malformed configuration line: {}", line); } } } diff --git a/config/config-apollo/src/main/java/com/alipay/sofa/rpc/dynamic/apollo/ApolloDynamicConfigManager.java b/config/config-apollo/src/main/java/com/alipay/sofa/rpc/dynamic/apollo/ApolloDynamicConfigManager.java index e8394b8f8..f36a23d1c 100644 --- a/config/config-apollo/src/main/java/com/alipay/sofa/rpc/dynamic/apollo/ApolloDynamicConfigManager.java +++ b/config/config-apollo/src/main/java/com/alipay/sofa/rpc/dynamic/apollo/ApolloDynamicConfigManager.java @@ -18,11 +18,10 @@ import com.alipay.sofa.common.config.SofaConfigs; import com.alipay.sofa.rpc.auth.AuthRuleGroup; +import com.alipay.sofa.rpc.common.utils.StringUtils; import com.alipay.sofa.rpc.dynamic.*; import com.alipay.sofa.rpc.ext.Extension; import com.alipay.sofa.rpc.listener.ConfigListener; -import com.alipay.sofa.rpc.log.Logger; -import com.alipay.sofa.rpc.log.LoggerFactory; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.ConfigService; @@ -45,12 +44,12 @@ @Extension(value = "apollo", override = true) public class ApolloDynamicConfigManager extends DynamicConfigManager { - Logger LOGGER = LoggerFactory.getLogger(ApolloDynamicConfigManager.class); - private static final String APOLLO_APPID_KEY = "app.id"; private static final String APOLLO_ADDR_KEY = "apollo.meta"; + private static final String APOLLO_CLUSTER_KEY = "apollo.cluster"; + private static final String APOLLO_PROTOCOL_PREFIX = "http://"; private Config config; @@ -58,47 +57,70 @@ public class ApolloDynamicConfigManager extends DynamicConfigManager { private final ConcurrentMap watchListenerMap = new ConcurrentHashMap<>(); protected ApolloDynamicConfigManager(String appName) { - super(appName); - System.setProperty(APOLLO_APPID_KEY, appName); - System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + SofaConfigs.getOrDefault(DynamicConfigKeys.APOLLO_ADDRESS)); - config = ConfigService.getConfig(DynamicConfigKeys.DEFAULT_GROUP); + super(appName, SofaConfigs.getOrCustomDefault(DynamicConfigKeys.APOLLO_ADDRESS,"")); + if (StringUtils.isNotBlank(appName)) { + System.setProperty(APOLLO_APPID_KEY, appName); + } + if (StringUtils.isNotBlank(getAddress())) { + System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + getAddress()); + } + config = ConfigService.getAppConfig(); } - protected ApolloDynamicConfigManager(String appName,String address) { - super(appName); + protected ApolloDynamicConfigManager(String appName, String remainUrl) { + super(appName, remainUrl); System.setProperty(APOLLO_APPID_KEY, appName); - System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + address); - config = ConfigService.getConfig(DynamicConfigKeys.DEFAULT_GROUP); + System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + getAddress()); + String params[] = getParams(); + if (params!= null && params.length > 0){ + for (String param : params) { + String[] keyValue = param.split("="); + if (keyValue.length == 2) { + if ("cluster".equals(keyValue[0])) { + System.setProperty(APOLLO_CLUSTER_KEY, keyValue[1]); + } + } + } + } + config = ConfigService.getAppConfig(); } @Override public void initServiceConfiguration(String service) { - //TODO not now + // TODO 暂不支持 + } + + @Override + public void initServiceConfiguration(String service, ConfigListener listener) { + String rawConfig = config.getProperty(service, ""); + if (StringUtils.isNotBlank(rawConfig)) { + listener.process(new ConfigChangedEvent(service, rawConfig)); + } } @Override public String getProviderServiceProperty(String service, String key) { return config.getProperty(DynamicConfigKeyHelper.buildProviderServiceProKey(service, key), - DynamicHelper.DEFAULT_DYNAMIC_VALUE); + DynamicHelper.DEFAULT_DYNAMIC_VALUE); } @Override public String getConsumerServiceProperty(String service, String key) { return config.getProperty(DynamicConfigKeyHelper.buildConsumerServiceProKey(service, key), - DynamicHelper.DEFAULT_DYNAMIC_VALUE); + DynamicHelper.DEFAULT_DYNAMIC_VALUE); } @Override public String getProviderMethodProperty(String service, String method, String key) { return config.getProperty(DynamicConfigKeyHelper.buildProviderMethodProKey(service, method, key), - DynamicHelper.DEFAULT_DYNAMIC_VALUE); + DynamicHelper.DEFAULT_DYNAMIC_VALUE); } @Override public String getConsumerMethodProperty(String service, String method, String key) { return config.getProperty(DynamicConfigKeyHelper.buildConsumerMethodProKey(service, method, key), - DynamicHelper.DEFAULT_DYNAMIC_VALUE); + DynamicHelper.DEFAULT_DYNAMIC_VALUE); } @@ -109,12 +131,7 @@ public AuthRuleGroup getServiceAuthRule(String service) { } @Override - public String getConfig(String key){ - return config.getProperty(key, DynamicHelper.DEFAULT_DYNAMIC_VALUE); - } - - @Override - public void addListener(String key, ConfigListener listener){ + public void addListener(String key, ConfigListener listener) { ApolloListener apolloListener = watchListenerMap.computeIfAbsent(key, k -> new ApolloListener()); apolloListener.addListener(listener); config.addChangeListener(apolloListener, Collections.singleton(key)); @@ -124,19 +141,15 @@ public class ApolloListener implements ConfigChangeListener { private Set listeners = new CopyOnWriteArraySet<>(); - ApolloListener() {} + ApolloListener() { + } @Override public void onChange(com.ctrip.framework.apollo.model.ConfigChangeEvent changeEvent) { for (String key : changeEvent.changedKeys()) { ConfigChange change = changeEvent.getChange(key); - if ("".equals(change.getNewValue())) { - LOGGER.info("an empty rule is received for key: " + key); - return; - } - ConfigChangedEvent event = - new ConfigChangedEvent(key, change.getNamespace(), change.getNewValue(), getChangeType(change)); + new ConfigChangedEvent(key, change.getNewValue(), getChangeType(change)); listeners.forEach(listener -> listener.process(event)); } } diff --git a/config/config-nacos/src/main/java/com/alipay/sofa/rpc/dynamic/nacos/NacosDynamicConfigManager.java b/config/config-nacos/src/main/java/com/alipay/sofa/rpc/dynamic/nacos/NacosDynamicConfigManager.java index dd58d1bd6..fc6e92ca8 100644 --- a/config/config-nacos/src/main/java/com/alipay/sofa/rpc/dynamic/nacos/NacosDynamicConfigManager.java +++ b/config/config-nacos/src/main/java/com/alipay/sofa/rpc/dynamic/nacos/NacosDynamicConfigManager.java @@ -38,8 +38,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executor; -import static com.alipay.sofa.rpc.common.utils.StringUtils.KEY_SEPARATOR; - /** * @author Narziss * @version NaocsDynamicConfigManager.java, v 0.1 2024年07月26日 09:37 Narziss @@ -48,39 +46,47 @@ @Extension(value = "nacos", override = true) public class NacosDynamicConfigManager extends DynamicConfigManager { - private final static Logger LOGGER = LoggerFactory.getLogger(NacosDynamicConfigManager.class); - - private static final long DEFAULT_TIMEOUT = 5000; + private final static Logger LOGGER = LoggerFactory.getLogger(NacosDynamicConfigManager.class); - private final String address; + private static final long DEFAULT_TIMEOUT = 5000; - private ConfigService configService; + private final String group; - private Properties nacosConfig = new Properties(); + private final ConcurrentMap watchListenerMap = new ConcurrentHashMap<>(); - private final String group; + private ConfigService configService; - private final ConcurrentMap watchListenerMap = new ConcurrentHashMap<>(); + private Properties nacosConfig = new Properties(); protected NacosDynamicConfigManager(String appName) { - super(appName); - address=SofaConfigs.getOrDefault(DynamicConfigKeys.NACOS_ADDRESS); - group = DynamicConfigKeys.DEFAULT_GROUP; + super(appName, SofaConfigs.getOrDefault(DynamicConfigKeys.NACOS_ADDRESS)); + group = appName; + nacosConfig.put(PropertyKeyConst.SERVER_ADDR, getAddress()); try { - nacosConfig.put(PropertyKeyConst.SERVER_ADDR, address); configService = ConfigFactory.createConfigService(nacosConfig); - } catch (NacosException e) { LOGGER.error("Failed to create ConfigService", e); } } - protected NacosDynamicConfigManager(String appName, String address) { - super(appName); - this.address = address; - group = DynamicConfigKeys.DEFAULT_GROUP; + protected NacosDynamicConfigManager(String appName, String remainUrl) { + super(appName, remainUrl); + group = appName; + nacosConfig.put(PropertyKeyConst.SERVER_ADDR, getAddress()); + String params[] = getParams(); + if (params != null && params.length > 0) { + for (String param : params) { + String[] keyValue = param.split("="); + if (keyValue.length == 2) { + if ("username".equals(keyValue[0])) { + nacosConfig.put(PropertyKeyConst.USERNAME, keyValue[1]); + } else if ("password".equals(keyValue[0])) { + nacosConfig.put(PropertyKeyConst.PASSWORD, keyValue[1]); + } + } + } + } try { - nacosConfig.put(PropertyKeyConst.SERVER_ADDR, address); configService = ConfigFactory.createConfigService(nacosConfig); } catch (NacosException e) { @@ -90,15 +96,26 @@ protected NacosDynamicConfigManager(String appName, String address) { @Override public void initServiceConfiguration(String service) { - //TODO not now + // TODO 暂不支持 + } + @Override + public void initServiceConfiguration(String service, ConfigListener listener) { + try { + String rawConfig = configService.getConfig(service, group, DEFAULT_TIMEOUT); + if (!StringUtils.isEmpty(rawConfig)) { + listener.process(new ConfigChangedEvent(service, rawConfig)); + } + } catch (NacosException e) { + LOGGER.error("Failed to getConfig for key:{}, group:{}", service, group, e); + } } @Override public String getProviderServiceProperty(String service, String key) { try { String configValue = configService.getConfig( - DynamicConfigKeyHelper.buildProviderServiceProKey(service, key), + DynamicConfigKeyHelper.buildProviderServiceProKey(service, key), group, DEFAULT_TIMEOUT); return configValue != null ? configValue : DynamicHelper.DEFAULT_DYNAMIC_VALUE; } catch (NacosException e) { @@ -110,7 +127,7 @@ public String getProviderServiceProperty(String service, String key) { public String getConsumerServiceProperty(String service, String key) { try { String configValue = configService.getConfig( - DynamicConfigKeyHelper.buildConsumerServiceProKey(service, key), + DynamicConfigKeyHelper.buildConsumerServiceProKey(service, key), group, DEFAULT_TIMEOUT); return configValue != null ? configValue : DynamicHelper.DEFAULT_DYNAMIC_VALUE; } catch (NacosException e) { @@ -122,7 +139,7 @@ public String getConsumerServiceProperty(String service, String key) { public String getProviderMethodProperty(String service, String method, String key) { try { String configValue = configService.getConfig( - DynamicConfigKeyHelper.buildProviderMethodProKey(service, method, key), + DynamicConfigKeyHelper.buildProviderMethodProKey(service, method, key), group, DEFAULT_TIMEOUT); return configValue != null ? configValue : DynamicHelper.DEFAULT_DYNAMIC_VALUE; } catch (NacosException e) { @@ -134,7 +151,7 @@ public String getProviderMethodProperty(String service, String method, String ke public String getConsumerMethodProperty(String service, String method, String key) { try { String configValue = configService.getConfig( - buildDataId(DynamicConfigKeyHelper.buildConsumerMethodProKey(service, method, key)), + DynamicConfigKeyHelper.buildConsumerMethodProKey(service, method, key), group, DEFAULT_TIMEOUT); return configValue != null ? configValue : DynamicHelper.DEFAULT_DYNAMIC_VALUE; } catch (NacosException e) { @@ -142,33 +159,19 @@ public String getConsumerMethodProperty(String service, String method, String ke } } - public String buildDataId(String proKey) { - return getAppName() + KEY_SEPARATOR + proKey; - } - @Override public AuthRuleGroup getServiceAuthRule(String service) { //TODO 暂不支持 return null; } - @Override - public String getConfig(String key){ - try { - return configService.getConfig(getAppName()+ KEY_SEPARATOR +key, group, DEFAULT_TIMEOUT); - } catch (NacosException e) { - LOGGER.error("Failed to getConfig for key:{}, group:{}", key, group, e); - return DynamicHelper.DEFAULT_DYNAMIC_VALUE; - } - } - @Override public void addListener(String key, ConfigListener listener) { NacosConfigListener nacosConfigListener = watchListenerMap.computeIfAbsent( key, k -> createTargetListener(key)); nacosConfigListener.addListener(listener); try { - configService.addListener(getAppName()+KEY_SEPARATOR +key, group, nacosConfigListener); + configService.addListener(key, group, nacosConfigListener); } catch (NacosException e) { LOGGER.error("Failed to add listener for key:{}, group:{}", key, group, e); } @@ -194,7 +197,7 @@ public Executor getExecutor() { } /** - * receive + * receive config change event * * @param dataId data ID * @param group group @@ -204,7 +207,7 @@ public Executor getExecutor() { public void innerReceive(String dataId, String group, String configInfo) { String oldValue = cacheData.get(dataId); ConfigChangedEvent event = - new ConfigChangedEvent(dataId, group, configInfo, getChangeType(configInfo, oldValue)); + new ConfigChangedEvent(dataId, configInfo, getChangeType(configInfo, oldValue)); if (configInfo == null) { cacheData.remove(dataId); } else { diff --git a/config/config-zk/src/main/java/com/alipay/sofa/rpc/dynamic/zk/ZookeeperDynamicConfigManager.java b/config/config-zk/src/main/java/com/alipay/sofa/rpc/dynamic/zk/ZookeeperDynamicConfigManager.java index 47dadc444..773c8e7f3 100644 --- a/config/config-zk/src/main/java/com/alipay/sofa/rpc/dynamic/zk/ZookeeperDynamicConfigManager.java +++ b/config/config-zk/src/main/java/com/alipay/sofa/rpc/dynamic/zk/ZookeeperDynamicConfigManager.java @@ -19,6 +19,7 @@ import com.alipay.sofa.common.config.SofaConfigs; import com.alipay.sofa.rpc.auth.AuthRuleGroup; import com.alipay.sofa.rpc.common.RpcConstants; +import com.alipay.sofa.rpc.common.utils.StringUtils; import com.alipay.sofa.rpc.dynamic.*; import com.alipay.sofa.rpc.ext.Extension; import com.alipay.sofa.rpc.listener.ConfigListener; @@ -35,7 +36,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import static com.alipay.sofa.rpc.common.utils.StringUtils.CONTEXT_SEP; -import static com.alipay.sofa.rpc.common.utils.StringUtils.KEY_SEPARATOR; /** * @author Narziss @@ -45,27 +45,23 @@ @Extension(value = "zookeeper", override = true) public class ZookeeperDynamicConfigManager extends DynamicConfigManager { - private final static Logger LOGGER = LoggerFactory - .getLogger(ZookeeperDynamicConfigManager.class); + private final static Logger LOGGER = LoggerFactory + .getLogger(ZookeeperDynamicConfigManager.class); - private final CuratorFramework zkClient; - - private final String address; - - private final String rootPath; - private ConcurrentMap configMap = new ConcurrentHashMap<>(); + private final CuratorFramework zkClient; + private final String rootPath; private final ConcurrentMap watchListenerMap = new ConcurrentHashMap<>(); + private ConcurrentMap configMap = new ConcurrentHashMap<>(); protected ZookeeperDynamicConfigManager(String appName) { - super(appName); - rootPath = CONTEXT_SEP + DynamicConfigKeys.CONFIG_NODE + CONTEXT_SEP + DynamicConfigKeys.DEFAULT_GROUP + CONTEXT_SEP + getAppName(); - address = SofaConfigs.getOrDefault(DynamicConfigKeys.ZK_ADDRESS); + super(appName, SofaConfigs.getOrDefault(DynamicConfigKeys.ZK_ADDRESS)); + rootPath = CONTEXT_SEP + DynamicConfigKeys.CONFIG_NODE + CONTEXT_SEP + appName; zkClient = CuratorFrameworkFactory.builder() - .connectString(address) - .retryPolicy(new ExponentialBackoffRetry(1000, 3)) - .namespace(DynamicConfigKeys.DEFAULT_NAMESPACE) - .build(); + .connectString(getAddress()) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)) + .namespace(DynamicConfigKeys.DEFAULT_NAMESPACE) + .build(); zkClient.start(); PathChildrenCache cache = new PathChildrenCache(zkClient, rootPath, true); @@ -97,12 +93,11 @@ public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) th } } - protected ZookeeperDynamicConfigManager(String appName,String address) { - super(appName); - rootPath = CONTEXT_SEP + DynamicConfigKeys.CONFIG_NODE + CONTEXT_SEP + DynamicConfigKeys.DEFAULT_GROUP; - this.address = address; + protected ZookeeperDynamicConfigManager(String appName, String remainUrl) { + super(appName, remainUrl); + rootPath = CONTEXT_SEP + DynamicConfigKeys.CONFIG_NODE + CONTEXT_SEP + appName; zkClient = CuratorFrameworkFactory.builder() - .connectString(address) + .connectString(getAddress()) .retryPolicy(new ExponentialBackoffRetry(1000, 3)) .namespace(DynamicConfigKeys.DEFAULT_NAMESPACE) .build(); @@ -111,7 +106,23 @@ protected ZookeeperDynamicConfigManager(String appName,String address) { @Override public void initServiceConfiguration(String service) { - //TODO not now + // TODO 暂不支持 + } + + @Override + public void initServiceConfiguration(String service, ConfigListener listener) { + try { + String path = rootPath + CONTEXT_SEP + service; + if (zkClient.checkExists().forPath(path) != null) { + byte[] bytes = zkClient.getData().forPath(rootPath + CONTEXT_SEP + service); + String rawConfig = new String(bytes, RpcConstants.DEFAULT_CHARSET); + if (!StringUtils.isEmpty(rawConfig)) { + listener.process(new ConfigChangedEvent(service, rawConfig)); + } + } + } catch (Exception e) { + LOGGER.error("Failed to init service configuration for service: " + service, e); + } } @@ -163,19 +174,8 @@ public AuthRuleGroup getServiceAuthRule(String service) { } @Override - public String getConfig(String key){ - try { - byte[] bytes = zkClient.getData().forPath(rootPath+ CONTEXT_SEP +getAppName()+ KEY_SEPARATOR + key); - String configValue = new String(bytes, RpcConstants.DEFAULT_CHARSET); - return configValue != null ? configValue : DynamicHelper.DEFAULT_DYNAMIC_VALUE; - } catch (Exception e) { - return DynamicHelper.DEFAULT_DYNAMIC_VALUE; - } - } - - @Override - public void addListener(String key, ConfigListener listener){ - String pathKey = rootPath+ CONTEXT_SEP +getAppName()+ KEY_SEPARATOR + key; + public void addListener(String key, ConfigListener listener) { + String pathKey = rootPath + CONTEXT_SEP + key; ZookeeperConfigListener zookeeperConfigListener = watchListenerMap.computeIfAbsent( key, k -> createTargetListener(pathKey)); @@ -224,12 +224,11 @@ public void nodeChanged() throws Exception { content = new String(childData.getData(), RpcConstants.DEFAULT_CHARSET); changeType = ConfigChangeType.MODIFIED; } - ConfigChangedEvent configChangeEvent = new ConfigChangedEvent(pathKey, DynamicConfigKeys.DEFAULT_GROUP, (String) content, changeType); + ConfigChangedEvent configChangeEvent = new ConfigChangedEvent(pathKey, (String) content, changeType); listeners.forEach(listener -> listener.process(configChangeEvent)); } } - } \ No newline at end of file diff --git a/core/api/src/main/java/com/alipay/sofa/rpc/config/AbstractInterfaceConfig.java b/core/api/src/main/java/com/alipay/sofa/rpc/config/AbstractInterfaceConfig.java index acc4a74e1..8966c6a7e 100644 --- a/core/api/src/main/java/com/alipay/sofa/rpc/config/AbstractInterfaceConfig.java +++ b/core/api/src/main/java/com/alipay/sofa/rpc/config/AbstractInterfaceConfig.java @@ -215,6 +215,11 @@ public abstract class AbstractInterfaceConfig configValueCache = null; + /** + * 动态配置的方法名称和方法参数配置的map + */ + protected transient volatile Map dynamicConfigValueCache = new ConcurrentHashMap<>(); + /** * 代理接口类,和T对应,主要针对泛化调用 */ @@ -924,6 +929,10 @@ public String queryAttribute(String property) { public boolean updateAttribute(String property, String newValueStr, boolean overwrite) { try { boolean changed = false; + if(StringUtils.isBlank(newValueStr)){ + // 改为默认值 + newValueStr = configValueCache.get(property) == null ? null : configValueCache.get(property).toString(); + } if (property.charAt(0) == RpcConstants.HIDE_KEY_PREFIX) { // 方法级配置 例如.echoStr.timeout String methodAndP = property.substring(1); @@ -940,6 +949,7 @@ public boolean updateAttribute(String property, String newValueStr, boolean over // 拿到旧的值 Object oldValue = null; Object newValue = CompatibleTypeUtils.convert(newValueStr, propertyClazz); + if (methodConfig == null) { methodConfig = new MethodConfig(); methodConfig.setName(methodName); @@ -960,6 +970,11 @@ public boolean updateAttribute(String property, String newValueStr, boolean over } if (changed && overwrite) { BeanUtils.setProperty(methodConfig, methodProperty, propertyClazz, newValue);// 覆盖属性 + if (newValue != null){ + dynamicConfigValueCache.put(property, newValue); + } else { + dynamicConfigValueCache.remove(property); + } if (LOGGER.isInfoEnabled()) { LOGGER.info("Property \"" + methodName + "." + methodProperty + "\" changed from {} to {}", oldValue, newValueStr); @@ -1016,11 +1031,17 @@ public Object getMethodConfigValue(String methodName, String configKey, Object d * @return 配置值 method config value */ public Object getMethodConfigValue(String methodName, String configKey) { - if (configValueCache == null) { - return null; - } String key = buildmkey(methodName, configKey); - return configValueCache.get(key); + Object value = null; + if (dynamicConfigValueCache != null) { + value = dynamicConfigValueCache.get(key); + } + if (value == null) { + if (configValueCache != null) { + value = configValueCache.get(key); + } + } + return value; } /** diff --git a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/ConfigChangedEvent.java b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/ConfigChangedEvent.java index 2dc006610..77d2d06f6 100644 --- a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/ConfigChangedEvent.java +++ b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/ConfigChangedEvent.java @@ -17,7 +17,6 @@ package com.alipay.sofa.rpc.dynamic; import java.util.EventObject; -import java.util.Objects; /** * @author Narziss @@ -28,20 +27,17 @@ public class ConfigChangedEvent extends EventObject { private final String key; - private final String group; - private final String content; private final ConfigChangeType changeType; - public ConfigChangedEvent(String key, String group, String content) { - this(key, group, content, ConfigChangeType.MODIFIED); + public ConfigChangedEvent(String key, String content) { + this(key, content, ConfigChangeType.MODIFIED); } - public ConfigChangedEvent(String key, String group, String content, ConfigChangeType changeType) { - super(key + "," + group); + public ConfigChangedEvent(String key, String content, ConfigChangeType changeType) { + super(key); this.key = key; - this.group = group; this.content = content; this.changeType = changeType; } @@ -50,10 +46,6 @@ public String getKey() { return key; } - public String getGroup() { - return group; - } - public String getContent() { return content; } @@ -61,34 +53,4 @@ public String getContent() { public ConfigChangeType getChangeType() { return changeType; } - - @Override - public String toString() { - return "ConfigChangedEvent{" + "key='" - + key + '\'' + ", group='" - + group + '\'' + ", content='" - + content + '\'' + ", changeType=" - + changeType + "} " - + super.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ConfigChangedEvent)) { - return false; - } - ConfigChangedEvent that = (ConfigChangedEvent) o; - return Objects.equals(getKey(), that.getKey()) - && Objects.equals(getGroup(), that.getGroup()) - && Objects.equals(getContent(), that.getContent()) - && getChangeType() == that.getChangeType(); - } - - @Override - public int hashCode() { - return Objects.hash(getKey(), getGroup(), getContent(), getChangeType()); - } } diff --git a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigKeys.java b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigKeys.java index d7929b689..581c7c55e 100644 --- a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigKeys.java +++ b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigKeys.java @@ -25,13 +25,17 @@ public class DynamicConfigKeys { public static final String DYNAMIC_ALIAS = "dynamicAlias"; - public static final String DYNAMIC_URL = "dynamicUrl"; - public static final String CONFIG_NODE = "config"; public static final String DEFAULT_NAMESPACE = "sofa-rpc"; - public static final String DEFAULT_GROUP = "sofa-rpc"; + public static ConfigKey DYNAMIC_URL = ConfigKey + .build( + "dynamicUrl", + " ", + false, + "The url of the dynamic configuration.", + new String[] { "dynamicUrl" }); public static ConfigKey ZK_ADDRESS = ConfigKey .build( diff --git a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigManager.java b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigManager.java index 72f879fcd..7fda9f36d 100644 --- a/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigManager.java +++ b/core/api/src/main/java/com/alipay/sofa/rpc/dynamic/DynamicConfigManager.java @@ -30,14 +30,32 @@ public abstract class DynamicConfigManager { private String appName; - protected DynamicConfigManager(String appName) { + private String address; + + private String params[]; + + protected DynamicConfigManager(String appName, String remainUrl) { this.appName = appName; + int queryIndex = remainUrl.indexOf("?"); + this.address = (queryIndex > -1) ? remainUrl.substring(0, queryIndex) : remainUrl; + if (queryIndex > -1 && queryIndex < remainUrl.length() - 1) { + String query = remainUrl.substring(queryIndex + 1); + this.params = query.split("&"); + } } protected String getAppName() { return appName; } + protected String getAddress() { + return address; + } + + protected String[] getParams() { + return params; + } + /** * Init service's governance related configuration. * Such as auth rules、lb rules @@ -46,6 +64,15 @@ protected String getAppName() { */ public abstract void initServiceConfiguration(String service); + /** + * Init service's governance related configuration. + * Such as auth rules、lb rules + * + * @param service target service + * @param listener config listener + */ + public abstract void initServiceConfiguration(String service, ConfigListener listener); + /** * Get provider service related property. * @@ -100,12 +127,4 @@ protected String getAppName() { */ public abstract void addListener(String key, ConfigListener listener); - /** - * Get config value by key. - * - * @param key config key - * @return config value - */ - public abstract String getConfig(String key); - } \ No newline at end of file diff --git a/core/common/src/main/java/com/alipay/sofa/rpc/common/utils/StringUtils.java b/core/common/src/main/java/com/alipay/sofa/rpc/common/utils/StringUtils.java index 97bda388b..77febb203 100644 --- a/core/common/src/main/java/com/alipay/sofa/rpc/common/utils/StringUtils.java +++ b/core/common/src/main/java/com/alipay/sofa/rpc/common/utils/StringUtils.java @@ -39,11 +39,6 @@ public class StringUtils { */ public static final String CONTEXT_SEP = "/"; - /** - * The config key separator String {@code ":"} - */ - public static final String KEY_SEPARATOR = ":"; - /** * The string {@code "*"}. * diff --git a/test/test-integration/pom.xml b/test/test-integration/pom.xml index 5d78a8e48..84e669099 100644 --- a/test/test-integration/pom.xml +++ b/test/test-integration/pom.xml @@ -206,7 +206,7 @@ com.alipay.sofa - sofa-rpc-config-apollo + sofa-rpc-config-nacos ${project.parent.version} test @@ -273,6 +273,24 @@ junit test + + com.alipay.sofa + sofa-rpc-config-apollo + 5.13.1-SNAPSHOT + test + + + com.alipay.sofa + sofa-rpc-config-zk + 5.13.1-SNAPSHOT + test + + + org.apache.curator + curator-test + 4.3.0 + test + diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ApolloDynamicConfigTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ApolloDynamicConfigTest.java new file mode 100644 index 000000000..f72a5c362 --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ApolloDynamicConfigTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test.config; + +import com.alipay.sofa.rpc.config.ApplicationConfig; +import com.alipay.sofa.rpc.config.ConsumerConfig; +import com.alipay.sofa.rpc.dynamic.DynamicConfigKeys; +import com.alipay.sofa.rpc.dynamic.DynamicConfigManager; +import com.alipay.sofa.rpc.dynamic.DynamicConfigManagerFactory; +import com.alipay.sofa.rpc.dynamic.apollo.ApolloDynamicConfigManager; +import com.alipay.sofa.rpc.test.HelloService; +import com.ctrip.framework.apollo.enums.PropertyChangeType; +import com.ctrip.framework.apollo.model.ConfigChange; +import com.ctrip.framework.apollo.model.ConfigChangeEvent; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Narziss + * @version ApolloDynamicConfigTest.java, v 0.1 2024年09月28日 10:46 Narziss + */ +public class ApolloDynamicConfigTest { + + @Test + public void testApolloDynamicConfig() throws Exception { + System.setProperty(DynamicConfigKeys.DYNAMIC_URL.getKey(), "apollo://127.0.0.1:8080"); + ApplicationConfig clientApplication = new ApplicationConfig(); + clientApplication.setAppName("demo"); + + ConsumerConfig consumerConfig = new ConsumerConfig() + .setInterfaceId(HelloService.class.getName()) + .setProtocol("bolt") + .setDirectUrl("bolt://127.0.0.1:12200") + .setConnectTimeout(10 * 1000) + .setApplication(clientApplication); + + consumerConfig.refer(); + + // 获取接口对应的动态配置监听器 + DynamicConfigManager dynamicConfigManager = DynamicConfigManagerFactory.getDynamicManagerWithUrl + (clientApplication.getAppName(), System.getProperty(DynamicConfigKeys.DYNAMIC_URL.getKey())); + Field field = ApolloDynamicConfigManager.class.getDeclaredField("watchListenerMap"); + field.setAccessible(true); + Map watchListenerMap = (Map) field + .get(dynamicConfigManager); + ApolloDynamicConfigManager.ApolloListener apolloConfigListener = watchListenerMap.get(consumerConfig + .getInterfaceId()); + + // 测试配置更新 + String configValue = "timeout=5000\n.sayHello.timeout=6000"; + ConfigChange configChange = new ConfigChange("application", consumerConfig.getInterfaceId(), null, configValue, PropertyChangeType.ADDED); + Map changes= new HashMap<>(); + changes.put(configChange.getPropertyName(), configChange); + ConfigChangeEvent event = new ConfigChangeEvent("application",changes); + apolloConfigListener.onChange(event); + Assert.assertEquals(6000, consumerConfig.getMethodTimeout("sayHello")); + } +} diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/NacosDynamicConfigTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/NacosDynamicConfigTest.java new file mode 100644 index 000000000..a95ee2a39 --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/NacosDynamicConfigTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test.config; + +import com.alipay.sofa.rpc.config.ApplicationConfig; +import com.alipay.sofa.rpc.config.ConsumerConfig; +import com.alipay.sofa.rpc.dynamic.DynamicConfigKeys; +import com.alipay.sofa.rpc.dynamic.DynamicConfigManager; + +import com.alipay.sofa.rpc.dynamic.DynamicConfigManagerFactory; +import com.alipay.sofa.rpc.dynamic.nacos.NacosDynamicConfigManager; +import com.alipay.sofa.rpc.test.HelloService; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.util.Map; + +/** + * @author Narziss + * @version NacosDynamicConfigTest.java, v 0.1 2024年09月28日 12:11 Narziss + */ +public class NacosDynamicConfigTest { + + @Test + public void testNacosDynamicConfig() throws Exception { + System.setProperty(DynamicConfigKeys.DYNAMIC_URL.getKey(), "nacos://127.0.0.1:8848"); + ApplicationConfig clientApplication = new ApplicationConfig(); + clientApplication.setAppName("demo"); + + ConsumerConfig consumerConfig = new ConsumerConfig() + .setInterfaceId(HelloService.class.getName()) + .setProtocol("bolt") + .setDirectUrl("bolt://127.0.0.1:12200") + .setConnectTimeout(10 * 1000) + .setApplication(clientApplication); + + consumerConfig.refer(); + + // 获取接口对应的动态配置监听器 + DynamicConfigManager dynamicConfigManager = DynamicConfigManagerFactory.getDynamicManagerWithUrl + (clientApplication.getAppName(), System.getProperty(DynamicConfigKeys.DYNAMIC_URL.getKey())); + Field field = NacosDynamicConfigManager.class.getDeclaredField("watchListenerMap"); + field.setAccessible(true); + Map watchListenerMap = (Map) field + .get(dynamicConfigManager); + NacosDynamicConfigManager.NacosConfigListener nacosConfigListener = watchListenerMap.get(consumerConfig + .getInterfaceId()); + + // 测试配置更新 + String configValue = "timeout=5000"; + nacosConfigListener.innerReceive(consumerConfig.getInterfaceId(), consumerConfig.getAppName(), configValue); + Assert.assertEquals(5000, consumerConfig.getMethodTimeout("sayHello")); + configValue = "timeout=5000\n.sayHello.timeout=6000"; + nacosConfigListener.innerReceive(consumerConfig.getInterfaceId(), consumerConfig.getAppName(), configValue); + Assert.assertEquals(6000, consumerConfig.getMethodTimeout("sayHello")); + } +} diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ZookeeperDynamicConfigTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ZookeeperDynamicConfigTest.java new file mode 100644 index 000000000..224b1489f --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/ZookeeperDynamicConfigTest.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test.config; + +import com.alipay.sofa.rpc.config.ApplicationConfig; +import com.alipay.sofa.rpc.config.ConsumerConfig; +import com.alipay.sofa.rpc.dynamic.DynamicConfigKeys; +import com.alipay.sofa.rpc.dynamic.DynamicConfigManager; +import com.alipay.sofa.rpc.dynamic.DynamicConfigManagerFactory; +import com.alipay.sofa.rpc.dynamic.zk.ZookeeperDynamicConfigManager; +import com.alipay.sofa.rpc.test.HelloService; +import com.alipay.sofa.rpc.test.config.base.BaseZkTest; +import org.apache.curator.framework.CuratorFramework; +import org.apache.zookeeper.CreateMode; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; + +/** + * @author Narziss + * @version ZookeeperDynamicConfigTest.java, v 0.1 2024年09月28日 14:33 Narziss + */ +public class ZookeeperDynamicConfigTest extends BaseZkTest { + + @Test + public void testZookeeperDynamicConfig() throws Exception { + System.setProperty(DynamicConfigKeys.DYNAMIC_URL.getKey(), "zookeeper://127.0.0.1:2181"); + ApplicationConfig clientApplication = new ApplicationConfig(); + clientApplication.setAppName("demo"); + + ConsumerConfig consumerConfig = new ConsumerConfig() + .setInterfaceId(HelloService.class.getName()) + .setProtocol("bolt") + .setDirectUrl("bolt://127.0.0.1:12200") + .setConnectTimeout(10 * 1000) + .setApplication(clientApplication); + + consumerConfig.refer(); + + DynamicConfigManager dynamicConfigManager = DynamicConfigManagerFactory.getDynamicManagerWithUrl + (clientApplication.getAppName(), System.getProperty(DynamicConfigKeys.DYNAMIC_URL.getKey())); + Field field = ZookeeperDynamicConfigManager.class.getDeclaredField("zkClient"); + field.setAccessible(true); + CuratorFramework zkClient = (CuratorFramework) field.get(dynamicConfigManager); + // 创建或更新配置节点 + if (zkClient.checkExists().forPath("/config/demo/com.alipay.sofa.rpc.test.HelloService") == null) { + zkClient.create() + .creatingParentsIfNeeded() + .withMode(CreateMode.PERSISTENT) + .forPath("/config/demo/com.alipay.sofa.rpc.test.HelloService", "timeout=5000".getBytes()); + } else { + zkClient.setData().forPath("/sofa-rpc/config/demo/com.alipay.sofa.rpc.test.HelloService", + "timeout=5000".getBytes()); + } + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 验证配置是否更新 + Assert.assertEquals(5000, consumerConfig.getMethodTimeout("sayHello")); + + } +} diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/base/BaseZkTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/base/BaseZkTest.java new file mode 100644 index 000000000..9268a8f0b --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/config/base/BaseZkTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test.config.base; + +import com.alipay.sofa.rpc.context.RpcInternalContext; +import com.alipay.sofa.rpc.context.RpcInvokeContext; +import com.alipay.sofa.rpc.context.RpcRunningState; +import com.alipay.sofa.rpc.context.RpcRuntimeContext; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.io.IOException; + +/** + * @author Narziss + * @version BaseZkTest.java, v 0.1 2024年10月08日 10:20 Narziss + */ +public abstract class BaseZkTest { + protected static TestingServer server = null; + + @BeforeClass + public static void adBeforeClass() { + RpcRunningState.setUnitTestMode(true); + + try { + server = new TestingServer(2181, true); + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void adAfterClass() { + RpcRuntimeContext.destroy(); + RpcInternalContext.removeContext(); + RpcInvokeContext.removeContext(); + + if (server != null) { + try { + server.stop(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file