diff --git a/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java b/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java index 2bc0fe5bdc9..e56a82801bc 100644 --- a/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java +++ b/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java @@ -37,6 +37,9 @@ public class PropertyKeyConst { public static final String ENDPOINT_CLUSTER_NAME = "endpointClusterName"; + public static final String ENDPOINT_REFRESH_INTERVAL_SECONDS = "endpointRefreshIntervalSeconds"; + + @Deprecated public static final String SERVER_NAME = "serverName"; public static final String NAMESPACE = "namespace"; @@ -55,8 +58,19 @@ public class PropertyKeyConst { public static final String CONTEXT_PATH = "contextPath"; + /** + * Please use {@link #ENDPOINT_CLUSTER_NAME} replaced. + */ + @Deprecated public static final String CLUSTER_NAME = "clusterName"; + /** + * Default is {@code "false"}, if true, and without {@link #ENDPOINT_CLUSTER_NAME}, use {@link #CLUSTER_NAME} to set + * endpoint cluster name. + */ + @Deprecated + public static final String IS_ADAPT_CLUSTER_NAME_USAGE = "isAdaptClusterNameUsage"; + public static final String ENCODE = "encode"; public static final String CONFIG_LONG_POLL_TIMEOUT = "configLongPollTimeout"; @@ -97,8 +111,6 @@ public class PropertyKeyConst { public static final String LOG_ALL_PROPERTIES = "logAllProperties"; - public static final String CLIENT_MODULE_TYPE = "clientModuleType"; - /** * Since 2.3.3, For some situation like java agent using nacos-client which can't use env ram info. */ diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index 0bb32558b11..b3313dd45e8 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -252,6 +252,8 @@ public class Constants { */ public static final String DEFAULT_USE_RAM_INFO_PARSING = "true"; + public static final String CLIENT_MODULE_TYPE = "clientModuleType"; + /** * The constants in config directory. */ diff --git a/client/src/main/java/com/alibaba/nacos/client/address/AbstractServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/address/AbstractServerListManager.java index 06cb728c7f7..7933b01b692 100644 --- a/client/src/main/java/com/alibaba/nacos/client/address/AbstractServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/address/AbstractServerListManager.java @@ -17,9 +17,11 @@ package com.alibaba.nacos.client.address; import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.client.env.NacosClientProperties; import com.alibaba.nacos.client.utils.LogUtils; +import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.http.client.NacosRestTemplate; import com.alibaba.nacos.common.lifecycle.Closeable; import com.alibaba.nacos.common.remote.client.ServerListFactory; @@ -44,22 +46,18 @@ public abstract class AbstractServerListManager implements ServerListFactory, Cl protected NacosClientProperties properties; - public AbstractServerListManager(NacosClientProperties properties) throws NacosException { + public AbstractServerListManager(NacosClientProperties properties) { this(properties, null); } - public AbstractServerListManager(NacosClientProperties properties, String namespace) throws NacosException { - if (null == properties) { - LOGGER.error("properties is null"); - return; - } + public AbstractServerListManager(NacosClientProperties properties, String namespace) { + // To avoid set operation affect the original properties. + NacosClientProperties tmpProperties = properties.derive(); if (StringUtils.isNotBlank(namespace)) { - // To avoid set operation affect the original properties. - properties = properties.derive(); - properties.setProperty(PropertyKeyConst.NAMESPACE, namespace); + tmpProperties.setProperty(PropertyKeyConst.NAMESPACE, namespace); } - properties.setProperty(PropertyKeyConst.CLIENT_MODULE_TYPE, getModuleName()); - this.properties = properties; + tmpProperties.setProperty(Constants.CLIENT_MODULE_TYPE, getModuleName()); + this.properties = tmpProperties; } @Override @@ -98,16 +96,12 @@ public void start() throws NacosException { } } if (null == serverListProvider) { - LOGGER.error("no server list provider found"); - return; + LOGGER.error("No server list provider found, SPI load size: {}", sorted.size()); + throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "No server list provider found."); } this.serverListProvider.init(properties, getNacosRestTemplate()); } - public NacosClientProperties getProperties() { - return properties; - } - public String getServerName() { return getModuleName() + "-" + serverListProvider.getServerName(); } @@ -133,12 +127,17 @@ public boolean isFixed() { * * @return module name */ - public abstract String getModuleName(); + protected abstract String getModuleName(); /** * get nacos rest template. * * @return nacos rest template */ - public abstract NacosRestTemplate getNacosRestTemplate(); + protected abstract NacosRestTemplate getNacosRestTemplate(); + + @JustForTest + NacosClientProperties getProperties() { + return properties; + } } diff --git a/client/src/main/java/com/alibaba/nacos/client/address/EndpointServerListProvider.java b/client/src/main/java/com/alibaba/nacos/client/address/EndpointServerListProvider.java index b16d25c0229..ea04bdcb8d2 100644 --- a/client/src/main/java/com/alibaba/nacos/client/address/EndpointServerListProvider.java +++ b/client/src/main/java/com/alibaba/nacos/client/address/EndpointServerListProvider.java @@ -18,6 +18,7 @@ import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.SystemPropertyKeyConst; +import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.client.constant.Constants.Address; import com.alibaba.nacos.client.env.NacosClientProperties; @@ -46,8 +47,8 @@ /** * Endpoint server list provider. - * - * @author totalo + * + * @author totalo */ public class EndpointServerListProvider extends AbstractServerListProvider { @@ -80,7 +81,8 @@ public class EndpointServerListProvider extends AbstractServerListProvider { private String moduleName = "default"; @Override - public void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate) throws NacosException { + public void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate) + throws NacosException { super.init(properties, nacosRestTemplate); this.nacosRestTemplate = nacosRestTemplate; initEndpoint(properties); @@ -89,7 +91,7 @@ public void init(final NacosClientProperties properties, final NacosRestTemplate initServerListName(properties); initAddressServerUrl(properties); initModuleName(properties); - startRefreshServerListTask(); + startRefreshServerListTask(properties); } @Override @@ -102,8 +104,7 @@ public String getServerName() { String contextPathTmp = StringUtils.isNotBlank(this.endpointContextPath) ? this.endpointContextPath : this.contextPath; return CUSTOM_NAME + "-" + String.join("_", endpoint, String.valueOf(endpointPort), contextPathTmp, - serverListName) + (StringUtils.isNotBlank(namespace) ? ("_" + StringUtils.trim( - namespace)) : ""); + serverListName) + (StringUtils.isNotBlank(namespace) ? ("_" + StringUtils.trim(namespace)) : ""); } @Override @@ -113,6 +114,16 @@ public int getOrder() { @Override public boolean match(final NacosClientProperties properties) { + String endpointTmp = getEndPointTmp(properties); + return StringUtils.isNotBlank(endpointTmp); + } + + @Override + public String getAddressSource() { + return this.addressServerUrl; + } + + private String getEndPointTmp(NacosClientProperties properties) { String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT); String isUseEndpointRuleParsing = properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, properties.getProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, @@ -120,12 +131,7 @@ public boolean match(final NacosClientProperties properties) { if (Boolean.parseBoolean(isUseEndpointRuleParsing)) { endpointTmp = ParamUtil.parsingEndpointRule(endpointTmp); } - return StringUtils.isNotBlank(endpointTmp); - } - - @Override - public String getAddressSource() { - return this.addressServerUrl; + return endpointTmp; } /** @@ -133,7 +139,7 @@ public String getAddressSource() { * * @throws NacosException nacos exception */ - public void startRefreshServerListTask() throws NacosException { + public void startRefreshServerListTask(NacosClientProperties properties) throws NacosException { for (int i = 0; i < initServerListRetryTimes && getServerList().isEmpty(); ++i) { refreshServerListIfNeed(); if (!serversFromEndpoint.isEmpty()) { @@ -155,7 +161,10 @@ public void startRefreshServerListTask() throws NacosException { refreshServerListExecutor = new ScheduledThreadPoolExecutor(1, new NameThreadFactory("com.alibaba.nacos.client.address.EndpointServerListProvider.refreshServerList")); // executor schedules the timer task - refreshServerListExecutor.scheduleWithFixedDelay(this::refreshServerListIfNeed, 0L, 30L, TimeUnit.SECONDS); + long refreshInterval = Long.parseLong( + properties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, "30")); + refreshServerListExecutor.scheduleWithFixedDelay(this::refreshServerListIfNeed, 0L, refreshInterval, + TimeUnit.SECONDS); } private void refreshServerListIfNeed() { @@ -168,7 +177,7 @@ private void refreshServerListIfNeed() { throw new Exception("Can not acquire Nacos list"); } list.sort(String::compareTo); - if (null == serversFromEndpoint || !CollectionUtils.isEqualCollection(list, serversFromEndpoint)) { + if (!CollectionUtils.isEqualCollection(list, serversFromEndpoint)) { LOGGER.info("[SERVER-LIST] server list is updated: {}", list); serversFromEndpoint = list; lastServerListRefreshTime = System.currentTimeMillis(); @@ -181,8 +190,8 @@ private void refreshServerListIfNeed() { private List getServerListFromEndpoint() { try { - HttpRestResult httpResult = nacosRestTemplate.get(addressServerUrl, HttpUtils.builderHeader(moduleName), - Query.EMPTY, String.class); + HttpRestResult httpResult = nacosRestTemplate.get(addressServerUrl, + HttpUtils.builderHeader(moduleName), Query.EMPTY, String.class); if (!httpResult.ok()) { LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl, @@ -192,10 +201,7 @@ private List getServerListFromEndpoint() { List lines = IoUtils.readLines(new StringReader(httpResult.getData())); List result = new ArrayList<>(lines.size()); for (String serverAddr : lines) { - if (StringUtils.isBlank(serverAddr)) { - continue; - } - String[] ipPort = InternetAddressUtil.splitIPPortStr(serverAddr.trim()); + String[] ipPort = InternetAddressUtil.splitIPPortStr(serverAddr); String ip = ipPort[0].trim(); if (ipPort.length == 1) { result.add(ip + InternetAddressUtil.IP_PORT_SPLITER + ParamUtil.getDefaultServerPort()); @@ -211,15 +217,8 @@ private List getServerListFromEndpoint() { } private void initEndpoint(NacosClientProperties properties) { - String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT); - // Whether to enable domain name resolution rules - String isUseEndpointRuleParsing = properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, - properties.getProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, - String.valueOf(ParamUtil.USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE))); - if (Boolean.parseBoolean(isUseEndpointRuleParsing)) { - endpointTmp = ParamUtil.parsingEndpointRule(endpointTmp); - } - this.endpoint = StringUtils.isNotBlank(endpointTmp) ? endpointTmp : ""; + // Endpoint should not be null or empty, because the match has return `true`. + this.endpoint = getEndPointTmp(properties); } private void initEndpointPort(NacosClientProperties properties) { @@ -241,8 +240,12 @@ private void initEndpointContextPath(NacosClientProperties properties) { } private void initServerListName(NacosClientProperties properties) { - String serverListNameTmp = properties.getProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, - properties.getProperty(PropertyKeyConst.CLUSTER_NAME)); + String serverListNameTmp = properties.getProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME); + boolean isUseClusterName = Boolean.parseBoolean( + properties.getProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE)); + if (StringUtils.isBlank(serverListNameTmp) && isUseClusterName) { + serverListNameTmp = properties.getProperty(PropertyKeyConst.CLUSTER_NAME); + } if (!StringUtils.isBlank(serverListNameTmp)) { this.serverListName = serverListNameTmp; } @@ -259,17 +262,16 @@ private void initAddressServerUrl(NacosClientProperties properties) { addressServerUrlTem.append("?namespace=").append(namespace); hasQueryString = true; } - if (properties != null && properties.containsKey(PropertyKeyConst.ENDPOINT_QUERY_PARAMS)) { - addressServerUrlTem.append( - hasQueryString ? "&" : "?" + properties.getProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS)); - + if (properties.containsKey(PropertyKeyConst.ENDPOINT_QUERY_PARAMS)) { + addressServerUrlTem.append(hasQueryString ? "&" : "?"); + addressServerUrlTem.append(properties.getProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS)); } this.addressServerUrl = addressServerUrlTem.toString(); LOGGER.info("address server url = {}", this.addressServerUrl); } private void initModuleName(NacosClientProperties properties) { - String moduleNameTmp = properties.getProperty(PropertyKeyConst.CLIENT_MODULE_TYPE); + String moduleNameTmp = properties.getProperty(Constants.CLIENT_MODULE_TYPE); if (StringUtils.isNotBlank(moduleNameTmp)) { this.moduleName = moduleNameTmp; } diff --git a/client/src/main/java/com/alibaba/nacos/client/address/AddressServerListProvider.java b/client/src/main/java/com/alibaba/nacos/client/address/PropertiesListProvider.java similarity index 96% rename from client/src/main/java/com/alibaba/nacos/client/address/AddressServerListProvider.java rename to client/src/main/java/com/alibaba/nacos/client/address/PropertiesListProvider.java index 2bc34e74e1f..8321407da72 100644 --- a/client/src/main/java/com/alibaba/nacos/client/address/AddressServerListProvider.java +++ b/client/src/main/java/com/alibaba/nacos/client/address/PropertiesListProvider.java @@ -33,11 +33,11 @@ import static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX; /** - * Address server list provider. + * Properties server list provider. * * @author totalo */ -public class AddressServerListProvider extends AbstractServerListProvider { +public class PropertiesListProvider extends AbstractServerListProvider { private static final String FIXED_NAME = "fixed"; diff --git a/client/src/main/java/com/alibaba/nacos/client/address/ServerListChangeEvent.java b/client/src/main/java/com/alibaba/nacos/client/address/ServerListChangeEvent.java index 6efafe69c60..0eb215ff7bb 100644 --- a/client/src/main/java/com/alibaba/nacos/client/address/ServerListChangeEvent.java +++ b/client/src/main/java/com/alibaba/nacos/client/address/ServerListChangeEvent.java @@ -24,4 +24,6 @@ * @author zongtanghu */ public class ServerListChangeEvent extends SlowEvent { + + private static final long serialVersionUID = -1655577508567092395L; } diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigServerListManager.java index e6f0c611559..cc175188355 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigServerListManager.java @@ -51,7 +51,7 @@ public class ConfigServerListManager extends AbstractServerListManager { private Iterator iterator; - public ConfigServerListManager(NacosClientProperties properties) throws NacosException { + public ConfigServerListManager(NacosClientProperties properties) { super(properties); String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE); if (StringUtils.isNotBlank(namespace)) { @@ -60,12 +60,12 @@ public ConfigServerListManager(NacosClientProperties properties) throws NacosExc } @Override - public String getModuleName() { + protected String getModuleName() { return "Config"; } @Override - public NacosRestTemplate getNacosRestTemplate() { + protected NacosRestTemplate getNacosRestTemplate() { return ConfigHttpClientManager.getInstance().getNacosRestTemplate(); } @@ -80,7 +80,7 @@ public void start() throws NacosException { private String initServerName(NacosClientProperties properties) { String serverName; //1.user define server name. - if (properties != null && properties.containsKey(PropertyKeyConst.SERVER_NAME)) { + if (properties.containsKey(PropertyKeyConst.SERVER_NAME)) { serverName = properties.getProperty(PropertyKeyConst.SERVER_NAME); } else { serverName = getServerName(); @@ -106,8 +106,7 @@ public String genNextServer() { } try { return iterator.next(); - } catch (Exception e) { - //No nothing. + } catch (Exception ignored) { } refreshCurrentServerAddr(); return currentServerAddr; @@ -167,32 +166,26 @@ static class RandomizedServerAddress implements Comparable sorted; + + final Iterator iter; + public ServerAddressIterator(List source) { sorted = new ArrayList<>(); for (String address : source) { @@ -211,14 +204,5 @@ public boolean hasNext() { public String next() { return iter.next().serverIp; } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - final List sorted; - - final Iterator iter; } } \ No newline at end of file diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/core/NamingServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/naming/core/NamingServerListManager.java index c35b2879c66..11bcb5f648e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/core/NamingServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/core/NamingServerListManager.java @@ -19,7 +19,7 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.runtime.NacosLoadException; import com.alibaba.nacos.client.address.AbstractServerListManager; -import com.alibaba.nacos.client.address.AddressServerListProvider; +import com.alibaba.nacos.client.address.PropertiesListProvider; import com.alibaba.nacos.client.env.NacosClientProperties; import com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager; import com.alibaba.nacos.client.utils.LogUtils; @@ -48,11 +48,11 @@ public class NamingServerListManager extends AbstractServerListManager { private boolean isDomain; @JustForTest - public NamingServerListManager(Properties properties) throws NacosException { + public NamingServerListManager(Properties properties) { this(NacosClientProperties.PROTOTYPE.derive(properties), ""); } - public NamingServerListManager(NacosClientProperties properties, String namespace) throws NacosException { + public NamingServerListManager(NacosClientProperties properties, String namespace) { super(properties, namespace); } @@ -65,7 +65,7 @@ public void start() throws NacosException { } else { currentIndex.set(new Random().nextInt(serverList.size())); } - if (serverListProvider instanceof AddressServerListProvider) { + if (serverListProvider instanceof PropertiesListProvider) { if (serverList.size() == 1) { isDomain = true; nacosDomain = serverList.get(0); @@ -81,17 +81,13 @@ public boolean isDomain() { return isDomain; } - public void setDomain(final boolean domain) { - isDomain = domain; - } - @Override - public String getModuleName() { + protected String getModuleName() { return "Naming"; } @Override - public NacosRestTemplate getNacosRestTemplate() { + protected NacosRestTemplate getNacosRestTemplate() { return NamingHttpClientManager.getInstance().getNacosRestTemplate(); } diff --git a/client/src/main/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider b/client/src/main/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider index 9efd2f7ce26..88c9e4add3e 100644 --- a/client/src/main/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider +++ b/client/src/main/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider @@ -16,4 +16,4 @@ # com.alibaba.nacos.client.address.EndpointServerListProvider -com.alibaba.nacos.client.address.AddressServerListProvider +com.alibaba.nacos.client.address.PropertiesListProvider diff --git a/client/src/test/java/com/alibaba/nacos/client/address/AbstractServerListManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/address/AbstractServerListManagerTest.java new file mode 100644 index 00000000000..a4aead0cf9e --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/address/AbstractServerListManagerTest.java @@ -0,0 +1,209 @@ +/* + * 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.client.address; + +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.client.env.NacosClientProperties; +import com.alibaba.nacos.common.http.client.NacosRestTemplate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class AbstractServerListManagerTest { + + @Mock + NacosRestTemplate restTemplate; + + NacosClientProperties properties; + + AbstractServerListManager serverListManager; + + @BeforeEach + void setUp() { + properties = NacosClientProperties.PROTOTYPE.derive(); + } + + @AfterEach + void tearDown() throws NacosException { + if (null != serverListManager) { + serverListManager.shutdown(); + } + } + + @Test + void testConstructorWithNamespace() { + serverListManager = new MockServerListManager(properties, "test-namespace"); + assertFalse(properties.containsKey(PropertyKeyConst.NAMESPACE)); + assertFalse(properties.containsKey(Constants.CLIENT_MODULE_TYPE)); + assertTrue(serverListManager.getProperties().containsKey(PropertyKeyConst.NAMESPACE)); + assertEquals("testModule", serverListManager.getProperties().getProperty(Constants.CLIENT_MODULE_TYPE)); + } + + @Test + void testConstructorWithoutNamespace() { + serverListManager = new MockServerListManager(properties); + assertFalse(properties.containsKey(PropertyKeyConst.NAMESPACE)); + assertFalse(properties.containsKey(Constants.CLIENT_MODULE_TYPE)); + assertFalse(serverListManager.getProperties().containsKey(PropertyKeyConst.NAMESPACE)); + assertEquals("testModule", serverListManager.getProperties().getProperty(Constants.CLIENT_MODULE_TYPE)); + } + + @Test + void testStartWithoutProvider() { + serverListManager = new MockServerListManager(properties); + assertThrows(NacosException.class, () -> serverListManager.start()); + } + + @Test + void testGetServerList() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + // Mock provider will call this method in init. + verify(restTemplate).getInterceptors(); + assertEquals(1, serverListManager.getServerList().size()); + assertEquals("mock-server-list", serverListManager.getServerList().get(0)); + } + + @Test + void testGetServerNameDefault() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("testModule-", serverListManager.getServerName()); + } + + @Test + void testGetServerName() throws NacosException { + properties.setProperty("MockTest", "true"); + properties.setProperty("ReturnMock", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("testModule-MockServerName", serverListManager.getServerName()); + } + + @Test + void testGetContextPathDefault() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("nacos", serverListManager.getContextPath()); + } + + @Test + void testGetContextPath() throws NacosException { + properties.setProperty("MockTest", "true"); + properties.setProperty("ReturnMock", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("MockContextPath", serverListManager.getContextPath()); + } + + @Test + void testGetNamespaceDefault() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("", serverListManager.getNamespace()); + } + + @Test + void testGetNamespace() throws NacosException { + properties.setProperty("MockTest", "true"); + properties.setProperty("ReturnMock", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("MockNamespace", serverListManager.getNamespace()); + } + + @Test + void testGetAddressSourceDefault() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("", serverListManager.getAddressSource()); + } + + @Test + void testGetAddressSource() throws NacosException { + properties.setProperty("MockTest", "true"); + properties.setProperty("ReturnMock", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertEquals("MockAddressSource", serverListManager.getAddressSource()); + } + + @Test + void testIsFixedDefault() throws NacosException { + properties.setProperty("MockTest", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertFalse(serverListManager.isFixed()); + } + + @Test + void testIsFixed() throws NacosException { + properties.setProperty("MockTest", "true"); + properties.setProperty("ReturnMock", "true"); + serverListManager = new MockServerListManager(properties); + serverListManager.start(); + assertTrue(serverListManager.isFixed()); + } + + private class MockServerListManager extends AbstractServerListManager { + + public MockServerListManager(NacosClientProperties properties) { + super(properties); + } + + public MockServerListManager(NacosClientProperties properties, String namespace) { + super(properties, namespace); + } + + @Override + protected String getModuleName() { + return "testModule"; + } + + @Override + protected NacosRestTemplate getNacosRestTemplate() { + return restTemplate; + } + + @Override + public String genNextServer() { + return ""; + } + + @Override + public String getCurrentServer() { + return ""; + } + } +} \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/address/EndpointServerListProviderTest.java b/client/src/test/java/com/alibaba/nacos/client/address/EndpointServerListProviderTest.java new file mode 100644 index 00000000000..e755b8554c6 --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/address/EndpointServerListProviderTest.java @@ -0,0 +1,402 @@ +/* + * 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.client.address; + +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.SystemPropertyKeyConst; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.client.constant.Constants; +import com.alibaba.nacos.client.env.NacosClientProperties; +import com.alibaba.nacos.client.utils.ContextPathUtil; +import com.alibaba.nacos.client.utils.ParamUtil; +import com.alibaba.nacos.common.constant.HttpHeaderConsts; +import com.alibaba.nacos.common.http.HttpRestResult; +import com.alibaba.nacos.common.http.client.NacosRestTemplate; +import com.alibaba.nacos.common.http.param.Header; +import com.alibaba.nacos.common.http.param.Query; +import com.alibaba.nacos.common.utils.StringUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class EndpointServerListProviderTest { + + @Mock + NacosRestTemplate nacosRestTemplate; + + private EndpointServerListProvider serverListProvider; + + private NacosClientProperties properties; + + private HttpRestResult requestSuccess; + + @BeforeEach + void setUp() { + requestSuccess = new HttpRestResult<>(Header.EMPTY, 200, "\n127.0.0.1\nlocalhost:9848", "success"); + serverListProvider = new EndpointServerListProvider(); + properties = NacosClientProperties.PROTOTYPE.derive(); + } + + @AfterEach + void tearDown() throws NacosException { + System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL); + System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT); + System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH); + System.clearProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME); + System.clearProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE); + serverListProvider.shutdown(); + } + + @Test + void testInitWithoutProperties() throws NacosException { + assertThrows(NacosException.class, () -> serverListProvider.init(null, nacosRestTemplate)); + } + + @Test + void testMatchAndInitForPropertiesEndpoint() throws Exception { + assertFalse(serverListProvider.match(properties)); + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + assertTrue(serverListProvider.match(properties)); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testMatchAndInitForSystemEndpoint() throws Exception { + assertFalse(serverListProvider.match(properties)); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, "endpointFromSystem"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + assertTrue(serverListProvider.match(properties)); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromSystem", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testMatchAndInitByParsingFalseFromProperties() throws Exception { + assertFalse(serverListProvider.match(properties)); + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, "endpointFromSystem"); + properties.setProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, "false"); + assertTrue(serverListProvider.match(properties)); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testMatchAndInitByParsingFalseFromSystem() throws Exception { + assertFalse(serverListProvider.match(properties)); + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, "endpointFromSystem"); + System.setProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, "false"); + assertTrue(serverListProvider.match(properties)); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testMatchAndInitByParsingTrue() throws Exception { + assertFalse(serverListProvider.match(properties)); + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, "endpointFromSystem"); + assertTrue(serverListProvider.match(properties)); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromSystem", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithPropertiesEndpointPort() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, "80"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 80, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithSystemEndpointPort() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT, "443"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 443, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithPropertiesEndpointContextPath() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, "address"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, "address", ParamUtil.getDefaultNodesPath(), "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithSystemEndpointContextPath() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH, "addresses"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, "addresses", ParamUtil.getDefaultNodesPath(), "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitContextPathWithFull() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.CONTEXT_PATH, "globalContextPath"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, "globalContextPath", ParamUtil.getDefaultNodesPath(), "", + "globalContextPath"); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithPropertiesEndpointClusterName() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, "endpointClusterName"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), "endpointClusterName", "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithPropertiesEndpointClusterNameWithFull() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.CLUSTER_NAME, "clusterName"); + properties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, "endpointClusterName"); + properties.setProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE, "true"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), "endpointClusterName", "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithSystemEndpointClusterNameByOldWay() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.CLUSTER_NAME, "clusterName"); + properties.setProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE, "true"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), "clusterName", "", + ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithSystemEndpointClusterWithoutAdapt() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.CLUSTER_NAME, "clusterName"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithNamespace() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.NAMESPACE, "customNamespace"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "customNamespace", ParamUtil.getDefaultContextPath()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithQuery() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS, "nofix=1"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "", ParamUtil.getDefaultContextPath(), "nofix=1"); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithNamespaceAndQuery() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.NAMESPACE, "customNamespace"); + properties.setProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS, "nofix=1"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertInit("endpointFromProperties", 8080, ParamUtil.getDefaultContextPath(), ParamUtil.getDefaultNodesPath(), + "customNamespace", ParamUtil.getDefaultContextPath(), "nofix=1"); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitWithModuleType() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(com.alibaba.nacos.api.common.Constants.CLIENT_MODULE_TYPE, "naming"); + when(nacosRestTemplate.get(anyString(), + argThat(header -> "naming".equals(header.getValue(HttpHeaderConsts.REQUEST_MODULE))), any(Query.class), + eq(String.class))).thenReturn(requestSuccess); + serverListProvider.init(properties, nacosRestTemplate); + assertFalse(serverListProvider.getServerList().isEmpty()); + assertEquals(2, serverListProvider.getServerList().size()); + } + + @Test + void testInitGetServerListWithException() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenThrow( + new IOException("test")); + assertThrows(NacosException.class, () -> serverListProvider.init(properties, nacosRestTemplate)); + } + + @Test + void testInitGetServerListWithError() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + HttpRestResult failedResult = new HttpRestResult<>(Header.EMPTY, 500, null, "test"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + failedResult); + assertThrows(NacosException.class, () -> serverListProvider.init(properties, nacosRestTemplate)); + } + + @Test + void testRefreshServerList() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, "1"); + HttpRestResult newResult = new HttpRestResult<>(Header.EMPTY, 200, "\n1.1.1.1 \nlocalhost:9848", "success"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess, newResult); + serverListProvider.init(properties, nacosRestTemplate); + assertEquals(2, serverListProvider.getServerList().size()); + assertEquals("127.0.0.1:8848", serverListProvider.getServerList().get(0)); + assertEquals("localhost:9848", serverListProvider.getServerList().get(1)); + Field field = EndpointServerListProvider.class.getDeclaredField("lastServerListRefreshTime"); + field.setAccessible(true); + field.set(serverListProvider, 0L); + // wait refresh + TimeUnit.MILLISECONDS.sleep(2000); + assertEquals(2, serverListProvider.getServerList().size()); + assertEquals("1.1.1.1:8848", serverListProvider.getServerList().get(0)); + assertEquals("localhost:9848", serverListProvider.getServerList().get(1)); + } + + @Test + void testRefreshServerListWithDiffSort() throws Exception { + properties.setProperty(PropertyKeyConst.ENDPOINT, "endpointFromProperties"); + properties.setProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, "1"); + HttpRestResult newResult = new HttpRestResult<>(Header.EMPTY, 200, "\nlocalhost:9848\n127.0.0.1", "success"); + when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn( + requestSuccess, newResult); + serverListProvider.init(properties, nacosRestTemplate); + assertEquals(2, serverListProvider.getServerList().size()); + assertEquals("127.0.0.1:8848", serverListProvider.getServerList().get(0)); + assertEquals("localhost:9848", serverListProvider.getServerList().get(1)); + Field field = EndpointServerListProvider.class.getDeclaredField("lastServerListRefreshTime"); + field.setAccessible(true); + field.set(serverListProvider, 0L); + // wait refresh + TimeUnit.MILLISECONDS.sleep(2000); + assertEquals(2, serverListProvider.getServerList().size()); + assertEquals("127.0.0.1:8848", serverListProvider.getServerList().get(0)); + assertEquals("localhost:9848", serverListProvider.getServerList().get(1)); + } + + private void assertInit(String expectedEndpoint, int expectEndpointPort, String expectedEndpointContext, + String expectedServiceName, String expectedNamespace, String expectedContextPath) { + assertInit(expectedEndpoint, expectEndpointPort, expectedEndpointContext, expectedServiceName, + expectedNamespace, expectedContextPath, null); + } + + private void assertInit(String expectedEndpoint, int expectEndpointPort, String expectedEndpointContext, + String expectedServiceName, String expectedNamespace, String expectedContextPath, String expectedQuery) { + String expectedAddressServerUrl = String.format("http://%s:%d%s/%s", expectedEndpoint, expectEndpointPort, + ContextPathUtil.normalizeContextPath(expectedEndpointContext), expectedServiceName); + assertEquals(Constants.Address.ENDPOINT_SERVER_LIST_PROVIDER_ORDER, serverListProvider.getOrder()); + String expectedServerName = String.format("%s-%s_%d_%s_%s", "custom", expectedEndpoint, expectEndpointPort, + expectedEndpointContext, expectedServiceName); + if (StringUtils.isNotBlank(expectedNamespace)) { + expectedServerName = String.format("%s_%s", expectedServerName, expectedNamespace); + expectedAddressServerUrl += "?namespace=" + expectedNamespace; + } + if (StringUtils.isNotBlank(expectedQuery)) { + String queryTag = StringUtils.isBlank(expectedNamespace) ? "?" : "&"; + expectedAddressServerUrl += queryTag + expectedQuery; + } + assertEquals(expectedAddressServerUrl, serverListProvider.getAddressSource()); + assertEquals(expectedServerName, serverListProvider.getServerName()); + assertEquals(expectedNamespace, serverListProvider.getNamespace()); + assertEquals(expectedContextPath, serverListProvider.getContextPath()); + } +} \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/address/PropertiesListProviderTest.java b/client/src/test/java/com/alibaba/nacos/client/address/PropertiesListProviderTest.java new file mode 100644 index 00000000000..740e5449f6d --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/address/PropertiesListProviderTest.java @@ -0,0 +1,81 @@ +/* + * 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.client.address; + +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.client.constant.Constants; +import com.alibaba.nacos.client.env.NacosClientProperties; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PropertiesListProviderTest { + + private PropertiesListProvider propertiesListProvider; + + @BeforeEach + void setUp() { + propertiesListProvider = new PropertiesListProvider(); + } + + @AfterEach + void tearDown() throws NacosException { + propertiesListProvider.shutdown(); + } + + @Test + void testInitWithoutProperties() throws NacosException { + assertThrows(NacosException.class, () -> propertiesListProvider.init(null, null)); + } + + @Test + void testInit() throws NacosException { + NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive(); + assertFalse(propertiesListProvider.match(properties)); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, + "localhost:1111,http://127.0.0.1:2222;https://1.1.1.1:3333,2.2.2.2;http://3.3.3.3,https://4.4.4.4"); + assertTrue(propertiesListProvider.match(properties)); + propertiesListProvider.init(properties, null); + assertEquals(6, propertiesListProvider.getServerList().size()); + assertEquals("localhost:1111", propertiesListProvider.getServerList().get(0)); + assertEquals("http://127.0.0.1:2222", propertiesListProvider.getServerList().get(1)); + assertEquals("https://1.1.1.1:3333", propertiesListProvider.getServerList().get(2)); + assertEquals("2.2.2.2:8848", propertiesListProvider.getServerList().get(3)); + assertEquals("http://3.3.3.3", propertiesListProvider.getServerList().get(4)); + assertEquals("https://4.4.4.4", propertiesListProvider.getServerList().get(5)); + assertTrue(propertiesListProvider.isFixed()); + assertEquals(Constants.Address.ADDRESS_SERVER_LIST_PROVIDER_ORDER, propertiesListProvider.getOrder()); + assertEquals("fixed-localhost_1111-127.0.0.1_2222-1.1.1.1_3333-2.2.2.2_8848-3.3.3.3-4.4.4.4", + propertiesListProvider.getServerName()); + } + + @Test + void testGetServerNameWithNamespace() throws NacosException { + NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive(); + properties.setProperty(PropertyKeyConst.NAMESPACE, "test_namespace"); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, "localhost:1111"); + propertiesListProvider.init(properties, null); + assertEquals("fixed-test_namespace-localhost_1111", propertiesListProvider.getServerName()); + assertEquals("test_namespace", propertiesListProvider.getNamespace()); + } +} \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/address/mock/MockServerListProvider.java b/client/src/test/java/com/alibaba/nacos/client/address/mock/MockServerListProvider.java new file mode 100644 index 00000000000..c45f14896e5 --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/address/mock/MockServerListProvider.java @@ -0,0 +1,102 @@ +/* + * 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.client.address.mock; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.client.address.ServerListProvider; +import com.alibaba.nacos.client.env.NacosClientProperties; +import com.alibaba.nacos.common.http.client.NacosRestTemplate; + +import java.util.Collections; +import java.util.List; + +public class MockServerListProvider implements ServerListProvider { + + private NacosClientProperties properties; + + @Override + public void init(NacosClientProperties properties, NacosRestTemplate nacosRestTemplate) throws NacosException { + this.properties = properties; + nacosRestTemplate.getInterceptors(); + } + + @Override + public List getServerList() { + if (properties.containsKey("EmptyList")) { + return Collections.emptyList(); + } + return Collections.singletonList("mock-server-list"); + } + + @Override + public int getOrder() { + return Integer.MIN_VALUE; + } + + @Override + public boolean match(NacosClientProperties properties) { + return properties.containsKey("MockTest"); + } + + @Override + public void shutdown() throws NacosException { + } + + @Override + public String getServerName() { + if (isReturnMock()) { + return "MockServerName"; + } + return ServerListProvider.super.getServerName(); + } + + @Override + public String getNamespace() { + if (isReturnMock()) { + return "MockNamespace"; + } + return ServerListProvider.super.getNamespace(); + } + + @Override + public String getContextPath() { + if (isReturnMock()) { + return "MockContextPath"; + } + return ServerListProvider.super.getContextPath(); + } + + @Override + public boolean isFixed() { + if (isReturnMock()) { + return true; + } + return ServerListProvider.super.isFixed(); + } + + @Override + public String getAddressSource() { + if (isReturnMock()) { + return "MockAddressSource"; + } + return ServerListProvider.super.getAddressSource(); + } + + private boolean isReturnMock() { + return properties.getBoolean("ReturnMock", false); + } +} diff --git a/client/src/test/java/com/alibaba/nacos/client/config/http/ServerHttpAgentTest.java b/client/src/test/java/com/alibaba/nacos/client/config/http/ServerHttpAgentTest.java index ee471513b9e..a471386cb29 100644 --- a/client/src/test/java/com/alibaba/nacos/client/config/http/ServerHttpAgentTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/config/http/ServerHttpAgentTest.java @@ -97,7 +97,8 @@ void setUp() throws Exception { Map restMap = (Map) restMapField.get(null); cachedNacosRestTemplate = restMap.get( "com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory"); - restMap.put("com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory", nacosRestTemplate); + restMap.put("com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory", + nacosRestTemplate); httpRestResult = new HttpRestResult(); httpRestResult.setData("127.0.0.1:8848"); httpRestResult.setCode(200); @@ -126,6 +127,7 @@ void tearDown() throws NacosException, NoSuchFieldException, IllegalAccessExcept void testConstruct() throws NacosException { NacosClientProperties mockedProperties = mock(NacosClientProperties.class); when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn("aaa"); + when(mockedProperties.derive()).thenReturn(mockedProperties); ConfigServerListManager server = new ConfigServerListManager(mockedProperties); final ServerHttpAgent serverHttpAgent1 = new ServerHttpAgent(server); assertNotNull(serverHttpAgent1); @@ -145,6 +147,8 @@ void testGetterAndSetter() throws Exception { NacosClientProperties mockedProperties = mock(NacosClientProperties.class); when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn("aaa"); when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn("namespace1"); + when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, "30")).thenReturn("30"); + when(mockedProperties.derive()).thenReturn(mockedProperties); ConfigServerListManager server = new ConfigServerListManager(mockedProperties); server.start(); final ServerHttpAgent serverHttpAgent = new ServerHttpAgent(server, new Properties()); diff --git a/client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigServerListManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigServerListManagerTest.java index 006aff12357..194faee6318 100644 --- a/client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigServerListManagerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigServerListManagerTest.java @@ -38,6 +38,7 @@ import java.lang.reflect.Field; import java.util.Iterator; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Properties; import static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX; @@ -45,6 +46,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.contains; @@ -69,7 +71,8 @@ void setUp() throws Exception { Map restMap = (Map) restMapField.get(null); cachedNacosRestTemplate = restMap.get( "com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory"); - restMap.put("com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory", nacosRestTemplate); + restMap.put("com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory", + nacosRestTemplate); httpRestResult = new HttpRestResult<>(); httpRestResult.setData("127.0.0.1:8848"); httpRestResult.setCode(200); @@ -92,9 +95,29 @@ void testStart() throws NacosException { NacosClientProperties mockedProperties = mock(NacosClientProperties.class); when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn("1.1.1.1"); when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_PORT)).thenReturn("9090"); + when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, "30")).thenReturn("30"); + when(mockedProperties.derive()).thenReturn(mockedProperties); final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties); - mgr.start(); - mgr.shutdown(); + try { + mgr.start(); + assertEquals("Config-custom-1.1.1.1_9090_nacos_serverlist", mgr.getName()); + } finally { + mgr.shutdown(); + } + } + + @Test + void testStartWithCustomServerName() throws NacosException { + NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive(); + properties.setProperty(PropertyKeyConst.SERVER_NAME, "test"); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, "1.1.1.1"); + final ConfigServerListManager mgr = new ConfigServerListManager(properties); + try { + mgr.start(); + assertEquals("test", mgr.getName()); + } finally { + mgr.shutdown(); + } } @Test @@ -103,6 +126,7 @@ void testGetter() throws NacosException { NacosClientProperties mockedProperties = mock(NacosClientProperties.class); when(mockedProperties.getProperty(PropertyKeyConst.SERVER_ADDR)).thenReturn("1.1.1.1"); when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn("namespace"); + when(mockedProperties.derive()).thenReturn(mockedProperties); final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties); mgr.start(); assertEquals("nacos", mgr.getContextPath()); @@ -190,6 +214,7 @@ void testIterator() throws NacosException { NacosClientProperties mockedProperties = mock(NacosClientProperties.class); when(mockedProperties.getProperty(PropertyKeyConst.SERVER_ADDR)).thenReturn("1.1.1.1:8848"); when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn("aaa"); + when(mockedProperties.derive()).thenReturn(mockedProperties); final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties); mgr.start(); @@ -241,8 +266,8 @@ void testAddressServerBaseEndpoint() throws NacosException { final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties); serverListManager.start(); - assertTrue(serverListManager.getAddressSource().startsWith( - HTTP_PREFIX + endpoint + ":" + endpointPort + endpointContextPath)); + assertTrue(serverListManager.getAddressSource() + .startsWith(HTTP_PREFIX + endpoint + ":" + endpointPort + endpointContextPath)); } @Test @@ -326,10 +351,10 @@ void testWithEndpointClusterName() throws NacosException { assertTrue(addressSource.contains(testEndpointClusterName)); assertTrue(serverListManager.getName().contains(testEndpointClusterName)); - + assertFalse(addressSource.contains(testClusterName)); assertFalse(serverListManager.getName().contains(testClusterName)); - + } @Test @@ -351,7 +376,7 @@ void testWithoutEndpointContextPath() throws NacosException { assertFalse(serverListManager.getName().contains("endpointContextPath")); assertTrue(serverListManager.getName().contains("contextPath")); } - + @Test void testUseEndpointParsingRule() throws NacosException { System.setProperty("nacos.endpoint", "1.1.1.1"); @@ -365,4 +390,64 @@ void testUseEndpointParsingRule() throws NacosException { String addressServerUrl = serverListManager.getAddressSource(); assertTrue(addressServerUrl.startsWith("http://1.1.1.1")); } + + @Test + void testUpdateCurrentServerAddr() throws NacosException { + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, "1.1.1.1:8848,2.2.2.2:8848"); + final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); + ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties); + serverListManager.start(); + assertTrue("1.1.1.1:8848,2.2.2.2:8848".contains(serverListManager.getCurrentServer())); + serverListManager.updateCurrentServerAddr(null); + assertTrue("1.1.1.1:8848,2.2.2.2:8848".contains(serverListManager.getCurrentServer())); + serverListManager.updateCurrentServerAddr("1.1.1.1:8848"); + assertEquals("1.1.1.1:8848", serverListManager.getCurrentServer()); + } + + @Test + void testStartWithEmptyServerList() throws NacosException { + Properties properties = new Properties(); + properties.setProperty("EmptyList", "true"); + properties.setProperty("MockTest", "true"); + NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); + final ConfigServerListManager mgr = new ConfigServerListManager(clientProperties); + try { + assertThrows(NoSuchElementException.class, mgr::start); + } finally { + mgr.shutdown(); + } + } + + @Test + void testGenNextServer() throws NacosException { + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, "1.1.1.1:8848,2.2.2.2:8848"); + final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); + ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties); + serverListManager.start(); + String currentServer = serverListManager.getCurrentServer(); + String expectedServer = "1.1.1.1:8848,2.2.2.2:8848".replace(currentServer, ""); + expectedServer = expectedServer.replace(",", ""); + assertEquals(expectedServer, serverListManager.genNextServer()); + // Don't throw NoSuchElementException, re-generate server list and re-shuffle. + assertTrue("1.1.1.1:8848,2.2.2.2:8848".contains(serverListManager.genNextServer())); + } + + @Test + void testGenNextServerWithMockConcurrent() throws NacosException, NoSuchFieldException, IllegalAccessException { + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, "1.1.1.1:8848,2.2.2.2:8848"); + final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); + ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties); + serverListManager.start(); + Iterator mockIterator = mock(Iterator.class); + Field field = ConfigServerListManager.class.getDeclaredField("iterator"); + field.setAccessible(true); + field.set(serverListManager, mockIterator); + // Mock async call gen next server, hasNext return `ture` and item be got by other thread. + when(mockIterator.hasNext()).thenReturn(true); + when(mockIterator.next()).thenThrow(new NoSuchElementException()); + assertNotNull(serverListManager.genNextServer()); + } } \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/core/NamingServerListManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/core/NamingServerListManagerTest.java index 2f542249922..5590bf39191 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/core/NamingServerListManagerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/core/NamingServerListManagerTest.java @@ -18,6 +18,7 @@ import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.runtime.NacosLoadException; import com.alibaba.nacos.client.address.AbstractServerListManager; import com.alibaba.nacos.client.address.EndpointServerListProvider; import com.alibaba.nacos.client.address.ServerListProvider; @@ -45,12 +46,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; @ExtendWith(MockitoExtension.class) -// todo remove strictness lenient @MockitoSettings(strictness = Strictness.LENIENT) class NamingServerListManagerTest { @@ -73,7 +75,8 @@ void setUp() throws Exception { Map restMap = (Map) restMapField.get(null); cachedNacosRestTemplate = restMap.get( "com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory"); - restMap.put("com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory", nacosRestTemplate); + restMap.put("com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory", + nacosRestTemplate); httpRestResult = new HttpRestResult<>(); httpRestResult.setData("127.0.0.1:8848"); httpRestResult.setCode(200); @@ -256,9 +259,8 @@ void testIsDomain() throws Exception { properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848"); serverListManager = new NamingServerListManager(properties); serverListManager.start(); - // todo - //assertTrue(serverListManager.isDomain()); - // assertEquals("127.0.0.1:8848", serverListManager()); + assertTrue(serverListManager.isDomain()); + assertEquals("127.0.0.1:8848", serverListManager.getNacosDomain()); } @Test @@ -282,6 +284,15 @@ void testShutdown() throws NacosException { }); } + @Test + void testStartWithEmptyServerList() { + Properties properties = new Properties(); + properties.setProperty("EmptyList", "true"); + properties.setProperty("MockTest", "true"); + final NamingServerListManager serverListManager = new NamingServerListManager(properties); + assertThrows(NacosLoadException.class, serverListManager::start); + } + private void mockThreadInvoke(NamingServerListManager serverListManager, boolean expectedInvoked) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Field providerField = AbstractServerListManager.class.getDeclaredField("serverListProvider"); diff --git a/client/src/test/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider b/client/src/test/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider new file mode 100644 index 00000000000..0a9a89efa4c --- /dev/null +++ b/client/src/test/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider @@ -0,0 +1,18 @@ +# +# Copyright 1999-2024 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +com.alibaba.nacos.client.address.mock.MockServerListProvider