Merge pull request #5707 from KomachiSion/feature_support_grpc_core
Merge codes from develop branch
This commit is contained in:
commit
04cc4da340
@ -1,16 +0,0 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package.json,.travis.yml}]
|
||||
indent_size = 2
|
28
NOTICE
28
NOTICE
@ -31,8 +31,30 @@ Also, please refer to each LICENSE.<component>.txt file, which is located in
|
||||
the 'license' directory of the distribution file, for the license terms of the
|
||||
components that this product depends on.
|
||||
|
||||
|
||||
------
|
||||
This product has a bundle Protocol Buffers:
|
||||
com.alibaba.nacos.common.utils.InetAddressValidator.java in this product is
|
||||
copied from com.dynatrace.openkit.core.util.InetAddressValidator.java of openkit-java project.
|
||||
https://github.com/Dynatrace/openkit-java
|
||||
openkit-java
|
||||
======================
|
||||
|
||||
Copyright 2018-2021 Dynatrace LLC
|
||||
|
||||
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.
|
||||
|
||||
------
|
||||
This product has a bundle Protocol Buffers<72><73>
|
||||
Protocol Buffers
|
||||
=======================
|
||||
Protocol Buffers for Go with Gadgets
|
||||
@ -41,7 +63,7 @@ Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||||
http://github.com/gogo/protobuf
|
||||
|
||||
------
|
||||
This product has a bundle Istio:
|
||||
This product has a bundle Istio<EFBFBD><EFBFBD>
|
||||
Istio
|
||||
=======================
|
||||
|
||||
@ -57,4 +79,4 @@ This product has a bundle Istio
|
||||
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.
|
||||
limitations under the License.
|
||||
|
@ -36,11 +36,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-naming</artifactId>
|
||||
|
@ -83,6 +83,8 @@ public class Constants {
|
||||
|
||||
public static final String GLOBAL_ADMIN = "globalAdmin";
|
||||
|
||||
public static final String USERNAME = "username";
|
||||
|
||||
public static final String TOKEN_REFRESH_WINDOW = "tokenRefreshWindow";
|
||||
|
||||
/**
|
||||
|
@ -113,21 +113,10 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.prometheus</groupId>
|
||||
<artifactId>simpleclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.common;
|
||||
|
||||
/**
|
||||
* config common constants.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigConstants {
|
||||
|
||||
public static final String TENANT = "tenant";
|
||||
|
||||
public static final String DATA_ID = "dataId";
|
||||
|
||||
public static final String GROUP = "group";
|
||||
|
||||
public static final String CONTENT = "content";
|
||||
|
||||
public static final String CONFIG_TYPE = "configType";
|
||||
|
||||
public static final String ENCRYPTED_DATA_KEY = "encryptedDataKey";
|
||||
}
|
@ -22,6 +22,11 @@ import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.CONTENT;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.DATA_ID;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.GROUP;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.TENANT;
|
||||
|
||||
/**
|
||||
* Config Request.
|
||||
*
|
||||
@ -34,35 +39,35 @@ public class ConfigRequest implements IConfigRequest {
|
||||
private final IConfigContext configContext = new ConfigContext();
|
||||
|
||||
public String getTenant() {
|
||||
return (String) param.get("tenant");
|
||||
return (String) param.get(TENANT);
|
||||
}
|
||||
|
||||
public void setTenant(String tenant) {
|
||||
param.put("tenant", tenant);
|
||||
param.put(TENANT, tenant);
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return (String) param.get("dataId");
|
||||
return (String) param.get(DATA_ID);
|
||||
}
|
||||
|
||||
public void setDataId(String dataId) {
|
||||
param.put("dataId", dataId);
|
||||
param.put(DATA_ID, dataId);
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return (String) param.get("group");
|
||||
return (String) param.get(GROUP);
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
param.put("group", group);
|
||||
param.put(GROUP, group);
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return (String) param.get("content");
|
||||
return (String) param.get(CONTENT);
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
param.put("content", content);
|
||||
param.put(CONTENT, content);
|
||||
}
|
||||
|
||||
public void getType() {
|
||||
|
@ -22,6 +22,13 @@ import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.CONFIG_TYPE;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.CONTENT;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.DATA_ID;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.ENCRYPTED_DATA_KEY;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.GROUP;
|
||||
import static com.alibaba.nacos.client.config.common.ConfigConstants.TENANT;
|
||||
|
||||
/**
|
||||
* Config Response.
|
||||
*
|
||||
@ -34,51 +41,51 @@ public class ConfigResponse implements IConfigResponse {
|
||||
private final IConfigContext configContext = new ConfigContext();
|
||||
|
||||
public String getTenant() {
|
||||
return (String) param.get("tenant");
|
||||
return (String) param.get(TENANT);
|
||||
}
|
||||
|
||||
public void setTenant(String tenant) {
|
||||
param.put("tenant", tenant);
|
||||
param.put(TENANT, tenant);
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return (String) param.get("dataId");
|
||||
return (String) param.get(DATA_ID);
|
||||
}
|
||||
|
||||
public void setDataId(String dataId) {
|
||||
param.put("dataId", dataId);
|
||||
param.put(DATA_ID, dataId);
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return (String) param.get("group");
|
||||
return (String) param.get(GROUP);
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
param.put("group", group);
|
||||
param.put(GROUP, group);
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return (String) param.get("content");
|
||||
return (String) param.get(CONTENT);
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
param.put("content", content);
|
||||
param.put(CONTENT, content);
|
||||
}
|
||||
|
||||
public String getConfigType() {
|
||||
return (String) param.get("configType");
|
||||
return (String) param.get(CONFIG_TYPE);
|
||||
}
|
||||
|
||||
public void setConfigType(String configType) {
|
||||
param.put("configType", configType);
|
||||
param.put(CONFIG_TYPE, configType);
|
||||
}
|
||||
|
||||
public String getEncryptedDataKey() {
|
||||
return (String) param.get("encryptedDataKey");
|
||||
return (String) param.get(ENCRYPTED_DATA_KEY);
|
||||
}
|
||||
|
||||
public void setEncryptedDataKey(String encryptedDataKey) {
|
||||
param.put("encryptedDataKey", encryptedDataKey);
|
||||
param.put(ENCRYPTED_DATA_KEY, encryptedDataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,7 +48,9 @@ public class ParamUtil {
|
||||
|
||||
private static String appName;
|
||||
|
||||
private static final String DEFAULT_SERVER_PORT;
|
||||
private static final String DEFAULT_SERVER_PORT = "8848";
|
||||
|
||||
private static String serverPort;
|
||||
|
||||
private static String clientVersion = "unknown";
|
||||
|
||||
@ -56,22 +58,38 @@ public class ParamUtil {
|
||||
|
||||
private static double perTaskConfigSize = 3000;
|
||||
|
||||
private static final String NACOS_CLIENT_APP_KEY = "nacos.client.appKey";
|
||||
|
||||
private static final String BLANK_STR = "";
|
||||
|
||||
private static final String NACOS_CLIENT_CONTEXTPATH_KEY = "nacos.client.contextPath";
|
||||
|
||||
private static final String DEFAULT_NACOS_CLIENT_CONTEXTPATH = "nacos";
|
||||
|
||||
private static final String NACOS_SERVER_PORT_KEY = "nacos.server.port";
|
||||
|
||||
private static final String NACOS_CONNECT_TIMEOUT_KEY = "NACOS.CONNECT.TIMEOUT";
|
||||
|
||||
private static final String DEFAULT_NACOS_CONNECT_TIMEOUT = "1000";
|
||||
|
||||
private static final String PER_TASK_CONFIG_SIZE_KEY = "PER_TASK_CONFIG_SIZE";
|
||||
|
||||
private static final String DEFAULT_PER_TASK_CONFIG_SIZE_KEY = "3000";
|
||||
|
||||
static {
|
||||
// 客户端身份信息
|
||||
appKey = System.getProperty("nacos.client.appKey", "");
|
||||
// Client identity information
|
||||
appKey = System.getProperty(NACOS_CLIENT_APP_KEY, BLANK_STR);
|
||||
|
||||
defaultContextPath = System.getProperty("nacos.client.contextPath", "nacos");
|
||||
defaultContextPath = System.getProperty(NACOS_CLIENT_CONTEXTPATH_KEY, DEFAULT_NACOS_CLIENT_CONTEXTPATH);
|
||||
|
||||
appName = AppNameUtils.getAppName();
|
||||
|
||||
String defaultServerPortTmp = "8848";
|
||||
|
||||
DEFAULT_SERVER_PORT = System.getProperty("nacos.server.port", defaultServerPortTmp);
|
||||
LOGGER.info("[settings] [req-serv] nacos-server port:{}", DEFAULT_SERVER_PORT);
|
||||
serverPort = System.getProperty(NACOS_SERVER_PORT_KEY, DEFAULT_SERVER_PORT);
|
||||
LOGGER.info("[settings] [req-serv] nacos-server port:{}", serverPort);
|
||||
|
||||
String tmp = "1000";
|
||||
try {
|
||||
tmp = System.getProperty("NACOS.CONNECT.TIMEOUT", "1000");
|
||||
tmp = System.getProperty(NACOS_CONNECT_TIMEOUT_KEY, DEFAULT_NACOS_CONNECT_TIMEOUT);
|
||||
connectTimeout = Integer.parseInt(tmp);
|
||||
} catch (NumberFormatException e) {
|
||||
final String msg = "[http-client] invalid connect timeout:" + tmp;
|
||||
@ -83,7 +101,8 @@ public class ParamUtil {
|
||||
clientVersion = VersionUtils.version;
|
||||
|
||||
try {
|
||||
perTaskConfigSize = Double.valueOf(System.getProperty("PER_TASK_CONFIG_SIZE", "3000"));
|
||||
perTaskConfigSize = Double
|
||||
.valueOf(System.getProperty(PER_TASK_CONFIG_SIZE_KEY, DEFAULT_PER_TASK_CONFIG_SIZE_KEY));
|
||||
LOGGER.info("PER_TASK_CONFIG_SIZE: {}", perTaskConfigSize);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("[PER_TASK_CONFIG_SIZE] PER_TASK_CONFIG_SIZE invalid", t);
|
||||
@ -139,7 +158,7 @@ public class ParamUtil {
|
||||
}
|
||||
|
||||
public static String getDefaultServerPort() {
|
||||
return DEFAULT_SERVER_PORT;
|
||||
return serverPort;
|
||||
}
|
||||
|
||||
public static String getDefaultNodesPath() {
|
||||
@ -188,7 +207,7 @@ public class ParamUtil {
|
||||
* @return end point rule
|
||||
*/
|
||||
public static String parsingEndpointRule(String endpointUrl) {
|
||||
// 配置文件中输入的话,以 ENV 中的优先,
|
||||
// If entered in the configuration file, the priority in ENV will be given priority.
|
||||
if (endpointUrl == null || !PATTERN.matcher(endpointUrl).find()) {
|
||||
// skip retrieve from system property and retrieve directly from system env
|
||||
String endpointUrlSource = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConfigFilterChainTest {
|
||||
|
||||
@Test
|
||||
public void testConfigFilterChain() {
|
||||
ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(null);
|
||||
configFilterChainManager.addFilter(new DemoFilter1());
|
||||
configFilterChainManager.addFilter(new DemoFilter2());
|
||||
ConfigRequest configRequest = new ConfigRequest();
|
||||
try {
|
||||
configFilterChainManager.doFilter(configRequest, null);
|
||||
Assert.assertEquals(DemoFilter1.class.getName(), configRequest.getParameter("filter1"));
|
||||
Assert.assertEquals(DemoFilter2.class.getName(), configRequest.getParameter("filter2"));
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import com.alibaba.nacos.api.config.filter.IFilterConfig;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class DemoFilter1 implements IConfigFilter {
|
||||
|
||||
private static final String DEFAULT_NAME = DemoFilter1.class.getName();
|
||||
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
|
||||
throws NacosException {
|
||||
request.putParameter("filter1", DEFAULT_NAME);
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterName() {
|
||||
return DEFAULT_NAME;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import com.alibaba.nacos.api.config.filter.IFilterConfig;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class DemoFilter2 implements IConfigFilter {
|
||||
|
||||
private static final String DEFAULT_NAME = DemoFilter2.class.getName();
|
||||
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
|
||||
throws NacosException {
|
||||
request.putParameter("filter2", DEFAULT_NAME);
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterName() {
|
||||
return DEFAULT_NAME;
|
||||
}
|
||||
}
|
@ -39,12 +39,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-core</artifactId>
|
||||
|
@ -65,13 +65,6 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
|
@ -119,7 +119,7 @@ public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
UPDATER.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Event listener exception : {}", ex);
|
||||
LOGGER.error("Event listener exception : ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -47,14 +45,15 @@ public class IPUtil {
|
||||
|
||||
private static final String LOCAL_HOST_IP_V6 = "[::1]";
|
||||
|
||||
private static Pattern ipv4Pattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
|
||||
|
||||
private static final int IPV4_ADDRESS_LENGTH = 4;
|
||||
|
||||
private static final int IPV6_ADDRESS_LENGTH = 16;
|
||||
|
||||
private static final String CHECK_OK = "ok";
|
||||
|
||||
private static final Pattern DOMAIN_PATTERN = Pattern.compile("[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?");
|
||||
|
||||
private static final String IPV4_TUPLE = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])";
|
||||
|
||||
private static final Pattern IPV4_PATTERN = Pattern
|
||||
.compile("(?<!\\d)" + IPV4_TUPLE + "\\." + IPV4_TUPLE + "\\." + IPV4_TUPLE + "\\." + IPV4_TUPLE + "(?!\\d)");
|
||||
|
||||
/**
|
||||
* get localhost ip.
|
||||
* @return java.lang.String
|
||||
@ -73,7 +72,7 @@ public class IPUtil {
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isIPv4(String addr) {
|
||||
return ipv4Pattern.matcher(addr).matches();
|
||||
return InetAddressValidator.isIPv4Address(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,11 +82,7 @@ public class IPUtil {
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isIPv6(String addr) {
|
||||
try {
|
||||
return InetAddress.getByName(addr).getAddress().length == IPV6_ADDRESS_LENGTH;
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
return InetAddressValidator.isIPv6Address(removeBrackets(addr));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,6 +134,9 @@ public class IPUtil {
|
||||
throw new IllegalArgumentException("The IP address(\"" + str
|
||||
+ "\") is incorrect. If it is an IPv6 address, please use [] to enclose the IP part!");
|
||||
}
|
||||
if (!isIPv4(serverAddrArr[0]) && !DOMAIN_PATTERN.matcher(serverAddrArr[0]).matches()) {
|
||||
throw new IllegalArgumentException("The IPv4 or Domain address(\"" + serverAddrArr[0] + "\") is incorrect.");
|
||||
}
|
||||
}
|
||||
return serverAddrArr;
|
||||
}
|
||||
@ -159,7 +157,7 @@ public class IPUtil {
|
||||
result = "";
|
||||
}
|
||||
} else {
|
||||
Matcher m = ipv4Pattern.matcher(str);
|
||||
Matcher m = IPV4_PATTERN.matcher(str);
|
||||
if (m.find()) {
|
||||
result = m.group();
|
||||
}
|
||||
@ -204,4 +202,17 @@ public class IPUtil {
|
||||
return CHECK_OK.equals(checkIPsResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove brackets "[]".
|
||||
*
|
||||
* @param str is ipv6 address
|
||||
* @return
|
||||
*/
|
||||
public static String removeBrackets(String str) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return "";
|
||||
}
|
||||
return str.replaceAll("[\\[\\]]", "");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Copyright 2018-2021 Dynatrace LLC
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* ipv4 ipv6 check util.
|
||||
*
|
||||
* @author Dynatrace LLC
|
||||
*/
|
||||
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName", "PMD.ClassNamingShouldBeCamelRule"})
|
||||
public class InetAddressValidator {
|
||||
|
||||
private static final String PERCENT = "%";
|
||||
|
||||
private static final String DOUBLE_COLON = "::";
|
||||
|
||||
private static final String DOUBLE_COLON_FFFF = "::ffff:";
|
||||
|
||||
private static final String FE80 = "fe80:";
|
||||
|
||||
private static final int ZERO = 0;
|
||||
|
||||
private static final int SEVEN = 7;
|
||||
|
||||
private static final int FIVE = 5;
|
||||
|
||||
private static final Pattern IPV4_PATTERN = Pattern
|
||||
.compile("^" + "(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)" + "(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}" + "$");
|
||||
|
||||
private static final Pattern IPV6_STD_PATTERN = Pattern
|
||||
.compile("^" + "(?:[0-9a-fA-F]{1,4}:){7}" + "[0-9a-fA-F]{1,4}" + "$");
|
||||
|
||||
private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern
|
||||
.compile("^" + "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "::"
|
||||
|
||||
+ "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "$");
|
||||
|
||||
private static final Pattern IPV6_MIXED_COMPRESSED_REGEX = Pattern.compile(
|
||||
"^" + "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "::" + "(" + "(?:[0-9A-Fa-f]{1,4}:"
|
||||
+ "(?:[0-9A-Fa-f]{1,4}:)*)?" + ")" + "$");
|
||||
|
||||
private static final Pattern IPV6_MIXED_UNCOMPRESSED_REGEX = Pattern
|
||||
.compile("^" + "(?:[0-9a-fA-F]{1,4}:){6}" + "$");
|
||||
|
||||
/**
|
||||
* Check if <code>input</code> is a valid IPv4 address.
|
||||
* The format is 'xxx.xxx.xxx.xxx'. Four blocks of integer numbers ranging from 0 to 255
|
||||
* are required. Letters are not allowed.
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv4 notation.
|
||||
*/
|
||||
public static boolean isIPv4Address(final String input) {
|
||||
return IPV4_PATTERN.matcher(input).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given address is a valid IPv6 address in the standard format
|
||||
* The format is 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. Eight blocks of hexadecimal digits
|
||||
* are required.
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv6 notation.
|
||||
*/
|
||||
public static boolean isIPv6StdAddress(final String input) {
|
||||
return IPV6_STD_PATTERN.matcher(input).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given address is a valid IPv6 address in the hex-compressed notation
|
||||
* The format is 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. If all digits in a block are '0'
|
||||
* the block can be left empty.
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv6 (hex-compressed) notation.
|
||||
*/
|
||||
public static boolean isIPv6HexCompressedAddress(final String input) {
|
||||
return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if <code>input</code> is a IPv6 address.
|
||||
* Possible notations for valid IPv6 are:
|
||||
* - Standard IPv6 address
|
||||
* - Hex-compressed IPv6 address
|
||||
* - Link-local IPv6 address
|
||||
* - IPv4-mapped-to-IPV6 address
|
||||
* - IPv6 mixed address
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv6 notation.
|
||||
*/
|
||||
public static boolean isIPv6Address(final String input) {
|
||||
return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input) || isLinkLocalIPv6WithZoneIndex(input)
|
||||
|| isIPv6IPv4MappedAddress(input) || isIPv6MixedAddress(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given address is a valid IPv6 address in the mixed-standard or mixed-compressed notation.
|
||||
* IPV6 Mixed mode consists of two parts, the first 96 bits (up to 6 blocks of 4 hex digits) are IPv6
|
||||
* the IPV6 part can be either compressed or uncompressed
|
||||
* the second block is a full IPv4 address
|
||||
* e.g. '0:0:0:0:0:0:172.12.55.18'
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv6 (mixed-standard or mixed-compressed) notation.
|
||||
*/
|
||||
public static boolean isIPv6MixedAddress(final String input) {
|
||||
int splitIndex = input.lastIndexOf(':');
|
||||
|
||||
if (splitIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//the last part is a ipv4 address
|
||||
boolean ipv4PartValid = isIPv4Address(input.substring(splitIndex + 1));
|
||||
|
||||
String ipV6Part = input.substring(ZERO, splitIndex + 1);
|
||||
if (DOUBLE_COLON.equals(ipV6Part)) {
|
||||
return ipv4PartValid;
|
||||
}
|
||||
|
||||
boolean ipV6UncompressedDetected = IPV6_MIXED_UNCOMPRESSED_REGEX.matcher(ipV6Part).matches();
|
||||
boolean ipV6CompressedDetected = IPV6_MIXED_COMPRESSED_REGEX.matcher(ipV6Part).matches();
|
||||
|
||||
return ipv4PartValid && (ipV6UncompressedDetected || ipV6CompressedDetected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if <code>input</code> is an IPv4 address mapped into a IPv6 address. These are
|
||||
* starting with "::ffff:" followed by the IPv4 address in a dot-seperated notation.
|
||||
* The format is '::ffff:d.d.d.d'
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if <code>input</code> is in correct IPv6 notation containing an IPv4 address
|
||||
*/
|
||||
public static boolean isIPv6IPv4MappedAddress(final String input) {
|
||||
if (input.length() > SEVEN && input.substring(ZERO, SEVEN).equalsIgnoreCase(DOUBLE_COLON_FFFF)) {
|
||||
String lowerPart = input.substring(SEVEN);
|
||||
return isIPv4Address(lowerPart);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if <code>input</code> is a link local IPv6 address starting with "fe80:" and containing
|
||||
* a zone index with "%xxx". The zone index will not be checked.
|
||||
*
|
||||
* @param input ip-address to check
|
||||
* @return true if address part of <code>input</code> is in correct IPv6 notation.
|
||||
*/
|
||||
public static boolean isLinkLocalIPv6WithZoneIndex(String input) {
|
||||
if (input.length() > FIVE && input.substring(ZERO, FIVE).equalsIgnoreCase(FE80)) {
|
||||
int lastIndex = input.lastIndexOf(PERCENT);
|
||||
if (lastIndex > ZERO && lastIndex < (input.length() - 1)) {
|
||||
String ipPart = input.substring(ZERO, lastIndex);
|
||||
return isIPv6StdAddress(ipPart) || isIPv6HexCompressedAddress(ipPart);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if <code>input</code> is a valid IPv4 or IPv6 address.
|
||||
*
|
||||
* @param ipAddress ip-address to check
|
||||
* @return <code>true</code> if <code>ipAddress</code> is a valid ip-address
|
||||
*/
|
||||
public static boolean isValidIP(String ipAddress) {
|
||||
if (ipAddress == null || ipAddress.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isIPv4Address(ipAddress) || isIPv6Address(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* get to ipv4 pattern.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Pattern getIpv4Pattern() {
|
||||
return IPV4_PATTERN;
|
||||
}
|
||||
|
||||
}
|
@ -71,6 +71,18 @@ public class IPUtilTest {
|
||||
Assert.assertEquals("", IPUtil.getIPFromString(
|
||||
"jdbc:mysql://666.288.333.444:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000"
|
||||
+ "&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"));
|
||||
Assert.assertEquals("", IPUtil.getIPFromString(
|
||||
"jdbc:mysql://292.168.1.1:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000"
|
||||
+ "&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"));
|
||||
Assert.assertEquals("", IPUtil.getIPFromString(
|
||||
"jdbc:mysql://29.168.1.288:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000"
|
||||
+ "&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"));
|
||||
Assert.assertEquals("", IPUtil.getIPFromString(
|
||||
"jdbc:mysql://29.168.288.28:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000"
|
||||
+ "&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"));
|
||||
Assert.assertEquals("", IPUtil.getIPFromString(
|
||||
"jdbc:mysql://29.288.28.28:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000"
|
||||
+ "&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -36,11 +36,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
@ -45,6 +45,12 @@ public class CapacityController {
|
||||
|
||||
private final CapacityService capacityService;
|
||||
|
||||
private static final int STATUS200 = 200;
|
||||
|
||||
private static final int STATUS400 = 400;
|
||||
|
||||
private static final int STATUS500 = 500;
|
||||
|
||||
@Autowired
|
||||
public CapacityController(CapacityService capacityService) {
|
||||
this.capacityService = capacityService;
|
||||
@ -55,25 +61,25 @@ public class CapacityController {
|
||||
@RequestParam(required = false) String tenant) {
|
||||
if (group == null && tenant == null) {
|
||||
RestResult<Capacity> restResult = new RestResult<Capacity>();
|
||||
response.setStatus(400);
|
||||
restResult.setCode(400);
|
||||
restResult.setMessage("参数group和tenant不能同时为空");
|
||||
response.setStatus(STATUS400);
|
||||
restResult.setCode(STATUS400);
|
||||
restResult.setMessage("The parameter group and tenant cannot be empty at the same time");
|
||||
return restResult;
|
||||
}
|
||||
if (group == null && StringUtils.isBlank(tenant)) {
|
||||
RestResult<Capacity> restResult = new RestResult<Capacity>();
|
||||
response.setStatus(400);
|
||||
restResult.setCode(400);
|
||||
restResult.setMessage("tenant不能为空字符串");
|
||||
response.setStatus(STATUS400);
|
||||
restResult.setCode(STATUS400);
|
||||
restResult.setMessage("tenant cannot be an empty string");
|
||||
return restResult;
|
||||
}
|
||||
RestResult<Capacity> restResult = new RestResult<Capacity>();
|
||||
try {
|
||||
response.setStatus(200);
|
||||
restResult.setCode(200);
|
||||
response.setStatus(STATUS200);
|
||||
restResult.setCode(STATUS200);
|
||||
Capacity capacity = capacityService.getCapacityWithDefault(group, tenant);
|
||||
if (capacity == null) {
|
||||
LOGGER.warn("[getCapacity] capacity不存在,需初始化 group: {}, tenant: {}", group, tenant);
|
||||
LOGGER.warn("[getCapacity] capacity not exist,need init group: {}, tenant: {}", group, tenant);
|
||||
capacityService.initCapacity(group, tenant);
|
||||
capacity = capacityService.getCapacityWithDefault(group, tenant);
|
||||
}
|
||||
@ -82,8 +88,8 @@ public class CapacityController {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[getCapacity] ", e);
|
||||
response.setStatus(500);
|
||||
restResult.setCode(500);
|
||||
response.setStatus(STATUS500);
|
||||
restResult.setCode(STATUS500);
|
||||
restResult.setMessage(e.getMessage());
|
||||
}
|
||||
return restResult;
|
||||
@ -100,14 +106,15 @@ public class CapacityController {
|
||||
if (StringUtils.isBlank(group) && StringUtils.isBlank(tenant)) {
|
||||
capacityService.initAllCapacity();
|
||||
RestResult<Boolean> restResult = new RestResult<Boolean>();
|
||||
setFailResult(response, restResult, 400);
|
||||
restResult.setMessage("参数group和tenant不能同时为空");
|
||||
setFailResult(response, restResult, STATUS400);
|
||||
restResult.setMessage("The parameter group and tenant cannot be empty at the same time");
|
||||
return restResult;
|
||||
}
|
||||
if (quota == null && maxSize == null && maxAggrCount == null && maxAggrSize == null) {
|
||||
RestResult<Boolean> restResult = new RestResult<Boolean>();
|
||||
setFailResult(response, restResult, 400);
|
||||
restResult.setMessage("参数quota、maxSize、maxAggrCount、maxAggrSize不能同时为空");
|
||||
setFailResult(response, restResult, STATUS400);
|
||||
restResult.setMessage(
|
||||
"The parameters quota, maxSize, maxAggrCount, maxAggrSize cannot be empty at the same time");
|
||||
return restResult;
|
||||
}
|
||||
String targetFieldName;
|
||||
@ -121,8 +128,8 @@ public class CapacityController {
|
||||
}
|
||||
RestResult<Boolean> restResult = new RestResult<Boolean>();
|
||||
if (StringUtils.isBlank(targetFieldValue)) {
|
||||
setFailResult(response, restResult, 400);
|
||||
restResult.setMessage(String.format("参数%s为空", targetFieldName));
|
||||
setFailResult(response, restResult, STATUS400);
|
||||
restResult.setMessage(String.format("parameter %s is empty.", targetFieldName));
|
||||
return restResult;
|
||||
}
|
||||
try {
|
||||
@ -130,15 +137,19 @@ public class CapacityController {
|
||||
.insertOrUpdateCapacity(group, tenant, quota, maxSize, maxAggrCount, maxAggrSize);
|
||||
if (insertOrUpdateResult) {
|
||||
setSuccessResult(response, restResult);
|
||||
restResult.setMessage(String.format("成功更新%s为%s的容量信息配置", targetFieldName, targetFieldValue));
|
||||
restResult.setMessage(
|
||||
String.format("successfully updated the capacity information configuration of %s to %s",
|
||||
targetFieldName, targetFieldValue));
|
||||
return restResult;
|
||||
}
|
||||
setFailResult(response, restResult, 500);
|
||||
restResult.setMessage(String.format("%s为%s的容量信息配置更新失败", targetFieldName, targetFieldValue));
|
||||
setFailResult(response, restResult, STATUS500);
|
||||
restResult.setMessage(
|
||||
String.format("failed updated the capacity information configuration of %s to %s", targetFieldName,
|
||||
targetFieldValue));
|
||||
return restResult;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[updateCapacity] ", e);
|
||||
setFailResult(response, restResult, 500);
|
||||
setFailResult(response, restResult, STATUS500);
|
||||
restResult.setMessage(e.getMessage());
|
||||
return restResult;
|
||||
}
|
||||
@ -151,8 +162,8 @@ public class CapacityController {
|
||||
}
|
||||
|
||||
private void setSuccessResult(HttpServletResponse response, RestResult<Boolean> restResult) {
|
||||
response.setStatus(200);
|
||||
restResult.setCode(200);
|
||||
response.setStatus(STATUS200);
|
||||
restResult.setCode(STATUS200);
|
||||
restResult.setData(true);
|
||||
}
|
||||
}
|
||||
|
@ -400,27 +400,31 @@ public class LongPollingService {
|
||||
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
|
||||
|
||||
// Delete subscriber's relations.
|
||||
allSubs.remove(ClientLongPolling.this);
|
||||
boolean removeFlag = allSubs.remove(ClientLongPolling.this);
|
||||
|
||||
if (isFixedPolling()) {
|
||||
LogUtil.CLIENT_LOG
|
||||
.info("{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - createTime), "fix",
|
||||
RequestUtil.getRemoteIp((HttpServletRequest) asyncContext.getRequest()),
|
||||
"polling", clientMd5Map.size(), probeRequestSize);
|
||||
List<String> changedGroups = MD5Util
|
||||
.compareMd5((HttpServletRequest) asyncContext.getRequest(),
|
||||
(HttpServletResponse) asyncContext.getResponse(), clientMd5Map);
|
||||
if (changedGroups.size() > 0) {
|
||||
sendResponse(changedGroups);
|
||||
if (removeFlag) {
|
||||
if (isFixedPolling()) {
|
||||
LogUtil.CLIENT_LOG
|
||||
.info("{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - createTime), "fix",
|
||||
RequestUtil.getRemoteIp((HttpServletRequest) asyncContext.getRequest()),
|
||||
"polling", clientMd5Map.size(), probeRequestSize);
|
||||
List<String> changedGroups = MD5Util
|
||||
.compareMd5((HttpServletRequest) asyncContext.getRequest(),
|
||||
(HttpServletResponse) asyncContext.getResponse(), clientMd5Map);
|
||||
if (changedGroups.size() > 0) {
|
||||
sendResponse(changedGroups);
|
||||
} else {
|
||||
sendResponse(null);
|
||||
}
|
||||
} else {
|
||||
LogUtil.CLIENT_LOG
|
||||
.info("{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - createTime), "timeout",
|
||||
RequestUtil.getRemoteIp((HttpServletRequest) asyncContext.getRequest()),
|
||||
"polling", clientMd5Map.size(), probeRequestSize);
|
||||
sendResponse(null);
|
||||
}
|
||||
} else {
|
||||
LogUtil.CLIENT_LOG
|
||||
.info("{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - createTime), "timeout",
|
||||
RequestUtil.getRemoteIp((HttpServletRequest) asyncContext.getRequest()),
|
||||
"polling", clientMd5Map.size(), probeRequestSize);
|
||||
sendResponse(null);
|
||||
LogUtil.DEFAULT_LOG.warn("client subsciber's relations delete fail.");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LogUtil.DEFAULT_LOG.error("long polling error:" + t.getMessage(), t.getCause());
|
||||
|
@ -16,21 +16,12 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.common.task.NacosTask;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -39,6 +30,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Nacos
|
||||
*/
|
||||
public class NotifySingleService {
|
||||
private static final Logger LOGGER = LogUtil.FATAL_LOG;
|
||||
|
||||
static class NotifyTaskProcessorWrapper extends NotifyTaskProcessor {
|
||||
|
||||
@ -84,7 +76,7 @@ public class NotifySingleService {
|
||||
.error("[notify-exception] target:{} dataid:{} group:{} ts:{}", target, getDataId(), getGroup(),
|
||||
getLastModified());
|
||||
LogUtil.NOTIFY_LOG.debug("[notify-exception] target:{} dataid:{} group:{} ts:{}",
|
||||
new Object[] {target, getDataId(), getGroup(), getLastModified()}, e);
|
||||
target, getDataId(), getGroup(), getLastModified(), e);
|
||||
}
|
||||
|
||||
if (!this.isSuccess) {
|
||||
@ -100,59 +92,4 @@ public class NotifySingleService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public NotifySingleService(ServerMemberManager memberManager) {
|
||||
this.memberManager = memberManager;
|
||||
setupNotifyExecutors();
|
||||
}
|
||||
|
||||
/**
|
||||
* When the system is started or when the cluster is expanded or offline: single-threaded setupNotifyExecutors
|
||||
* executors use ConcurrentHashMap to ensure visibility.
|
||||
*/
|
||||
private void setupNotifyExecutors() {
|
||||
Collection<Member> clusterIps = memberManager.allMembers();
|
||||
|
||||
for (Member member : clusterIps) {
|
||||
|
||||
final String address = member.getAddress();
|
||||
|
||||
/*
|
||||
* Fixed number of threads, unbounded queue
|
||||
* (based on assumption: thread pool throughput is good,
|
||||
* there will be no continuous task accumulation,
|
||||
* there is occasional instantaneous pressure)
|
||||
*/
|
||||
Executor executor = ExecutorFactory.newSingleScheduledExecutorService(
|
||||
new NameThreadFactory("com.alibaba.nacos.config.NotifySingleServiceThread-" + address));
|
||||
|
||||
if (null == executors.putIfAbsent(address, executor)) {
|
||||
LOGGER.warn("[notify-thread-pool] setup thread target ip {} ok.", address);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Executor> entry : executors.entrySet()) {
|
||||
String target = entry.getKey();
|
||||
|
||||
// The cluster node goes offline
|
||||
if (!clusterIps.contains(target)) {
|
||||
ThreadPoolExecutor executor = (ThreadPoolExecutor) entry.getValue();
|
||||
executor.shutdown();
|
||||
executors.remove(target);
|
||||
LOGGER.warn("[notify-thread-pool] tear down thread target ip {} ok.", target);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LogUtil.FATAL_LOG;
|
||||
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
private ConcurrentHashMap<String, Executor> executors = new ConcurrentHashMap<String, Executor>();
|
||||
|
||||
public ConcurrentHashMap<String, Executor> getExecutors() {
|
||||
return executors;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@ -90,7 +91,8 @@ public class RequestUtil {
|
||||
*/
|
||||
public static String getSrcUserName(HttpServletRequest request) {
|
||||
User user = getUser(request);
|
||||
return user == null ? null : user.getUserName();
|
||||
// If auth is disabled, get username from parameters by agreed key
|
||||
return user == null ? request.getParameter(Constants.USERNAME) : user.getUserName();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -497,13 +497,13 @@ const request = (function(_global) {
|
||||
try {
|
||||
token = JSON.parse(localStorage.token);
|
||||
} catch (e) {
|
||||
console.log('Token Erro', localStorage.token, e);
|
||||
console.log('Token Error', localStorage.token, e);
|
||||
goLogin();
|
||||
}
|
||||
const { accessToken = '' } = token;
|
||||
const { accessToken = '', username = '' } = token;
|
||||
const [url, paramsStr = ''] = config.url.split('?');
|
||||
const params = paramsStr.split('&');
|
||||
params.push(`accessToken=${accessToken}`);
|
||||
params.push(`accessToken=${accessToken}&username=${username}`);
|
||||
|
||||
return $.ajax(
|
||||
Object.assign({}, config, {
|
||||
|
@ -244,6 +244,7 @@ const I18N_CONF = {
|
||||
home: 'Application:',
|
||||
actionType: 'Action Type:',
|
||||
operator: 'Operator:',
|
||||
sourceIp: 'Source IP',
|
||||
configureContent: 'Configuration Content:',
|
||||
back: 'Back',
|
||||
},
|
||||
@ -252,6 +253,7 @@ const I18N_CONF = {
|
||||
viewDetails1: 'view details',
|
||||
},
|
||||
ConfigurationManagement: {
|
||||
exportBtn: 'Export',
|
||||
questionnaire2: 'questionnaire',
|
||||
ad:
|
||||
'a ACM front-end monitoring questionnaire, the time limit to receive Ali cloud voucher details shoved stamp: the',
|
||||
@ -539,6 +541,7 @@ const I18N_CONF = {
|
||||
rollbackDelete: 'Delete',
|
||||
update: 'Update',
|
||||
insert: 'Insert',
|
||||
additionalRollbackMessage: 'This operation will delete the below config!',
|
||||
},
|
||||
UserManagement: {
|
||||
userManagement: 'User Management',
|
||||
|
@ -244,6 +244,7 @@ const I18N_CONF = {
|
||||
actionType: '操作类型:',
|
||||
configureContent: '配置内容:',
|
||||
operator: '操作人:',
|
||||
sourceIp: '来源 IP:',
|
||||
back: '返回',
|
||||
},
|
||||
DashboardCard: {
|
||||
@ -251,6 +252,7 @@ const I18N_CONF = {
|
||||
viewDetails1: '查看详情',
|
||||
},
|
||||
ConfigurationManagement: {
|
||||
exportBtn: '导出',
|
||||
questionnaire2: '问卷调查',
|
||||
ad: '答 ACM 前端监控调查问卷,限时领取阿里云代金券\t 详情猛戳:',
|
||||
noLongerDisplay4: '不再显示:',
|
||||
@ -535,6 +537,7 @@ const I18N_CONF = {
|
||||
rollbackDelete: '删除',
|
||||
update: '更新',
|
||||
insert: '插入',
|
||||
additionalRollbackMessage: '此操作将删除以下配置!',
|
||||
},
|
||||
UserManagement: {
|
||||
userManagement: '用户管理',
|
||||
|
@ -92,7 +92,11 @@ class PermissionsManagement extends React.Component {
|
||||
<>
|
||||
<RegionGroup left={locale.privilegeManagement} />
|
||||
<div className="filter-panel">
|
||||
<Button type="primary" onClick={() => this.setState({ createPermissionVisible: true })}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ createPermissionVisible: true })}
|
||||
style={{ marginRight: 20 }}
|
||||
>
|
||||
{locale.addPermission}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getPermissions()}>
|
||||
|
@ -72,7 +72,11 @@ class RolesManagement extends React.Component {
|
||||
<>
|
||||
<RegionGroup left={locale.roleManagement} />
|
||||
<div className="filter-panel">
|
||||
<Button type="primary" onClick={() => this.setState({ createRoleVisible: true })}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ createRoleVisible: true })}
|
||||
style={{ marginRight: 20 }}
|
||||
>
|
||||
{locale.bindingRoles}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getRoles()}>
|
||||
|
@ -74,7 +74,11 @@ class UserManagement extends React.Component {
|
||||
<>
|
||||
<RegionGroup left={locale.userManagement} />
|
||||
<div className="filter-panel">
|
||||
<Button type="primary" onClick={() => this.setState({ createUserVisible: true })}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ createUserVisible: true })}
|
||||
style={{ marginRight: 20 }}
|
||||
>
|
||||
{locale.createUser}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getUsers()}>
|
||||
|
@ -86,7 +86,7 @@ class ConfigRollback extends React.Component {
|
||||
self.field.setValue('dataId', data.dataId);
|
||||
self.field.setValue('content', data.content);
|
||||
self.field.setValue('appName', data.appName);
|
||||
self.field.setValue('opType', self.typeMapName[data.opType.trim()]);
|
||||
self.field.setValue('opType', data.opType.trim());
|
||||
self.opType = data.opType; // 当前回滚类型I:插入,D:删除,U:'更新'
|
||||
self.field.setValue('group', data.group);
|
||||
self.field.setValue('md5', data.md5);
|
||||
@ -111,15 +111,17 @@ class ConfigRollback extends React.Component {
|
||||
const { locale = {} } = this.props;
|
||||
const self = this;
|
||||
let type = 'post';
|
||||
let additionalMsg = '';
|
||||
if (this.opType.trim() === 'I') {
|
||||
type = 'delete';
|
||||
additionalMsg = locale.additionalRollbackMessage;
|
||||
}
|
||||
Dialog.confirm({
|
||||
title: locale.rollBack,
|
||||
content: (
|
||||
<div style={{ marginTop: '-20px' }}>
|
||||
<div style={{ marginTop: '-20px', maxWidth: '500px' }}>
|
||||
<h3>
|
||||
{locale.determine} {locale.followingConfiguration}
|
||||
{locale.determine} {locale.followingConfiguration} {additionalMsg}
|
||||
</h3>
|
||||
<p>
|
||||
<span style={{ color: '#999', marginRight: 5 }}>Data ID:</span>
|
||||
@ -166,6 +168,18 @@ class ConfigRollback extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getOpType(type, locale) {
|
||||
if (type) {
|
||||
const typeMap = {
|
||||
U: locale.update,
|
||||
I: locale.insert,
|
||||
D: locale.deleteAction,
|
||||
};
|
||||
return typeMap[type];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
render() {
|
||||
const { locale = {} } = this.props;
|
||||
const { init } = this.field;
|
||||
@ -177,6 +191,7 @@ class ConfigRollback extends React.Component {
|
||||
span: 18,
|
||||
},
|
||||
};
|
||||
const { getOpType } = this;
|
||||
return (
|
||||
<div style={{ padding: 10 }}>
|
||||
<h1>{locale.configurationRollback}</h1>
|
||||
@ -198,7 +213,7 @@ class ConfigRollback extends React.Component {
|
||||
</FormItem>
|
||||
</div>
|
||||
<FormItem label={locale.actionType} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('opType')} />
|
||||
<Input htmlType="text" readOnly value={getOpType(init('opType').value, locale)} />
|
||||
</FormItem>
|
||||
<FormItem label="MD5:" required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('md5')} />
|
||||
|
@ -33,6 +33,8 @@ import {
|
||||
Table,
|
||||
Upload,
|
||||
Message,
|
||||
MenuButton,
|
||||
Box,
|
||||
} from '@alifd/next';
|
||||
import BatchHandle from 'components/BatchHandle';
|
||||
import RegionGroup from 'components/RegionGroup';
|
||||
@ -46,6 +48,7 @@ import { getConfigs } from '../../../reducers/configuration';
|
||||
import './index.scss';
|
||||
import { LANGUAGE_KEY, GLOBAL_PAGE_SIZE_LIST } from '../../../constants';
|
||||
|
||||
const { Item } = MenuButton;
|
||||
const { Panel } = Collapse;
|
||||
const configsTableSelected = new Map();
|
||||
@connect(
|
||||
@ -515,7 +518,7 @@ class ConfigurationManagement extends React.Component {
|
||||
|
||||
exportData() {
|
||||
const { group, appName, dataId, openUri } = this;
|
||||
const { accessToken = '' } = JSON.parse(localStorage.token || '{}');
|
||||
const { accessToken = '', username = '' } = JSON.parse(localStorage.token || '{}');
|
||||
openUri('v1/cs/configs', {
|
||||
export: 'true',
|
||||
tenant: getParams('namespace'),
|
||||
@ -524,12 +527,13 @@ class ConfigurationManagement extends React.Component {
|
||||
dataId,
|
||||
ids: '',
|
||||
accessToken,
|
||||
username,
|
||||
});
|
||||
}
|
||||
|
||||
exportDataNew() {
|
||||
const { group, appName, dataId, openUri } = this;
|
||||
const { accessToken = '' } = JSON.parse(localStorage.token || '{}');
|
||||
const { accessToken = '', username = '' } = JSON.parse(localStorage.token || '{}');
|
||||
openUri('v1/cs/configs', {
|
||||
exportV2: 'true',
|
||||
tenant: getParams('namespace'),
|
||||
@ -538,13 +542,14 @@ class ConfigurationManagement extends React.Component {
|
||||
dataId,
|
||||
ids: '',
|
||||
accessToken,
|
||||
username,
|
||||
});
|
||||
}
|
||||
|
||||
exportSelectedData(newVersion) {
|
||||
const ids = [];
|
||||
const { locale = {} } = this.props;
|
||||
const { accessToken = '' } = JSON.parse(localStorage.token || '{}');
|
||||
const { accessToken = '', username = '' } = JSON.parse(localStorage.token || '{}');
|
||||
if (!configsTableSelected.size) {
|
||||
Dialog.alert({
|
||||
title: locale.exportSelectedAlertTitle,
|
||||
@ -561,6 +566,7 @@ class ConfigurationManagement extends React.Component {
|
||||
appName: '',
|
||||
ids: ids.join(','),
|
||||
accessToken,
|
||||
username,
|
||||
});
|
||||
} else {
|
||||
this.openUri('v1/cs/configs', {
|
||||
@ -570,6 +576,7 @@ class ConfigurationManagement extends React.Component {
|
||||
appName: '',
|
||||
ids: ids.join(','),
|
||||
accessToken,
|
||||
username,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -956,12 +963,12 @@ class ConfigurationManagement extends React.Component {
|
||||
console.log(e);
|
||||
goLogin();
|
||||
}
|
||||
const { accessToken = '' } = token;
|
||||
const { accessToken = '', username = '' } = token;
|
||||
const uploadProps = {
|
||||
accept: 'application/zip',
|
||||
action: `v1/cs/configs?import=true&namespace=${getParams(
|
||||
'namespace'
|
||||
)}&accessToken=${accessToken}`,
|
||||
)}&accessToken=${accessToken}&username=${username}`,
|
||||
headers: Object.assign({}, {}, { accessToken }),
|
||||
data: {
|
||||
policy: self.field.getValue('sameConfigPolicy'),
|
||||
@ -1163,42 +1170,24 @@ class ConfigurationManagement extends React.Component {
|
||||
style={
|
||||
this.inApp
|
||||
? { display: 'none' }
|
||||
: { verticalAlign: 'middle', marginTop: 0, marginLeft: 10 }
|
||||
: { verticalAlign: 'middle', marginTop: 0, marginLeft: 0 }
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{ color: '#33cde5', fontSize: 12, cursor: 'pointer' }}
|
||||
onClick={this.changeAdvancedQuery}
|
||||
>
|
||||
<span style={{ marginRight: 5, lineHeight: '28px' }}>
|
||||
{locale.advancedQuery9}
|
||||
</span>
|
||||
<Icon
|
||||
type={this.state.isAdvancedQuery ? 'arrow-up-filling' : 'arrow-down-filling'}
|
||||
size={'xs'}
|
||||
/>
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Form.Item label={''}>
|
||||
<Button
|
||||
type={'primary'}
|
||||
style={{ marginRight: 10 }}
|
||||
onClick={this.exportData.bind(this)}
|
||||
data-spm-click={'gostr=/aliyun;locaid=configsExport'}
|
||||
>
|
||||
{locale.export}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item label={''}>
|
||||
<Button
|
||||
type={'primary'}
|
||||
style={{ marginRight: 10 }}
|
||||
onClick={this.exportDataNew.bind(this)}
|
||||
data-spm-click={'gostr=/aliyun;locaid=configsExport'}
|
||||
>
|
||||
{locale.newExport}
|
||||
<Button onClick={this.changeAdvancedQuery}>
|
||||
{this.state.isAdvancedQuery ? (
|
||||
<>
|
||||
{locale.advancedQuery9}
|
||||
<Icon type="arrow-up" size="xs" style={{ marginLeft: '5px' }} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{locale.advancedQuery9}
|
||||
<Icon type="arrow-down" size="xs" style={{ marginLeft: '5px' }} />
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={''}>
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -1287,16 +1276,7 @@ class ConfigurationManagement extends React.Component {
|
||||
locaid: 'configsDelete',
|
||||
onClick: () => this.multipleSelectionDeletion(),
|
||||
},
|
||||
{
|
||||
text: locale.exportSelected,
|
||||
locaid: 'configsExport',
|
||||
onClick: () => this.exportSelectedData(false),
|
||||
},
|
||||
{
|
||||
text: locale.newExportSelected,
|
||||
locaid: 'configsExport',
|
||||
onClick: () => this.exportSelectedData(true),
|
||||
},
|
||||
|
||||
{
|
||||
text: locale.clone,
|
||||
locaid: 'configsDelete',
|
||||
@ -1313,6 +1293,38 @@ class ConfigurationManagement extends React.Component {
|
||||
{item.text}
|
||||
</Button>
|
||||
))}
|
||||
<MenuButton
|
||||
type="primary"
|
||||
label={locale.exportBtn}
|
||||
popupStyle={{ minWidth: 150 }}
|
||||
>
|
||||
{[
|
||||
{
|
||||
text: locale.export,
|
||||
locaid: 'exportData',
|
||||
onClick: () => this.exportData(this),
|
||||
},
|
||||
{
|
||||
text: locale.newExport,
|
||||
locaid: 'exportDataNew',
|
||||
onClick: () => this.exportDataNew(this),
|
||||
},
|
||||
{
|
||||
text: locale.exportSelected,
|
||||
locaid: 'configsExport',
|
||||
onClick: () => this.exportSelectedData(false),
|
||||
},
|
||||
{
|
||||
text: locale.newExportSelected,
|
||||
locaid: 'configsExport',
|
||||
onClick: () => this.exportSelectedData(true),
|
||||
},
|
||||
].map((item, index) => (
|
||||
<Item key={item.text} style={{ minWidth: 150 }} onClick={item.onClick}>
|
||||
{item.text}
|
||||
</Item>
|
||||
))}
|
||||
</MenuButton>
|
||||
</div>
|
||||
<Pagination
|
||||
style={{ float: 'right' }}
|
||||
|
@ -60,11 +60,6 @@ class HistoryDetail extends React.Component {
|
||||
getDataDetail() {
|
||||
const { locale = {} } = this.props;
|
||||
const self = this;
|
||||
const typeMap = {
|
||||
U: locale.update,
|
||||
I: locale.insert,
|
||||
D: locale.deleteAction,
|
||||
};
|
||||
request({
|
||||
url: `v1/cs/history?dataId=${this.dataId}&group=${this.group}&nid=${this.nid}`,
|
||||
success(result) {
|
||||
@ -74,8 +69,9 @@ class HistoryDetail extends React.Component {
|
||||
self.field.setValue('content', data.content);
|
||||
self.field.setValue('appName', self.inApp ? self.edasAppName : data.appName);
|
||||
self.field.setValue('envs', self.serverId);
|
||||
self.field.setValue('srcUser', self.srcUser);
|
||||
self.field.setValue('opType', typeMap[data.opType.trim()]);
|
||||
self.field.setValue('srcUser', data.srcUser);
|
||||
self.field.setValue('srcIp', data.srcIp);
|
||||
self.field.setValue('opType', data.opType.trim());
|
||||
self.field.setValue('group', data.group);
|
||||
self.field.setValue('md5', data.md5);
|
||||
}
|
||||
@ -85,10 +81,22 @@ class HistoryDetail extends React.Component {
|
||||
|
||||
goList() {
|
||||
this.props.history.push(
|
||||
`/historyRollback?serverId=${this.serverId}&group=${this.group}&dataId=${this.dataId}&namespace=${this.tenant}`
|
||||
`/historyRollback?serverId=${this.serverId}&historyGroup=${this.group}&historyDataId=${this.dataId}&namespace=${this.tenant}`
|
||||
);
|
||||
}
|
||||
|
||||
getOpType(type, locale) {
|
||||
if (type) {
|
||||
const typeMap = {
|
||||
U: locale.update,
|
||||
I: locale.insert,
|
||||
D: locale.deleteAction,
|
||||
};
|
||||
return typeMap[type];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
render() {
|
||||
const { locale = {} } = this.props;
|
||||
const { init } = this.field;
|
||||
@ -100,6 +108,7 @@ class HistoryDetail extends React.Component {
|
||||
span: 18,
|
||||
},
|
||||
};
|
||||
const { getOpType } = this;
|
||||
return (
|
||||
<div style={{ padding: 10 }}>
|
||||
<h1>{locale.historyDetails}</h1>
|
||||
@ -123,8 +132,11 @@ class HistoryDetail extends React.Component {
|
||||
<Form.Item label={locale.operator} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('srcUser')} />
|
||||
</Form.Item>
|
||||
<Form.Item label={locale.sourceIp} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('srcIp')} />
|
||||
</Form.Item>
|
||||
<Form.Item label={locale.actionType} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('opType')} />
|
||||
<Input htmlType="text" readOnly value={getOpType(init('opType').value, locale)} />
|
||||
</Form.Item>
|
||||
<Form.Item label="MD5:" required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('md5')} />
|
||||
|
@ -203,6 +203,10 @@ class ListeningToQuery extends React.Component {
|
||||
dataSource={selectDataSource}
|
||||
style={{ width: 200 }}
|
||||
{...this.init('type')}
|
||||
onChange={value => {
|
||||
this.field.setValue('type', value);
|
||||
this.queryTrackQuery();
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
|
@ -47,8 +47,9 @@ const request = () => {
|
||||
console.log(e);
|
||||
goLogin();
|
||||
}
|
||||
const { accessToken = '' } = token;
|
||||
const { accessToken = '', username = '' } = token;
|
||||
config.params.accessToken = accessToken;
|
||||
config.params.username = username;
|
||||
config.headers = Object.assign({}, headers, { accessToken });
|
||||
}
|
||||
if (data && isPlainObject(data) && ['post', 'put'].includes(method)) {
|
||||
|
@ -66,12 +66,6 @@
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
</dependency>
|
||||
<!-- log -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
|
@ -211,26 +211,26 @@ public class UserController {
|
||||
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, NacosAuthConfig.TOKEN_PREFIX + user.getToken());
|
||||
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
// JSONObject result = new JSONObject();
|
||||
result.put(Constants.ACCESS_TOKEN, user.getToken());
|
||||
result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());
|
||||
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
|
||||
result.put(Constants.USERNAME, user.getUserName());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationToken
|
||||
// create Authentication class through username and password, the implement class is UsernamePasswordAuthenticationToken
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
|
||||
RestResult<String> rr = new RestResult<String>();
|
||||
try {
|
||||
//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象
|
||||
// use the method authenticate of AuthenticationManager(default implement is ProviderManager) to valid Authentication
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
//将 Authentication 绑定到 SecurityContext
|
||||
// bind SecurityContext to Authentication
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
//生成Token
|
||||
// generate Token
|
||||
String token = jwtTokenManager.createToken(authentication);
|
||||
//将Token写入到Http头部
|
||||
// write Token to Http header
|
||||
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);
|
||||
rr.setCode(200);
|
||||
rr.setData("Bearer " + token);
|
||||
|
@ -364,7 +364,7 @@
|
||||
* 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.
|
||||
*/.next-pagination-size-selector{position:static!important}.configuration-table{margin-bottom:20px}.next-sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;top:0;margin:-1px}.next-switch:after[dir=rtl]{content:" ";transition:all .1s linear;transform-origin:right center}.next-switch-medium[dir=rtl]:after,.next-switch-small[dir=rtl]:after{right:100%;transform:translateX(100%)}.next-switch-on[dir=rtl]>.next-switch-children{right:10px;left:auto;color:#fff}.next-switch-on[disabled][dir=rtl]:after{left:0;right:100%;box-shadow:1px 1px 3px 0 rgba(0,0,0,.12)}.next-switch-on.next-switch-small[dir=rtl]>.next-switch-children{right:6px;left:auto}.next-switch-off[dir=rtl]:after{right:0;transform:translateX(0);box-shadow:-1px 0 3px 0 rgba(0,0,0,.12)}.next-switch-off[dir=rtl]>.next-switch-children{left:10px;right:auto}.next-switch-off.next-switch-small[dir=rtl]>.next-switch-children{left:5px;right:auto}.next-switch{outline:none;text-align:left;transition:all .1s linear;overflow:hidden;cursor:pointer;user-select:none}.next-switch,.next-switch *,.next-switch :after,.next-switch :before{box-sizing:border-box}.next-switch:after{content:" ";transition:all .1s linear;transform-origin:left center}.next-switch-medium{width:56px;height:26px;border-radius:20px}.next-switch-medium:after{border:1px solid transparent;position:absolute;left:100%;transform:translateX(-100%);width:24px;height:24px;border-radius:20px;box-sizing:border-box}.next-switch-medium>.next-switch-children{font-size:12px;height:24px;line-height:24px}.next-switch-small{position:relative;display:inline-block;width:44px;height:22px}.next-switch-small,.next-switch-small:after{border:1px solid transparent;border-radius:20px}.next-switch-small:after{position:absolute;left:100%;transform:translateX(-100%);width:20px;height:20px;box-sizing:border-box}.next-switch-small>.next-switch-children{font-size:12px;position:absolute;height:20px;line-height:20px}.next-switch-on{background-color:#5584ff}.next-switch-on:after{box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#fff;border-color:transparent}.next-switch-on>.next-switch-children{left:10px}.next-switch-on:focus,.next-switch-on:hover{background-color:#3e71f7}.next-switch-on:focus:after,.next-switch-on:hover:after{background-color:#fff}.next-switch-on.next-switch-small>.next-switch-children{left:6px}.next-switch-on[disabled]{background-color:#ebecf0;cursor:not-allowed}.next-switch-on[disabled]:after{right:0;box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#f7f8fa;border-color:#e6e7eb}.next-switch-on[disabled]>.next-switch-children{color:#ccc}.next-switch-off{background-color:#fff;border-color:#c4c6cf}.next-switch-off:focus,.next-switch-off:hover{background-color:#f2f3f7;border-color:#c4c6cf}.next-switch-off:after{left:0;transform:translateX(0);box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#fff;border-color:transparent}.next-switch-off:after:focus,.next-switch-off:after:hover{background-color:#fff}.next-switch-off>.next-switch-children{right:10px;color:#999}.next-switch-off[disabled]{background-color:#f7f8fa;cursor:not-allowed}.next-switch-off[disabled]:after{box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#f7f8fa;border-color:#e6e7eb}.next-switch-off[disabled]>.next-switch-children{color:#c4c6cf}.next-switch-off.next-switch-small>.next-switch-children{right:5px}
|
||||
*/.next-pagination-size-selector{position:static!important}.configuration-table{margin-bottom:20px}.next-sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;top:0;margin:-1px}.next-switch:after[dir=rtl]{content:" ";transition:all .1s linear;transform-origin:right center}.next-switch-medium[dir=rtl]:after,.next-switch-small[dir=rtl]:after{right:100%;transform:translateX(100%)}.next-switch-on[dir=rtl]>.next-switch-children{right:10px;left:auto;color:#fff}.next-switch-on[disabled][dir=rtl]:after{left:0;right:100%;box-shadow:1px 1px 3px 0 rgba(0,0,0,.12)}.next-switch-on.next-switch-small[dir=rtl]>.next-switch-children{right:6px;left:auto}.next-switch-off[dir=rtl]:after{right:0;transform:translateX(0);box-shadow:-1px 0 3px 0 rgba(0,0,0,.12)}.next-switch-off[dir=rtl]>.next-switch-children{left:10px;right:auto}.next-switch-off.next-switch-small[dir=rtl]>.next-switch-children{left:5px;right:auto}.next-switch{outline:none;text-align:left;transition:all .1s linear;overflow:hidden;cursor:pointer}.next-switch,.next-switch *,.next-switch :after,.next-switch :before{box-sizing:border-box}.next-switch:after{content:" ";transition:all .1s linear;transform-origin:left center}.next-switch-medium{width:56px;height:26px;border-radius:20px}.next-switch-medium:after{border:1px solid transparent;position:absolute;left:100%;transform:translateX(-100%);width:24px;height:24px;border-radius:20px;box-sizing:border-box}.next-switch-medium>.next-switch-children{font-size:12px;height:24px;line-height:24px}.next-switch-small{position:relative;display:inline-block;width:44px;height:22px}.next-switch-small,.next-switch-small:after{border:1px solid transparent;border-radius:20px}.next-switch-small:after{position:absolute;left:100%;transform:translateX(-100%);width:20px;height:20px;box-sizing:border-box}.next-switch-small>.next-switch-children{font-size:12px;position:absolute;height:20px;line-height:20px}.next-switch-on{background-color:#5584ff}.next-switch-on:after{box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#fff;border-color:transparent}.next-switch-on>.next-switch-children{left:10px}.next-switch-on:focus,.next-switch-on:hover{background-color:#3e71f7}.next-switch-on:focus:after,.next-switch-on:hover:after{background-color:#fff}.next-switch-on.next-switch-small>.next-switch-children{left:6px}.next-switch-on[disabled]{background-color:#ebecf0;cursor:not-allowed}.next-switch-on[disabled]:after{right:0;box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#f7f8fa;border-color:#e6e7eb}.next-switch-on[disabled]>.next-switch-children{color:#ccc}.next-switch-off{background-color:#fff;border-color:#c4c6cf}.next-switch-off:focus,.next-switch-off:hover{background-color:#f2f3f7;border-color:#c4c6cf}.next-switch-off:after{left:0;transform:translateX(0);box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#fff;border-color:transparent}.next-switch-off:after:focus,.next-switch-off:after:hover{background-color:#fff}.next-switch-off>.next-switch-children{right:10px;color:#999}.next-switch-off[disabled]{background-color:#f7f8fa;cursor:not-allowed}.next-switch-off[disabled]:after{box-shadow:1px 1px 3px 0 rgba(0,0,0,.12);background-color:#f7f8fa;border-color:#e6e7eb}.next-switch-off[disabled]>.next-switch-children{color:#c4c6cf}.next-switch-off.next-switch-small>.next-switch-children{right:5px}
|
||||
|
||||
/*!
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
|
File diff suppressed because one or more lines are too long
@ -105,12 +105,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
|
@ -46,4 +46,17 @@ public abstract class AbstractMemberLookup implements MemberLookup {
|
||||
public void destroy() throws NacosException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws NacosException {
|
||||
if (start.compareAndSet(false, true)) {
|
||||
doStart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* subclass can override this method if need.
|
||||
* @throws NacosException NacosException
|
||||
*/
|
||||
protected abstract void doStart() throws NacosException;
|
||||
}
|
||||
|
@ -67,12 +67,10 @@ public class AddressServerMemberLookup extends AbstractMemberLookup {
|
||||
private volatile boolean shutdown = false;
|
||||
|
||||
@Override
|
||||
public void start() throws NacosException {
|
||||
if (start.compareAndSet(false, true)) {
|
||||
this.maxFailCount = Integer.parseInt(EnvUtil.getProperty("maxHealthCheckFailCount", "12"));
|
||||
initAddressSys();
|
||||
run();
|
||||
}
|
||||
public void doStart() throws NacosException {
|
||||
this.maxFailCount = Integer.parseInt(EnvUtil.getProperty("maxHealthCheckFailCount", "12"));
|
||||
initAddressSys();
|
||||
run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,17 +51,15 @@ public class FileConfigMemberLookup extends AbstractMemberLookup {
|
||||
};
|
||||
|
||||
@Override
|
||||
public void start() throws NacosException {
|
||||
if (start.compareAndSet(false, true)) {
|
||||
readClusterConfFromDisk();
|
||||
|
||||
// Use the inotify mechanism to monitor file changes and automatically
|
||||
// trigger the reading of cluster.conf
|
||||
try {
|
||||
WatchFileCenter.registerWatcher(EnvUtil.getConfPath(), watcher);
|
||||
} catch (Throwable e) {
|
||||
Loggers.CLUSTER.error("An exception occurred in the launch file monitor : {}", e.getMessage());
|
||||
}
|
||||
public void doStart() throws NacosException {
|
||||
readClusterConfFromDisk();
|
||||
|
||||
// Use the inotify mechanism to monitor file changes and automatically
|
||||
// trigger the reading of cluster.conf
|
||||
try {
|
||||
WatchFileCenter.registerWatcher(EnvUtil.getConfPath(), watcher);
|
||||
} catch (Throwable e) {
|
||||
Loggers.CLUSTER.error("An exception occurred in the launch file monitor : {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,9 @@ import java.util.Collections;
|
||||
public class StandaloneMemberLookup extends AbstractMemberLookup {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (start.compareAndSet(false, true)) {
|
||||
String url = InetUtils.getSelfIP() + ":" + EnvUtil.getPort();
|
||||
afterLookup(MemberUtil.readServerConf(Collections.singletonList(url)));
|
||||
}
|
||||
public void doStart() {
|
||||
String url = InetUtils.getSelfIP() + ":" + EnvUtil.getPort();
|
||||
afterLookup(MemberUtil.readServerConf(Collections.singletonList(url)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -36,6 +36,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.alibaba.nacos.common.constant.HttpHeaderConsts.ACCEPT_ENCODING;
|
||||
import static com.alibaba.nacos.common.http.param.MediaType.APPLICATION_JSON;
|
||||
|
||||
/**
|
||||
* web utils.
|
||||
*
|
||||
@ -43,6 +46,14 @@ import java.util.function.Function;
|
||||
*/
|
||||
public class WebUtils {
|
||||
|
||||
private static final String ENCODING_KEY = "encoding";
|
||||
|
||||
private static final String COMMA = ",";
|
||||
|
||||
private static final String SEMI = ";";
|
||||
|
||||
private static final String TMP_SUFFIX = ".tmp";
|
||||
|
||||
/**
|
||||
* get target value from parameterMap, if not found will throw {@link IllegalArgumentException}.
|
||||
*
|
||||
@ -55,7 +66,7 @@ public class WebUtils {
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
throw new IllegalArgumentException("Param '" + key + "' is required.");
|
||||
}
|
||||
String encoding = req.getParameter("encoding");
|
||||
String encoding = req.getParameter(ENCODING_KEY);
|
||||
return resolveValue(value, encoding);
|
||||
}
|
||||
|
||||
@ -75,7 +86,7 @@ public class WebUtils {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
String encoding = req.getParameter("encoding");
|
||||
String encoding = req.getParameter(ENCODING_KEY);
|
||||
return resolveValue(value, encoding);
|
||||
}
|
||||
|
||||
@ -131,9 +142,9 @@ public class WebUtils {
|
||||
* @return accept encode
|
||||
*/
|
||||
public static String getAcceptEncoding(HttpServletRequest req) {
|
||||
String encode = StringUtils.defaultIfEmpty(req.getHeader("Accept-Charset"), StandardCharsets.UTF_8.name());
|
||||
encode = encode.contains(",") ? encode.substring(0, encode.indexOf(",")) : encode;
|
||||
return encode.contains(";") ? encode.substring(0, encode.indexOf(";")) : encode;
|
||||
String encode = StringUtils.defaultIfEmpty(req.getHeader(ACCEPT_ENCODING), StandardCharsets.UTF_8.name());
|
||||
encode = encode.contains(COMMA) ? encode.substring(0, encode.indexOf(COMMA)) : encode;
|
||||
return encode.contains(SEMI) ? encode.substring(0, encode.indexOf(SEMI)) : encode;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,7 +173,7 @@ public class WebUtils {
|
||||
*/
|
||||
public static void response(HttpServletResponse response, String body, int code) throws IOException {
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.setContentType(APPLICATION_JSON);
|
||||
response.getWriter().write(body);
|
||||
response.setStatus(code);
|
||||
}
|
||||
@ -183,7 +194,7 @@ public class WebUtils {
|
||||
}
|
||||
File tmpFile = null;
|
||||
try {
|
||||
tmpFile = DiskUtils.createTmpFile(multipartFile.getName(), ".tmp");
|
||||
tmpFile = DiskUtils.createTmpFile(multipartFile.getName(), TMP_SUFFIX);
|
||||
multipartFile.transferTo(tmpFile);
|
||||
consumer.accept(tmpFile);
|
||||
} catch (Throwable ex) {
|
||||
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.cluster.lookup;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
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.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AddressServerMemberLookupTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
private NacosRestTemplate restTemplate;
|
||||
|
||||
@Mock
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
@Mock
|
||||
private HttpRestResult<String> result;
|
||||
|
||||
private AddressServerMemberLookup addressServerMemberLookup;
|
||||
|
||||
private String addressUrl;
|
||||
|
||||
private String envIdUrl;
|
||||
|
||||
private String addressServerUrl;
|
||||
|
||||
private String addressPort;
|
||||
|
||||
private String domainName;
|
||||
|
||||
@Mock
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
EnvUtil.setEnvironment(environment);
|
||||
when(environment.getProperty("maxHealthCheckFailCount", "12")).thenReturn("12");
|
||||
when(environment.getProperty("nacos.core.address-server.retry", Integer.class, 5)).thenReturn(5);
|
||||
when(environment.getProperty("address.server.domain", "jmenv.tbsite.net")).thenReturn("jmenv.tbsite.net");
|
||||
when(environment.getProperty("address.server.port", "8080")).thenReturn("8080");
|
||||
when(environment.getProperty("address.server.domain", "jmenv.tbsite.net")).thenReturn("jmenv.tbsite.net");
|
||||
when(environment.getProperty(eq("address.server.url"), any(String.class))).thenReturn("/nacos/serverlist");
|
||||
initAddressSys();
|
||||
when(restTemplate.<String>get(eq(addressServerUrl), any(Header.EMPTY.getClass()), any(Query.EMPTY.getClass()), any(Type.class)))
|
||||
.thenReturn(result);
|
||||
addressServerMemberLookup = new AddressServerMemberLookup();
|
||||
ReflectionTestUtils.setField(addressServerMemberLookup, "restTemplate", restTemplate);
|
||||
|
||||
when(result.ok()).thenReturn(true);
|
||||
when(result.getData()).thenReturn("1.1.1.1:8848");
|
||||
addressServerMemberLookup.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws NacosException {
|
||||
addressServerMemberLookup.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemberChange() throws Exception {
|
||||
addressServerMemberLookup.injectMemberManager(memberManager);
|
||||
verify(restTemplate).get(eq(addressServerUrl), any(Header.EMPTY.getClass()), any(Query.EMPTY.getClass()), any(Type.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfo() {
|
||||
Map<String, Object> infos = addressServerMemberLookup.info();
|
||||
assertEquals(4, infos.size());
|
||||
assertTrue(infos.containsKey("addressServerHealth"));
|
||||
assertTrue(infos.containsKey("addressServerUrl"));
|
||||
assertTrue(infos.containsKey("envIdUrl"));
|
||||
assertTrue(infos.containsKey("addressServerFailCount"));
|
||||
assertEquals(addressServerUrl, infos.get("addressServerUrl"));
|
||||
assertEquals(envIdUrl, infos.get("envIdUrl"));
|
||||
}
|
||||
|
||||
private void initAddressSys() {
|
||||
String envDomainName = System.getenv("address_server_domain");
|
||||
if (StringUtils.isBlank(envDomainName)) {
|
||||
domainName = EnvUtil.getProperty("address.server.domain", "jmenv.tbsite.net");
|
||||
} else {
|
||||
domainName = envDomainName;
|
||||
}
|
||||
String envAddressPort = System.getenv("address_server_port");
|
||||
if (StringUtils.isBlank(envAddressPort)) {
|
||||
addressPort = EnvUtil.getProperty("address.server.port", "8080");
|
||||
} else {
|
||||
addressPort = envAddressPort;
|
||||
}
|
||||
String envAddressUrl = System.getenv("address_server_url");
|
||||
if (StringUtils.isBlank(envAddressUrl)) {
|
||||
addressUrl = EnvUtil.getProperty("address.server.url", EnvUtil.getContextPath() + "/" + "serverlist");
|
||||
} else {
|
||||
addressUrl = envAddressUrl;
|
||||
}
|
||||
addressServerUrl = "http://" + domainName + ":" + addressPort + addressUrl;
|
||||
envIdUrl = "http://" + domainName + ":" + addressPort + "/env";
|
||||
|
||||
Loggers.CORE.info("ServerListService address-server port:" + addressPort);
|
||||
Loggers.CORE.info("ADDRESS_SERVER_URL:" + addressServerUrl);
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.cluster.lookup;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.cluster.MemberLookup;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LookupFactoryTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
private ServletContext servletContext;
|
||||
|
||||
private static final String LOOKUP_MODE_TYPE = "nacos.core.member.lookup.type";
|
||||
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
private MemberLookup memberLookup;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
when(servletContext.getContextPath()).thenReturn("");
|
||||
EnvUtil.setEnvironment(new StandardEnvironment());
|
||||
memberManager = new ServerMemberManager(servletContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLookUp() throws NacosException {
|
||||
memberLookup = LookupFactory.createLookUp(memberManager);
|
||||
if (EnvUtil.getStandaloneMode()) {
|
||||
assertEquals(memberLookup.getClass(), StandaloneMemberLookup.class);
|
||||
} else {
|
||||
String lookupType = EnvUtil.getProperty(LOOKUP_MODE_TYPE);
|
||||
if (StringUtils.isNotBlank(lookupType)) {
|
||||
LookupFactory.LookupType type = LookupFactory.LookupType.sourceOf(lookupType);
|
||||
if (Objects.nonNull(type)) {
|
||||
if (LookupFactory.LookupType.FILE_CONFIG.equals(type)) {
|
||||
assertEquals(memberLookup.getClass(), FileConfigMemberLookup.class);
|
||||
}
|
||||
if (LookupFactory.LookupType.ADDRESS_SERVER.equals(type)) {
|
||||
assertEquals(memberLookup.getClass(), AddressServerMemberLookup.class);
|
||||
}
|
||||
} else {
|
||||
File file = new File(EnvUtil.getClusterConfFilePath());
|
||||
if (file.exists() || StringUtils.isNotBlank(EnvUtil.getMemberList())) {
|
||||
assertEquals(memberLookup.getClass(), FileConfigMemberLookup.class);
|
||||
} else {
|
||||
assertEquals(memberLookup.getClass(), AddressServerMemberLookup.class);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
File file = new File(EnvUtil.getClusterConfFilePath());
|
||||
if (file.exists() || StringUtils.isNotBlank(EnvUtil.getMemberList())) {
|
||||
assertEquals(memberLookup.getClass(), FileConfigMemberLookup.class);
|
||||
} else {
|
||||
assertEquals(memberLookup.getClass(), AddressServerMemberLookup.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchLookup() throws NacosException {
|
||||
String name1 = "file";
|
||||
MemberLookup memberLookup = LookupFactory.switchLookup(name1, memberManager);
|
||||
assertEquals(memberLookup.getClass(), FileConfigMemberLookup.class);
|
||||
String name2 = "address-server";
|
||||
memberLookup = LookupFactory.switchLookup(name2, memberManager);
|
||||
assertEquals(memberLookup.getClass(), AddressServerMemberLookup.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.distributed.distro;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DistroConfigTest extends TestCase {
|
||||
|
||||
private DistroConfig distroConfig;
|
||||
|
||||
private long syncDelayMillis = 2000;
|
||||
|
||||
private long syncRetryDelayMillis = 4000;
|
||||
|
||||
private long verifyIntervalMillis = 6000;
|
||||
|
||||
private long loadDataRetryDelayMillis = 80000;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
distroConfig = DistroConfig.getInstance();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSyncDelayMillis() {
|
||||
distroConfig.setSyncDelayMillis(syncDelayMillis);
|
||||
assertEquals(syncDelayMillis, distroConfig.getSyncDelayMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSyncRetryDelayMillis() {
|
||||
distroConfig.setSyncRetryDelayMillis(syncRetryDelayMillis);
|
||||
assertEquals(syncRetryDelayMillis, distroConfig.getSyncRetryDelayMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetVerifyIntervalMillis() {
|
||||
distroConfig.setVerifyIntervalMillis(verifyIntervalMillis);
|
||||
assertEquals(verifyIntervalMillis, distroConfig.getVerifyIntervalMillis());
|
||||
}
|
||||
|
||||
public void testSetLoadDataRetryDelayMillis() {
|
||||
distroConfig.setLoadDataRetryDelayMillis(loadDataRetryDelayMillis);
|
||||
assertEquals(loadDataRetryDelayMillis, distroConfig.getLoadDataRetryDelayMillis());
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.distributed.distro.component;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DistroComponentHolderTest extends TestCase {
|
||||
|
||||
private final String type = "com.alibaba.nacos.naming.iplist.";
|
||||
|
||||
private DistroComponentHolder componentHolder;
|
||||
|
||||
@Mock
|
||||
private DistroDataStorage distroDataStorage;
|
||||
|
||||
@Mock
|
||||
private DistroTransportAgent distroTransportAgent;
|
||||
|
||||
@Mock
|
||||
private DistroFailedTaskHandler distroFailedTaskHandler;
|
||||
|
||||
@Mock
|
||||
private DistroDataProcessor distroDataProcessor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
componentHolder = new DistroComponentHolder();
|
||||
componentHolder.registerDataStorage(type, distroDataStorage);
|
||||
componentHolder.registerTransportAgent(type, distroTransportAgent);
|
||||
componentHolder.registerFailedTaskHandler(type, distroFailedTaskHandler);
|
||||
when(distroDataProcessor.processType()).thenReturn(type);
|
||||
componentHolder.registerDataProcessor(distroDataProcessor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindTransportAgent() {
|
||||
DistroTransportAgent distroTransportAgent = componentHolder.findTransportAgent(type);
|
||||
assertEquals(this.distroTransportAgent, distroTransportAgent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDataStorage() {
|
||||
DistroDataStorage distroDataStorage = componentHolder.findDataStorage(type);
|
||||
assertEquals(this.distroDataStorage, distroDataStorage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataStorageTypes() {
|
||||
componentHolder.getDataStorageTypes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindFailedTaskHandler() {
|
||||
DistroFailedTaskHandler distroFailedTaskHandler = componentHolder.findFailedTaskHandler(type);
|
||||
assertEquals(this.distroFailedTaskHandler, distroFailedTaskHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDataProcessor() {
|
||||
DistroDataProcessor distroDataProcessor = componentHolder.findDataProcessor(type);
|
||||
assertEquals(this.distroDataProcessor, distroDataProcessor);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.distributed.distro.entity;
|
||||
|
||||
import com.alibaba.nacos.consistency.DataOperation;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DistroDataTest extends TestCase {
|
||||
|
||||
private DistroData distroData;
|
||||
|
||||
private DistroKey distroKey;
|
||||
|
||||
private final String type = "com.alibaba.nacos.naming.iplist.";
|
||||
|
||||
private int contentSize = 10;
|
||||
|
||||
private final byte[] content = new byte[contentSize];
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
distroKey = new DistroKey("checksum", type);
|
||||
distroData = new DistroData(distroKey, content);
|
||||
distroData.setType(DataOperation.VERIFY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetters() {
|
||||
assertEquals(distroKey, distroData.getDistroKey());
|
||||
assertEquals(content, distroData.getContent());
|
||||
assertEquals(DataOperation.VERIFY, distroData.getType());
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.distributed.distro.entity;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DistroKeyTest {
|
||||
|
||||
private final String type = "com.alibaba.nacos.naming.iplist.";
|
||||
|
||||
private final String resourceKey = "checksum";
|
||||
|
||||
private final String targetServer = "1.1.1.1";
|
||||
|
||||
private DistroKey distroKey1;
|
||||
|
||||
private DistroKey distroKey2;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
distroKey1 = new DistroKey(resourceKey, type, targetServer);
|
||||
distroKey2 = new DistroKey();
|
||||
distroKey2.setResourceKey(resourceKey);
|
||||
distroKey2.setResourceType(type);
|
||||
distroKey2.setTargetServer(targetServer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetters() {
|
||||
Assert.assertEquals(distroKey2.getResourceKey(), resourceKey);
|
||||
Assert.assertEquals(distroKey2.getResourceType(), type);
|
||||
Assert.assertEquals(distroKey2.getTargetServer(), targetServer);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
Assert.assertEquals(distroKey1, distroKey2);
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.distributed.distro.task.load;
|
||||
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.distributed.distro.DistroConfig;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroCallback;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroComponentHolder;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroDataProcessor;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroDataStorage;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroFailedTaskHandler;
|
||||
import com.alibaba.nacos.core.distributed.distro.component.DistroTransportAgent;
|
||||
import com.alibaba.nacos.core.distributed.distro.entity.DistroData;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DistroLoadDataTaskTest extends TestCase {
|
||||
|
||||
private final String type = "com.alibaba.nacos.naming.iplist.";
|
||||
|
||||
private DistroComponentHolder componentHolder;
|
||||
|
||||
@Mock
|
||||
private DistroDataStorage distroDataStorage;
|
||||
|
||||
@Mock
|
||||
private DistroTransportAgent distroTransportAgent;
|
||||
|
||||
@Mock
|
||||
private DistroFailedTaskHandler distroFailedTaskHandler;
|
||||
|
||||
@Mock
|
||||
private DistroDataProcessor distroDataProcessor;
|
||||
|
||||
@Mock
|
||||
private DistroData distroData;
|
||||
|
||||
private DistroLoadDataTask distroLoadDataTask;
|
||||
|
||||
@Mock
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
@Mock
|
||||
private DistroConfig distroConfig;
|
||||
|
||||
@Mock
|
||||
private DistroCallback loadCallback;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
EnvUtil.setEnvironment(new StandardEnvironment());
|
||||
memberManager = new ServerMemberManager(new MockServletContext());
|
||||
Member member1 = Member.builder().ip("2.2.2.2").port(8848).build();
|
||||
Member member2 = Member.builder().ip("1.1.1.1").port(8848).build();
|
||||
memberManager.update(member1);
|
||||
memberManager.update(member2);
|
||||
componentHolder = new DistroComponentHolder();
|
||||
componentHolder.registerDataStorage(type, distroDataStorage);
|
||||
componentHolder.registerTransportAgent(type, distroTransportAgent);
|
||||
componentHolder.registerFailedTaskHandler(type, distroFailedTaskHandler);
|
||||
when(distroDataProcessor.processType()).thenReturn(type);
|
||||
componentHolder.registerDataProcessor(distroDataProcessor);
|
||||
when(distroTransportAgent.getDatumSnapshot(any(String.class))).thenReturn(distroData);
|
||||
when(distroDataProcessor.processSnapshot(distroData)).thenReturn(true);
|
||||
distroLoadDataTask = new DistroLoadDataTask(memberManager, componentHolder, distroConfig, loadCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRun() {
|
||||
distroLoadDataTask.run();
|
||||
Map<String, Boolean> loadCompletedMap = (Map<String, Boolean>) ReflectionTestUtils.getField(distroLoadDataTask, "loadCompletedMap");
|
||||
assertNotNull(loadCompletedMap);
|
||||
assertTrue(loadCompletedMap.containsKey(type));
|
||||
verify(distroTransportAgent).getDatumSnapshot(any(String.class));
|
||||
}
|
||||
}
|
@ -38,11 +38,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-common</artifactId>
|
||||
|
@ -30,11 +30,6 @@
|
||||
<url>http://nacos.io</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-api</artifactId>
|
||||
|
@ -40,11 +40,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-core</artifactId>
|
||||
|
@ -82,15 +82,13 @@ public class ClientBeatProcessor implements BeatProcessor {
|
||||
Loggers.EVT_LOG.debug("[CLIENT-BEAT] refresh beat: {}", rsInfo.toString());
|
||||
}
|
||||
instance.setLastBeat(System.currentTimeMillis());
|
||||
if (!instance.isMarked()) {
|
||||
if (!instance.isHealthy()) {
|
||||
instance.setHealthy(true);
|
||||
Loggers.EVT_LOG
|
||||
.info("service: {} {POS} {IP-ENABLED} valid: {}:{}@{}, region: {}, msg: client beat ok",
|
||||
cluster.getService().getName(), ip, port, cluster.getName(),
|
||||
UtilsAndCommons.LOCALHOST_SITE);
|
||||
getPushService().serviceChanged(service);
|
||||
}
|
||||
if (!instance.isMarked() && !instance.isHealthy()) {
|
||||
instance.setHealthy(true);
|
||||
Loggers.EVT_LOG
|
||||
.info("service: {} {POS} {IP-ENABLED} valid: {}:{}@{}, region: {}, msg: client beat ok",
|
||||
cluster.getService().getName(), ip, port, cluster.getName(),
|
||||
UtilsAndCommons.LOCALHOST_SITE);
|
||||
getPushService().serviceChanged(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.consistency.ephemeral.distro;
|
||||
|
||||
import com.alibaba.nacos.naming.consistency.Datum;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DataStoreTest extends TestCase {
|
||||
|
||||
private DataStore dataStore;
|
||||
|
||||
private String key;
|
||||
|
||||
@Mock
|
||||
private Datum datum;
|
||||
|
||||
@Mock
|
||||
private Map<String, Datum> dataMap;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
dataStore = new DataStore();
|
||||
key = "tmp_key";
|
||||
ReflectionTestUtils.setField(dataStore, "dataMap", dataMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPut() {
|
||||
dataStore.put(key, datum);
|
||||
verify(dataMap).put(key, datum);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
dataStore.remove(key);
|
||||
verify(dataMap).remove(key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeys() {
|
||||
dataStore.keys();
|
||||
verify(dataMap).keySet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() {
|
||||
dataStore.get(key);
|
||||
verify(dataMap).get(key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContains() {
|
||||
dataStore.contains(key);
|
||||
verify(dataMap).containsKey(key);
|
||||
}
|
||||
}
|
@ -29,15 +29,44 @@ import org.junit.Test;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ClusterVersionJudgementTest {
|
||||
|
||||
private ServerMemberManager manager;
|
||||
|
||||
private String[] ipList;
|
||||
|
||||
private final int ipCount = 3;
|
||||
|
||||
private final String ip1 = "1.1.1.1";
|
||||
|
||||
private final String ip2 = "2.2.2.2";
|
||||
|
||||
private final String ip3 = "3.3.3.3";
|
||||
|
||||
private final int defalutPort = 80;
|
||||
|
||||
private final String newVersion = "1.4.0";
|
||||
|
||||
private final String oldVersion = "1.3.0";
|
||||
|
||||
private List<Member> members;
|
||||
|
||||
private Map<String, Object> newVersionMeta;
|
||||
|
||||
private Map<String, Object> oldVersionMeta;
|
||||
|
||||
private ClusterVersionJudgement judgement;
|
||||
|
||||
public ClusterVersionJudgementTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
EnvUtil.setEnvironment(new MockEnvironment());
|
||||
@ -46,6 +75,19 @@ public class ClusterVersionJudgementTest {
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
manager = new ServerMemberManager(new MockServletContext());
|
||||
newVersionMeta = new HashMap<>(4);
|
||||
newVersionMeta.put(MemberMetaDataConstants.VERSION, newVersion);
|
||||
oldVersionMeta = new HashMap<>(4);
|
||||
oldVersionMeta.put(MemberMetaDataConstants.VERSION, oldVersion);
|
||||
ipList = new String[ipCount];
|
||||
ipList[0] = ip1;
|
||||
ipList[1] = ip2;
|
||||
ipList[2] = ip3;
|
||||
members = new LinkedList<>();
|
||||
members.add(Member.builder().ip(ipList[0]).port(defalutPort).state(NodeState.UP).build());
|
||||
members.add(Member.builder().ip(ipList[1]).port(defalutPort).state(NodeState.UP).build());
|
||||
members.add(Member.builder().ip(ipList[2]).port(defalutPort).state(NodeState.UP).build());
|
||||
manager.memberJoin(members);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -59,49 +101,49 @@ public class ClusterVersionJudgementTest {
|
||||
*/
|
||||
@Test
|
||||
public void testAllMemberIsNewVersion() {
|
||||
Map<String, String> metadataInfo = new HashMap<>(4);
|
||||
metadataInfo.put(MemberMetaDataConstants.VERSION, "1.4.0");
|
||||
Collection<Member> members = Arrays
|
||||
.asList(Member.builder().ip("1.1.1.1").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("2.2.2.2").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("3.3.3.3").port(80).state(NodeState.UP).extendInfo(metadataInfo).build());
|
||||
manager.memberJoin(members);
|
||||
ClusterVersionJudgement judgement = new ClusterVersionJudgement(manager);
|
||||
Collection<Member> allMembers = manager.allMembers();
|
||||
allMembers.forEach(member -> member.setExtendInfo(newVersionMeta));
|
||||
judgement = new ClusterVersionJudgement(manager);
|
||||
judgement.judge();
|
||||
Assert.assertTrue(judgement.allMemberIsNewVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartMemberIsNewVersion() {
|
||||
Map<String, String> metadataInfo = new HashMap<>(4);
|
||||
metadataInfo.put(MemberMetaDataConstants.VERSION, "1.4.0");
|
||||
Collection<Member> members = Arrays
|
||||
.asList(Member.builder().ip("1.1.1.1").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("2.2.2.2").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("3.3.3.3").port(80).state(NodeState.UP).build());
|
||||
manager.memberJoin(members);
|
||||
ClusterVersionJudgement judgement = new ClusterVersionJudgement(manager);
|
||||
Collection<Member> allMembers = manager.allMembers();
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
allMembers.forEach(member -> {
|
||||
if (count.get() == 0) {
|
||||
member.setExtendInfo(oldVersionMeta);
|
||||
} else {
|
||||
count.incrementAndGet();
|
||||
member.setExtendInfo(newVersionMeta);
|
||||
}
|
||||
});
|
||||
judgement = new ClusterVersionJudgement(manager);
|
||||
judgement.judge();
|
||||
Assert.assertFalse(judgement.allMemberIsNewVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartMemberUpdateToNewVersion() {
|
||||
Map<String, String> metadataInfo = new HashMap<>(4);
|
||||
metadataInfo.put(MemberMetaDataConstants.VERSION, "1.4.0");
|
||||
Collection<Member> members = Arrays
|
||||
.asList(Member.builder().ip("1.1.1.1").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("2.2.2.2").port(80).state(NodeState.UP).extendInfo(metadataInfo).build(),
|
||||
Member.builder().ip("3.3.3.3").port(80).state(NodeState.UP).build());
|
||||
manager.memberJoin(members);
|
||||
ClusterVersionJudgement judgement = new ClusterVersionJudgement(manager);
|
||||
// Firstly, make a cluster with a part of new version servers.
|
||||
Collection<Member> allMembers = manager.allMembers();
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
allMembers.forEach(member -> {
|
||||
if (count.get() == 0) {
|
||||
member.setExtendInfo(oldVersionMeta);
|
||||
} else {
|
||||
count.incrementAndGet();
|
||||
member.setExtendInfo(newVersionMeta);
|
||||
}
|
||||
});
|
||||
judgement = new ClusterVersionJudgement(manager);
|
||||
judgement.judge();
|
||||
Assert.assertFalse(judgement.allMemberIsNewVersion());
|
||||
|
||||
// update 3.3.3.3:80 version to 1.4.0
|
||||
manager.update(Member.builder().ip("3.3.3.3").port(80).state(NodeState.UP).extendInfo(metadataInfo).build());
|
||||
|
||||
judgement.registerObserver(Assert::assertTrue, 0);
|
||||
// Secondly, make all in the cluster to be new version servers.
|
||||
allMembers.forEach(member -> member.setExtendInfo(newVersionMeta));
|
||||
judgement = new ClusterVersionJudgement(manager);
|
||||
judgement.judge();
|
||||
Assert.assertTrue(judgement.allMemberIsNewVersion());
|
||||
}
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.consistency.persistent.impl;
|
||||
|
||||
import com.alibaba.nacos.core.exception.KvStorageException;
|
||||
import com.alibaba.nacos.core.storage.kv.FileKvStorage;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NamingKvStorageTest extends TestCase {
|
||||
|
||||
private NamingKvStorage namingKvStorage;
|
||||
|
||||
@Mock
|
||||
private FileKvStorage baseDirStorageMock;
|
||||
|
||||
private final byte[] key = "fileName_test".getBytes();
|
||||
|
||||
private final String str = "str_test";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
namingKvStorage = new NamingKvStorage("baseDir_test");
|
||||
|
||||
Field baseDirStorageField = NamingKvStorage.class.getDeclaredField("baseDirStorage");
|
||||
baseDirStorageField.setAccessible(true);
|
||||
baseDirStorageField.set(namingKvStorage, baseDirStorageMock);
|
||||
|
||||
when(baseDirStorageMock.get(key)).thenReturn(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() throws KvStorageException {
|
||||
namingKvStorage.get(key);
|
||||
verify(baseDirStorageMock).get(key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPut() throws KvStorageException {
|
||||
byte[] value = "value_test".getBytes();
|
||||
namingKvStorage.put(key, value);
|
||||
verify(baseDirStorageMock).put(key, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws KvStorageException {
|
||||
namingKvStorage.delete(key);
|
||||
verify(baseDirStorageMock).delete(key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoSnapshot() throws KvStorageException {
|
||||
namingKvStorage.doSnapshot(str);
|
||||
verify(baseDirStorageMock).doSnapshot(str);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSnapshotLoad() throws KvStorageException {
|
||||
namingKvStorage.snapshotLoad(str);
|
||||
verify(baseDirStorageMock).snapshotLoad(str);
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import com.alibaba.nacos.core.distributed.raft.RaftConfig;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
|
||||
import com.alibaba.nacos.core.storage.kv.KvStorage;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.utils.DiskUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -38,6 +37,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NamingSnapshotOperationTest {
|
||||
|
||||
@ -49,21 +51,23 @@ public class NamingSnapshotOperationTest {
|
||||
@Mock
|
||||
private KvStorage storage;
|
||||
|
||||
private final String tmpDir = Paths.get(EnvUtil.getNacosTmpDir(), "rocks_test").toString();
|
||||
|
||||
private final String snapshotDir = Paths.get(EnvUtil.getNacosTmpDir(), "rocks_snapshot_test").toString();
|
||||
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
private boolean isSnapshoted = false;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
DiskUtils.deleteQuietly(Paths.get(EnvUtil.getNacosTmpDir()));
|
||||
public void init() throws Exception {
|
||||
doAnswer(invocationOnMock -> {
|
||||
isSnapshoted = true;
|
||||
return null;
|
||||
}).when(storage).doSnapshot(any(String.class));
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
storage.shutdown();
|
||||
DiskUtils.deleteQuietly(Paths.get(EnvUtil.getNacosTmpDir()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -78,6 +82,7 @@ public class NamingSnapshotOperationTest {
|
||||
latch.countDown();
|
||||
});
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
Assert.assertTrue(isSnapshoted);
|
||||
Assert.assertTrue(result.get());
|
||||
|
||||
final Reader reader = new Reader(snapshotDir, writer.listFiles());
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.core;
|
||||
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DistroMapperTest {
|
||||
|
||||
private DistroMapper distroMapper;
|
||||
|
||||
@Mock
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
private SwitchDomain switchDomain;
|
||||
|
||||
private String serviceName = "com.taobao.service";
|
||||
|
||||
private String ip1 = "1.1.1.1";
|
||||
|
||||
private String ip2 = "2.2.2.2";
|
||||
|
||||
private String ip3 = "3.3.3.3";
|
||||
|
||||
private String ip4 = "4.4.4.4";
|
||||
|
||||
private int port = 8848;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ConcurrentSkipListMap<String, Member> serverList = new ConcurrentSkipListMap<>();
|
||||
EnvUtil.setEnvironment(new StandardEnvironment());
|
||||
serverList.put(ip1, Member.builder().ip(ip1).port(port).build());
|
||||
serverList.put(ip2, Member.builder().ip(ip2).port(port).build());
|
||||
serverList.put(ip3, Member.builder().ip(ip3).port(port).build());
|
||||
EnvUtil.setLocalAddress(ip4);
|
||||
serverList.put(EnvUtil.getLocalAddress(), Member.builder().ip(EnvUtil.getLocalAddress()).port(port).build());
|
||||
HashSet<Member> set = new HashSet<>(serverList.values());
|
||||
switchDomain = new SwitchDomain();
|
||||
distroMapper = new DistroMapper(memberManager, switchDomain);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponsible() {
|
||||
assertTrue(distroMapper.responsible(serviceName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapSrv() {
|
||||
String server = distroMapper.mapSrv(serviceName);
|
||||
assertEquals(server, ip4);
|
||||
}
|
||||
}
|
@ -58,12 +58,6 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
|
@ -29,13 +29,13 @@ import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.alibaba.nacos.sys.env.Constants.IP_ADDRESS;
|
||||
import static com.alibaba.nacos.sys.env.Constants.NACOS_SERVER_IP;
|
||||
@ -62,6 +62,9 @@ public class InetUtils {
|
||||
|
||||
private static final List<String> IGNORED_INTERFACES = new ArrayList<String>();
|
||||
|
||||
private static Pattern domainPattern = Pattern
|
||||
.compile("[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?");
|
||||
|
||||
static {
|
||||
NotifyCenter.registerToSharePublisher(IPChangeEvent.class);
|
||||
|
||||
@ -92,8 +95,7 @@ public class InetUtils {
|
||||
preferHostnameOverIP = Boolean.getBoolean(SYSTEM_PREFER_HOSTNAME_OVER_IP);
|
||||
|
||||
if (!preferHostnameOverIP) {
|
||||
preferHostnameOverIP = Boolean
|
||||
.parseBoolean(EnvUtil.getProperty(PREFER_HOSTNAME_OVER_IP));
|
||||
preferHostnameOverIP = Boolean.parseBoolean(EnvUtil.getProperty(PREFER_HOSTNAME_OVER_IP));
|
||||
}
|
||||
|
||||
if (preferHostnameOverIP) {
|
||||
@ -157,7 +159,7 @@ public class InetUtils {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!ignoreInterface(ifc.getDisplayName())) {
|
||||
for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements(); ) {
|
||||
InetAddress address = addrs.nextElement();
|
||||
@ -220,18 +222,16 @@ public class InetUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* juege str is right domain.
|
||||
* juege str is right domain.(Check only rule)
|
||||
*
|
||||
* @param str nacosIP
|
||||
* @return nacosIP is domain
|
||||
*/
|
||||
public static boolean isDomain(String str) {
|
||||
InetSocketAddress address = new InetSocketAddress(str, 0);
|
||||
boolean unResolved = address.isUnresolved();
|
||||
if (unResolved) {
|
||||
LOG.warn("the domain: '" + str + "' can not be resolved");
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return false;
|
||||
}
|
||||
return !unResolved;
|
||||
return domainPattern.matcher(str).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
|
12
test/pom.xml
12
test/pom.xml
@ -92,12 +92,6 @@
|
||||
<artifactId>nacos-address</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
@ -110,12 +104,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.keran213539</groupId>
|
||||
<artifactId>commonOkHttp</artifactId>
|
||||
|
Loading…
Reference in New Issue
Block a user