Merge pull request #11452 from alibaba/develop

Upgrade to 2.3.0
This commit is contained in:
杨翊 SionYang 2023-11-30 11:22:14 +08:00 committed by GitHub
commit 8ac6c84a58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
294 changed files with 9624 additions and 3768 deletions

View File

@ -46,4 +46,4 @@ jobs:
- name: "Codecov"
uses: codecov/codecov-action@v3.1.0
with:
files: ./address/target/site/jacoco/jacoco.xml,./api/target/site/jacoco/jacoco.xml,./auth/target/site/jacoco/jacoco.xml,./client/target/site/jacoco/jacoco.xml,./common/target/site/jacoco/jacoco.xml,./consistency/target/site/jacoco/jacoco.xml,./console/target/site/jacoco/jacoco.xml,./core/target/site/jacoco/jacoco.xml,./naming/target/site/jacoco/jacoco.xml,./plugin-default-impl/target/site/jacoco/jacoco.xml,./plugin/auth/target/site/jacoco/jacoco.xml,./plugin/encryption/target/site/jacoco/jacoco.xml,./sys/target/site/jacoco/jacoco.xml
files: ./address/target/site/jacoco/jacoco.xml,./api/target/site/jacoco/jacoco.xml,./auth/target/site/jacoco/jacoco.xml,./client/target/site/jacoco/jacoco.xml,./common/target/site/jacoco/jacoco.xml,./consistency/target/site/jacoco/jacoco.xml,./console/target/site/jacoco/jacoco.xml,./core/target/site/jacoco/jacoco.xml,./naming/target/site/jacoco/jacoco.xml,./persistence/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-auth-plugin/target/site/jacoco/jacoco.xml,./plugin/auth/target/site/jacoco/jacoco.xml,./plugin/config/target/site/jacoco/jacoco.xml,./plugin/control/target/site/jacoco/jacoco.xml,./plugin/datasource/target/site/jacoco/jacoco.xml,./plugin/encryption/target/site/jacoco/jacoco.xml,./plugin/environment/target/site/jacoco/jacoco.xml,./plugin/trace/target/site/jacoco/jacoco.xml,./prometheus/target/site/jacoco/jacoco.xml,./sys/target/site/jacoco/jacoco.xml

View File

@ -25,7 +25,7 @@ jobs:
name: Upload distribution tar
with:
name: nacos
path: distribution/target/nacos-server-*-SNAPSHOT.tar.gz
path: distribution/target/nacos-server-*.tar.gz
- name: Save PR number
run: |
mkdir -p ./pr

View File

@ -62,7 +62,7 @@ jobs:
- name: Build and save docker images
id: build-images
run: |
mv nacos-server-*-SNAPSHOT.tar.gz nacos-e2e/cicd/build
mv nacos-server-*.tar.gz nacos-e2e/cicd/build
cd nacos-e2e/cicd/build
version=${{ github.event.pull_request.number || github.ref_name }}-$(uuidgen)
mkdir versionlist

View File

@ -42,7 +42,7 @@ jobs:
name: Upload distribution tar
with:
name: nacos
path: distribution/target/nacos-server-*-SNAPSHOT.tar.gz
path: distribution/target/nacos-server-*.tar.gz
docker:
if: ${{ success() }}
@ -74,7 +74,7 @@ jobs:
- name: Build and save docker images
id: build-images
run: |
mv nacos-server-*-SNAPSHOT.tar.gz nacos-e2e/cicd/build/
mv nacos-server-*.tar.gz nacos-e2e/cicd/build/
cd nacos-e2e/cicd/build
version=${{ github.event.pull_request.number || github.ref_name }}-$(uuidgen)
mkdir versionlist

View File

@ -18,8 +18,8 @@ package com.alibaba.nacos.api.ability.constant;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -30,6 +30,12 @@ import java.util.stream.Collectors;
* @date 2022/8/31 12:27
**/
public enum AbilityKey {
/**
* Server support register or deregister persistent instance by grpc.
*/
SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC("supportPersistentInstanceByGrpc",
"support persistent instance by grpc", AbilityMode.SERVER),
/**
* For Test temporarily.

View File

@ -45,6 +45,7 @@ public class ServerAbilities extends AbstractAbilityRegistry {
*
*/
// put ability here, which you want current server supports
supportedAbilities.put(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC, true);
}
/**.

View File

@ -188,18 +188,14 @@ public class ServiceInfo {
return false;
}
List<Instance> validHosts = new ArrayList<>();
boolean existValidHosts = false;
for (Instance host : hosts) {
if (!host.isHealthy()) {
continue;
}
for (int i = 0; i < host.getWeight(); i++) {
validHosts.add(host);
if (host.isHealthy() && host.getWeight() > 0) {
existValidHosts = true;
break;
}
}
//No valid hosts, return false.
return !validHosts.isEmpty();
return existValidHosts;
}
@JsonIgnore

View File

@ -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.api.naming.remote.request;
import com.alibaba.nacos.api.naming.pojo.Instance;
/**
* Nacos persistent instances request.
*
* @author blake.qiu
*/
public class PersistentInstanceRequest extends AbstractNamingRequest {
private String type;
private Instance instance;
public PersistentInstanceRequest() {
}
public PersistentInstanceRequest(String namespace, String serviceName, String groupName, String type, Instance instance) {
super(namespace, serviceName, groupName);
this.type = type;
this.instance = instance;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public Instance getInstance() {
return instance;
}
public void setInstance(Instance instance) {
this.instance = instance;
}
}

View File

@ -138,6 +138,10 @@ public class NamingUtils {
* @throws NacosException if check failed, throw exception
*/
public static void checkInstanceIsLegal(Instance instance) throws NacosException {
if (null == instance) {
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,
"Instance can not be null.");
}
if (instance.getInstanceHeartBeatTimeOut() < instance.getInstanceHeartBeatInterval()
|| instance.getIpDeleteTimeout() < instance.getInstanceHeartBeatInterval()) {
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,

View File

@ -47,6 +47,7 @@ com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncReque
com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse
com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest
com.alibaba.nacos.api.naming.remote.request.InstanceRequest
com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest
com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest
com.alibaba.nacos.api.naming.remote.request.ServiceListRequest
com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest

View File

@ -16,15 +16,21 @@
package com.alibaba.nacos.api.ability.register.impl;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ServerAbilitiesTest {
@Test
public void testGetStaticAbilities() {
// TODO add the server abilities.
assertTrue(ServerAbilities.getStaticAbilities().isEmpty());
assertFalse(ServerAbilities.getStaticAbilities().isEmpty());
}
@Test
public void testSupportPersistentInstanceByGrpcAbilities() {
assertTrue(ServerAbilities.getStaticAbilities().get(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
}
}

View File

@ -21,6 +21,7 @@ import com.alibaba.nacos.api.remote.ability.ServerRemoteAbility;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.BeforeClass;
@ -41,6 +42,7 @@ public class ServerRemoteAbilityTest {
mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
}
@Before
@ -52,7 +54,8 @@ public class ServerRemoteAbilityTest {
public void testSerialize() throws JsonProcessingException {
serverAbilities = new ServerRemoteAbility();
String json = mapper.writeValueAsString(serverAbilities);
assertEquals("{\"supportRemoteConnection\":false,\"grpcReportEnabled\":true}", json);
assertTrue(json.contains("\"supportRemoteConnection\":false"));
assertTrue(json.contains("\"grpcReportEnabled\":true"));
}
@Test

View File

@ -20,6 +20,7 @@ import com.alibaba.nacos.api.remote.request.Request;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.BeforeClass;
@ -60,6 +61,7 @@ public abstract class BasedConfigRequestTest {
mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
}
public abstract void testSerialize() throws JsonProcessingException;

View File

@ -35,7 +35,7 @@ public class ConfigBatchListenRequestTest extends BasedConfigRequestTest {
String json = mapper.writeValueAsString(configBatchListenRequest);
assertTrue(json.contains("\"listen\":" + "true"));
assertTrue(json.contains(
"\"configListenContexts\":[{\"group\":\"group\",\"md5\":\"test_MD5\",\"dataId\":\"test_data\",\"tenant\":\"test_tenant\"}]"));
"\"configListenContexts\":[{\"dataId\":\"test_data\",\"group\":\"group\",\"md5\":\"test_MD5\",\"tenant\":\"test_tenant\"}]"));
assertTrue(json.contains("\"module\":\"" + Constants.Config.CONFIG_MODULE));
assertTrue(json.contains("\"requestId\":\"" + requestId));
}

View File

@ -44,7 +44,7 @@ public class ConfigChangeBatchListenResponseTest extends BasedConfigResponseTest
assertTrue(json.contains("\"resultCode\":" + ResponseCode.SUCCESS.getCode()));
assertTrue(json.contains("\"errorCode\":0"));
assertTrue(json.contains(
"\"changedConfigs\":[{\"group\":\"group\",\"dataId\":\"test_data\",\"tenant\":\"test_tenant\"}]"));
"\"changedConfigs\":[{\"dataId\":\"test_data\",\"group\":\"group\",\"tenant\":\"test_tenant\"}]"));
}
@Override

View File

@ -0,0 +1,51 @@
/*
* Copyright 1999-2021 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.api.naming.remote.request;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class PersistentInstanceRequestTest extends BasedNamingRequestTest {
@Test
public void testSerialize() throws JsonProcessingException {
PersistentInstanceRequest request = new PersistentInstanceRequest(NAMESPACE, SERVICE, GROUP,
NamingRemoteConstants.REGISTER_INSTANCE, new Instance());
String json = mapper.writeValueAsString(request);
checkSerializeBasedInfo(json);
assertTrue(json.contains("\"type\":\"" + NamingRemoteConstants.REGISTER_INSTANCE + "\""));
assertTrue(json.contains("\"instance\":{"));
}
@Test
public void testDeserialize() throws JsonProcessingException {
String json = "{\"headers\":{},\"namespace\":\"namespace\",\"serviceName\":\"service\",\"groupName\":\"group\","
+ "\"type\":\"deregisterInstance\",\"instance\":{\"port\":0,\"weight\":1.0,\"healthy\":true,"
+ "\"enabled\":true,\"ephemeral\":true,\"metadata\":{},\"instanceIdGenerator\":\"simple\","
+ "\"instanceHeartBeatInterval\":5000,\"instanceHeartBeatTimeOut\":15000,\"ipDeleteTimeout\":30000},"
+ "\"module\":\"naming\"}";
PersistentInstanceRequest actual = mapper.readValue(json, PersistentInstanceRequest.class);
checkNamingRequestBasedInfo(actual);
assertEquals(NamingRemoteConstants.DE_REGISTER_INSTANCE, actual.getType());
assertEquals(new Instance(), actual.getInstance());
}
}

View File

@ -231,6 +231,19 @@ public class NamingUtilsTest {
Assert.assertEquals(e.getErrCode(), NacosException.INVALID_PARAM);
}
}
@Test
public void testCheckInstanceIsNull() throws NacosException {
Instance instance = new Instance();
instance.setIp("127.0.0.1");
instance.setPort(9089);
NamingUtils.checkInstanceIsLegal(instance);
try {
NamingUtils.checkInstanceIsLegal(null);
} catch (NacosException e) {
Assert.assertEquals(e.getErrCode(), NacosException.INVALID_PARAM);
}
}
@Test
public void testIsNumber() {

View File

@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.MapperFeature;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -40,6 +41,7 @@ public class ServerRemoteAbilityTest {
mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
}
@Before
@ -51,7 +53,8 @@ public class ServerRemoteAbilityTest {
public void testSerialize() throws JsonProcessingException {
serverAbilities = new ServerRemoteAbility();
String json = mapper.writeValueAsString(serverAbilities);
assertEquals("{\"supportRemoteConnection\":false,\"grpcReportEnabled\":true}", json);
assertTrue(json.contains("\"supportRemoteConnection\":false"));
assertTrue(json.contains("\"grpcReportEnabled\":true"));
}
@Test

View File

@ -44,16 +44,20 @@ public class AbilityKeyTest {
enumMap.put(AbilityKey.SERVER_TEST_1, true);
enumMap.put(AbilityKey.SERVER_TEST_2, false);
enumMap.put(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC, false);
stringBooleanMap = AbilityKey.mapStr(enumMap);
assertEquals(2, stringBooleanMap.size());
assertEquals(3, stringBooleanMap.size());
Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_1.getName()));
Assert.assertFalse(stringBooleanMap.get(AbilityKey.SERVER_TEST_2.getName()));
Assert.assertFalse(stringBooleanMap.get(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC.getName()));
enumMap.put(AbilityKey.SERVER_TEST_2, true);
enumMap.put(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC, true);
stringBooleanMap = AbilityKey.mapStr(enumMap);
assertEquals(2, stringBooleanMap.size());
assertEquals(3, stringBooleanMap.size());
Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_1.getName()));
Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_TEST_2.getName()));
Assert.assertTrue(stringBooleanMap.get(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC.getName()));
}
@Test
@ -71,23 +75,27 @@ public class AbilityKeyTest {
mapStr.put(AbilityKey.SERVER_TEST_2.getName(), false);
mapStr.put(AbilityKey.SERVER_TEST_1.getName(), true);
mapStr.put(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC.getName(), true);
enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr);
Assert.assertFalse(enumMap.get(AbilityKey.SERVER_TEST_2));
Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_1));
Assert.assertTrue(enumMap.get(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
mapStr.clear();
mapStr.put(AbilityKey.SERVER_TEST_2.getName(), true);
mapStr.put(AbilityKey.SERVER_TEST_1.getName(), true);
mapStr.put(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC.getName(), true);
enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr);
Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_2));
Assert.assertTrue(enumMap.get(AbilityKey.SERVER_TEST_1));
Assert.assertTrue(enumMap.get(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
}
@Test
public void testGetAllValues() {
Collection<AbilityKey> actual = AbilityKey.getAllValues(AbilityMode.SERVER);
assertEquals(2, actual.size());
assertEquals(3, actual.size());
actual = AbilityKey.getAllValues(AbilityMode.SDK_CLIENT);
assertEquals(1, actual.size());
actual = AbilityKey.getAllValues(AbilityMode.CLUSTER_CLIENT);
@ -97,7 +105,7 @@ public class AbilityKeyTest {
@Test
public void testGetAllNames() {
Collection<String> actual = AbilityKey.getAllNames(AbilityMode.SERVER);
assertEquals(2, actual.size());
assertEquals(3, actual.size());
actual = AbilityKey.getAllNames(AbilityMode.SDK_CLIENT);
assertEquals(1, actual.size());
actual = AbilityKey.getAllNames(AbilityMode.CLUSTER_CLIENT);

View File

@ -111,10 +111,16 @@
<artifactId>httpasyncclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>

View File

@ -22,6 +22,7 @@ import com.alibaba.nacos.api.config.filter.IConfigRequest;
import com.alibaba.nacos.api.config.filter.IConfigResponse;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.Pair;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;
import java.util.Objects;
@ -54,9 +55,14 @@ public class ConfigEncryptionFilter extends AbstractConfigFilter {
Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);
String secretKey = pair.getFirst();
String encryptContent = pair.getSecond();
((ConfigRequest) request).setContent(encryptContent);
((ConfigRequest) request).setEncryptedDataKey(secretKey);
if (!StringUtils.isBlank(encryptContent) && !encryptContent.equals(content)) {
((ConfigRequest) request).setContent(encryptContent);
}
if (!StringUtils.isBlank(secretKey) && !secretKey.equals(((ConfigRequest) request).getEncryptedDataKey())) {
((ConfigRequest) request).setEncryptedDataKey(secretKey);
} else if (StringUtils.isBlank(((ConfigRequest) request).getEncryptedDataKey()) && StringUtils.isBlank(secretKey)) {
((ConfigRequest) request).setEncryptedDataKey("");
}
}
if (Objects.nonNull(response) && response instanceof ConfigResponse && Objects.isNull(request)) {
@ -68,8 +74,16 @@ public class ConfigEncryptionFilter extends AbstractConfigFilter {
String content = configResponse.getContent();
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, content);
String secretKey = pair.getFirst();
String decryptContent = pair.getSecond();
((ConfigResponse) response).setContent(decryptContent);
if (!StringUtils.isBlank(decryptContent) && !decryptContent.equals(content)) {
((ConfigResponse) response).setContent(decryptContent);
}
if (!StringUtils.isBlank(secretKey) && !secretKey.equals(((ConfigResponse) response).getEncryptedDataKey())) {
((ConfigResponse) response).setEncryptedDataKey(secretKey);
} else if (StringUtils.isBlank(((ConfigResponse) response).getEncryptedDataKey()) && StringUtils.isBlank(secretKey)) {
((ConfigResponse) response).setEncryptedDataKey("");
}
}
filterChain.doFilter(request, response);
}

View File

@ -80,7 +80,7 @@ public class ConfigFilterChainManager implements IConfigFilterChain {
public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException {
new VirtualFilterChain(this.filters).doFilter(request, response);
}
private static class VirtualFilterChain implements IConfigFilterChain {
private final List<? extends IConfigFilter> additionalFilters;
@ -100,5 +100,5 @@ public class ConfigFilterChainManager implements IConfigFilterChain {
}
}
}
}

View File

@ -93,7 +93,7 @@ public class CacheData {
LOGGER.info("nacos.cache.data.init.snapshot = {} ", initSnapshot);
}
private final String envName;
public final String envName;
private final ConfigFilterChainManager configFilterChainManager;
@ -124,13 +124,13 @@ public class CacheData {
/**
* local cache change timestamp.
*/
private volatile AtomicLong lastModifiedTs = new AtomicLong(0);
private final AtomicLong lastModifiedTs = new AtomicLong(0);
/**
* notify change flag,for notify&sync concurrent control. 1.reset to false if starting to sync with server. 2.update
* to true if receive config change notification.
*/
private volatile AtomicBoolean receiveNotifyChanged = new AtomicBoolean(false);
private final AtomicBoolean receiveNotifyChanged = new AtomicBoolean(false);
private int taskId;
@ -139,7 +139,7 @@ public class CacheData {
/**
* if is cache data md5 sync with the server.
*/
private volatile AtomicBoolean isConsistentWithServer = new AtomicBoolean();
private final AtomicBoolean isConsistentWithServer = new AtomicBoolean();
/**
* if is cache data is discard,need to remove.

View File

@ -36,8 +36,6 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.RemoteConstants;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.remote.client.Connection;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
@ -55,6 +53,7 @@ import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.remote.ConnectionType;
import com.alibaba.nacos.common.remote.client.Connection;
import com.alibaba.nacos.common.remote.client.ConnectionEventListener;
import com.alibaba.nacos.common.remote.client.RpcClient;
import com.alibaba.nacos.common.remote.client.RpcClientFactory;
@ -66,10 +65,12 @@ import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@ -122,26 +123,26 @@ public class ClientWorker implements Closeable {
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<>(new HashMap<>());
private final ConfigFilterChainManager configFilterChainManager;
private String uuid = UUID.randomUUID().toString();
private final String uuid = UUID.randomUUID().toString();
private long timeout;
private ConfigRpcTransportClient agent;
private final ConfigRpcTransportClient agent;
private int taskPenaltyTime;
private boolean enableRemoteSyncConfig = false;
private static final int MIN_THREAD_NUM = 2;
private static final int THREAD_MULTIPLE = 1;
/**
* index(taskId)-> total cache count for this taskId.
*/
private final List<AtomicInteger> taskIdCacheCountList = new ArrayList<>();
/**
* Add listeners for data.
*
@ -404,11 +405,11 @@ public class ClientWorker implements Closeable {
private void increaseTaskIdCount(int taskId) {
taskIdCacheCountList.get(taskId).incrementAndGet();
}
private void decreaseTaskIdCount(int taskId) {
taskIdCacheCountList.get(taskId).decrementAndGet();
}
private int calculateTaskId() {
int perTaskSize = (int) ParamUtil.getPerTaskConfigSize();
for (int index = 0; index < taskIdCacheCountList.size(); index++) {
@ -419,7 +420,7 @@ public class ClientWorker implements Closeable {
taskIdCacheCountList.add(new AtomicInteger(0));
return taskIdCacheCountList.size() - 1;
}
public CacheData getCache(String dataId, String group) {
return getCache(dataId, group, TenantUtil.getUserTenantForAcm());
}
@ -567,15 +568,15 @@ public class ClientWorker implements Closeable {
public class ConfigRpcTransportClient extends ConfigTransportClient {
Map<String, ExecutorService> multiTaskExecutor = new HashMap<>();
private final BlockingQueue<Object> listenExecutebell = new ArrayBlockingQueue<>(1);
private Object bellItem = new Object();
private final Object bellItem = new Object();
private long lastAllSyncTime = System.currentTimeMillis();
Subscriber subscriber = null;
/**
* 3 minutes to check all listen cache keys.
*/
@ -779,37 +780,30 @@ public class ClientWorker implements Closeable {
for (CacheData cache : cacheMap.get().values()) {
synchronized (cache) {
//check local listeners consistent.
checkLocalConfig(cache);
// check local listeners consistent.
if (cache.isConsistentWithServer()) {
cache.checkListenerMd5();
if (!needAllSync) {
continue;
}
}
// If local configuration information is used, then skip the processing directly.
if (cache.isUseLocalConfigInfo()) {
continue;
}
if (!cache.isDiscard()) {
//get listen config
if (!cache.isUseLocalConfigInfo()) {
List<CacheData> cacheDatas = listenCachesMap.get(String.valueOf(cache.getTaskId()));
if (cacheDatas == null) {
cacheDatas = new LinkedList<>();
listenCachesMap.put(String.valueOf(cache.getTaskId()), cacheDatas);
}
cacheDatas.add(cache);
}
} else if (cache.isDiscard() && CollectionUtils.isEmpty(cache.getListeners())) {
if (!cache.isUseLocalConfigInfo()) {
List<CacheData> cacheDatas = removeListenCachesMap.get(String.valueOf(cache.getTaskId()));
if (cacheDatas == null) {
cacheDatas = new LinkedList<>();
removeListenCachesMap.put(String.valueOf(cache.getTaskId()), cacheDatas);
}
cacheDatas.add(cache);
}
List<CacheData> cacheDatas = listenCachesMap.computeIfAbsent(String.valueOf(cache.getTaskId()),
k -> new LinkedList<>());
cacheDatas.add(cache);
} else {
List<CacheData> cacheDatas = removeListenCachesMap.computeIfAbsent(
String.valueOf(cache.getTaskId()), k -> new LinkedList<>());
cacheDatas.add(cache);
}
}
@ -820,7 +814,7 @@ public class ClientWorker implements Closeable {
//execute check remove listen.
checkRemoveListenCache(removeListenCachesMap);
if (needAllSync) {
lastAllSyncTime = now;
}
@ -828,9 +822,59 @@ public class ClientWorker implements Closeable {
if (hasChangedKeys) {
notifyListenConfig();
}
}
/**
* Checks and handles local configuration for a given CacheData object. This method evaluates the use of
* failover files for local configuration storage and updates the CacheData accordingly.
*
* @param cacheData The CacheData object to be processed.
*/
public void checkLocalConfig(CacheData cacheData) {
final String dataId = cacheData.dataId;
final String group = cacheData.group;
final String tenant = cacheData.tenant;
final String envName = cacheData.envName;
// Check if a failover file exists for the specified dataId, group, and tenant.
File file = LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant);
// If not using local config info and a failover file exists, load and use it.
if (!cacheData.isUseLocalConfigInfo() && file.exists()) {
String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
cacheData.setUseLocalConfigInfo(true);
cacheData.setLocalConfigInfoVersion(file.lastModified());
cacheData.setContent(content);
LOGGER.warn(
"[{}] [failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}, content={}",
envName, dataId, group, tenant, md5, ContentUtils.truncateContent(content));
return;
}
// If use local config info, but the failover file is deleted, switch back to server config.
if (cacheData.isUseLocalConfigInfo() && !file.exists()) {
cacheData.setUseLocalConfigInfo(false);
LOGGER.warn("[{}] [failover-change] failover file deleted. dataId={}, group={}, tenant={}", envName,
dataId, group, tenant);
return;
}
// When the failover file content changes, indicating a change in local configuration.
if (cacheData.isUseLocalConfigInfo() && file.exists()
&& cacheData.getLocalConfigInfoVersion() != file.lastModified()) {
String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
cacheData.setUseLocalConfigInfo(true);
cacheData.setLocalConfigInfoVersion(file.lastModified());
cacheData.setContent(content);
LOGGER.warn(
"[{}] [failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}, content={}",
envName, dataId, group, tenant, md5, ContentUtils.truncateContent(content));
}
}
private ExecutorService ensureSyncExecutor(String taskId) {
if (!multiTaskExecutor.containsKey(taskId)) {
multiTaskExecutor.put(taskId,
@ -842,14 +886,14 @@ public class ClientWorker implements Closeable {
}
return multiTaskExecutor.get(taskId);
}
private void checkRemoveListenCache(Map<String, List<CacheData>> removeListenCachesMap) {
if (!removeListenCachesMap.isEmpty()) {
List<Future> listenFutures = new ArrayList<>();
for (Map.Entry<String, List<CacheData>> entry : removeListenCachesMap.entrySet()) {
String taskId = entry.getKey();
ExecutorService executorService = ensureSyncExecutor(taskId);
Future future = executorService.submit(() -> {
List<CacheData> removeListenCaches = entry.getValue();
@ -868,7 +912,7 @@ public class ClientWorker implements Closeable {
}
}
}
} catch (Throwable e) {
LOGGER.error("Async remove listen config change error ", e);
try {
@ -880,7 +924,7 @@ public class ClientWorker implements Closeable {
}
});
listenFutures.add(future);
}
for (Future future : listenFutures) {
try {
@ -891,9 +935,9 @@ public class ClientWorker implements Closeable {
}
}
}
private boolean checkListenCache(Map<String, List<CacheData>> listenCachesMap) {
final AtomicBoolean hasChangedKeys = new AtomicBoolean(false);
if (!listenCachesMap.isEmpty()) {
List<Future> listenFutures = new ArrayList<>();
@ -913,9 +957,9 @@ public class ClientWorker implements Closeable {
ConfigChangeBatchListenResponse listenResponse = (ConfigChangeBatchListenResponse) requestProxy(
rpcClient, configChangeListenRequest);
if (listenResponse != null && listenResponse.isSuccess()) {
Set<String> changeKeys = new HashSet<String>();
List<ConfigChangeBatchListenResponse.ConfigContext> changedConfigs = listenResponse.getChangedConfigs();
//handle changed keys,notify listener
if (!CollectionUtils.isEmpty(changedConfigs)) {
@ -927,9 +971,9 @@ public class ClientWorker implements Closeable {
boolean isInitializing = cacheMap.get().get(changeKey).isInitializing();
refreshContentAndCheck(changeKey, !isInitializing);
}
}
for (CacheData cacheData : listenCaches) {
if (cacheData.getReceiveNotifyChanged().get()) {
String changeKey = GroupKey.getKeyTenant(cacheData.dataId, cacheData.group,
@ -940,7 +984,7 @@ public class ClientWorker implements Closeable {
}
}
}
//handler content configs
for (CacheData cacheData : listenCaches) {
cacheData.setInitializing(false);
@ -954,7 +998,7 @@ public class ClientWorker implements Closeable {
}
}
}
}
} catch (Throwable e) {
LOGGER.error("Execute listen config change error ", e);
@ -967,7 +1011,7 @@ public class ClientWorker implements Closeable {
}
});
listenFutures.add(future);
}
for (Future future : listenFutures) {
try {
@ -976,7 +1020,7 @@ public class ClientWorker implements Closeable {
LOGGER.error("Async listen config change error ", throwable);
}
}
}
return hasChangedKeys.get();
}
@ -999,7 +1043,7 @@ public class ClientWorker implements Closeable {
}
}
/**
* build config string.
*
@ -1170,7 +1214,7 @@ public class ClientWorker implements Closeable {
ConfigRemoveResponse response = (ConfigRemoveResponse) requestProxy(getOneRunningClient(), request);
return response.isSuccess();
}
/**
* check server is health.
*
@ -1180,7 +1224,7 @@ public class ClientWorker implements Closeable {
try {
return getOneRunningClient().isRunning();
} catch (NacosException e) {
LOGGER.warn("check server status failed. error={}", e);
LOGGER.warn("check server status failed.", e);
return false;
}
}

View File

@ -77,7 +77,7 @@ public class ConfigHttpClientManager implements Closeable {
public void shutdown() throws NacosException {
NAMING_LOGGER.warn("[ConfigHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[ConfigHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));

View File

@ -25,16 +25,16 @@ import com.alibaba.nacos.client.logging.AbstractNacosLogging;
import com.alibaba.nacos.common.log.NacosLogbackConfigurator;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.common.utils.ResourceUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* Support for Logback version 1.0.8 or higher
*
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
* @author <a href="mailto:hujun3@xiaomi.com">hujun</a>
*
* @since 0.9.0
*/
public class LogbackNacosLogging extends AbstractNacosLogging {
@ -61,7 +61,7 @@ public class LogbackNacosLogging extends AbstractNacosLogging {
addListener(loggerContext);
}
}
private boolean hasListener(LoggerContext loggerContext) {
for (LoggerContextListener loggerContextListener : loggerContext.getCopyOfListenerList()) {
if (loggerContextListener instanceof NacosLoggerContextListener) {
@ -70,50 +70,55 @@ public class LogbackNacosLogging extends AbstractNacosLogging {
}
return false;
}
private LoggerContext loadConfigurationOnStart() {
String location = getLocation(NACOS_LOGBACK_LOCATION);
try {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Collection<NacosLogbackConfigurator> nacosLogbackConfigurators = NacosServiceLoader.load(
NacosLogbackConfigurator.class);
NacosLogbackConfigurator nacosLogbackConfigurator = nacosLogbackConfigurators.stream()
.filter(c -> c.getVersion() == userVersion).collect(Collectors.toList()).get(0);
nacosLogbackConfigurator.setContext(loggerContext);
nacosLogbackConfigurator.configure(ResourceUtils.getResourceUrl(location));
return loggerContext;
} catch (Exception e) {
throw new IllegalStateException("Could not initialize Logback Nacos logging from " + location, e);
}
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Collection<NacosLogbackConfigurator> nacosLogbackConfigurators = NacosServiceLoader.load(
NacosLogbackConfigurator.class);
nacosLogbackConfigurators.stream().filter(c -> c.getVersion() == userVersion).findFirst()
.ifPresent(nacosLogbackConfigurator -> {
nacosLogbackConfigurator.setContext(loggerContext);
if (StringUtils.isNotBlank(location)) {
try {
nacosLogbackConfigurator.configure(ResourceUtils.getResourceUrl(location));
} catch (Exception e) {
throw new IllegalStateException(
"Could not initialize Logback Nacos logging from " + location, e);
}
}
});
return loggerContext;
}
class NacosLoggerContextListener implements LoggerContextListener {
@Override
public boolean isResetResistant() {
return true;
}
@Override
public void onReset(LoggerContext context) {
loadConfigurationOnStart();
}
@Override
public void onStart(LoggerContext context) {
}
@Override
public void onStop(LoggerContext context) {
}
@Override
public void onLevelChange(Logger logger, Level level) {
}
}
private void addListener(LoggerContext loggerContext) {
loggerContext.addListener(new NacosLoggerContextListener());
}

View File

@ -142,6 +142,7 @@ public class NacosNamingService implements NamingService {
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
checkAndStripGroupNamePrefix(instance, groupName);
clientProxy.registerService(serviceName, groupName, instance);
}
@ -149,6 +150,7 @@ public class NacosNamingService implements NamingService {
public void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances)
throws NacosException {
NamingUtils.batchCheckInstanceIsLegal(instances);
batchCheckAndStripGroupNamePrefix(instances, groupName);
clientProxy.batchRegisterService(serviceName, groupName, instances);
}
@ -156,6 +158,7 @@ public class NacosNamingService implements NamingService {
public void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances)
throws NacosException {
NamingUtils.batchCheckInstanceIsLegal(instances);
batchCheckAndStripGroupNamePrefix(instances, groupName);
clientProxy.batchDeregisterService(serviceName, groupName, instances);
}
@ -191,6 +194,8 @@ public class NacosNamingService implements NamingService {
@Override
public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
checkAndStripGroupNamePrefix(instance, groupName);
clientProxy.deregisterService(serviceName, groupName, instance);
}
@ -470,4 +475,22 @@ public class NacosNamingService implements NamingService {
NotifyCenter.deregisterSubscriber(changeNotifier);
}
private void batchCheckAndStripGroupNamePrefix(List<Instance> instances, String groupName) throws NacosException {
for (Instance instance : instances) {
checkAndStripGroupNamePrefix(instance, groupName);
}
}
private void checkAndStripGroupNamePrefix(Instance instance, String groupName) throws NacosException {
String serviceName = instance.getServiceName();
if (serviceName != null) {
String groupNameOfInstance = NamingUtils.getGroupName(serviceName);
if (!groupName.equals(groupNameOfInstance)) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, String.format(
"wrong group name prefix of instance service name! it should be: %s, Instance: %s", groupName, instance));
}
instance.setServiceName(NamingUtils.getServiceName(serviceName));
}
}
}

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.client.naming.remote;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
@ -194,7 +195,10 @@ public class NamingClientProxyDelegate implements NamingClientProxy {
}
private NamingClientProxy getExecuteClientProxy(Instance instance) {
return instance.isEphemeral() ? grpcClientProxy : httpClientProxy;
if (instance.isEphemeral() || grpcClientProxy.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC)) {
return grpcClientProxy;
}
return httpClientProxy;
}
@Override

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.client.naming.remote.gprc;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.CommonParams;
@ -27,6 +29,7 @@ import com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;
import com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;
import com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.InstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.ServiceListRequest;
import com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest;
import com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;
@ -62,6 +65,7 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -128,6 +132,14 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
instance);
if (instance.isEphemeral()) {
registerServiceForEphemeral(serviceName, groupName, instance);
} else {
doRegisterServiceForPersistent(serviceName, groupName, instance);
}
}
private void registerServiceForEphemeral(String serviceName, String groupName, Instance instance) throws NacosException {
redoService.cacheInstanceForRedo(serviceName, groupName, instance);
doRegisterService(serviceName, groupName, instance);
}
@ -153,43 +165,60 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
*
* @param serviceName service name
* @param groupName group name
* @param instances instance list
* @return instance list that need to be deregistered.
* @param deRegisterInstances deregister instance list
* @return instance list that need to be retained.
*/
private List<Instance> getRetainInstance(String serviceName, String groupName, List<Instance> instances)
private List<Instance> getRetainInstance(String serviceName, String groupName, List<Instance> deRegisterInstances)
throws NacosException {
if (CollectionUtils.isEmpty(instances)) {
if (CollectionUtils.isEmpty(deRegisterInstances)) {
throw new NacosException(NacosException.INVALID_PARAM,
String.format("[Batch deRegistration] need deRegister instance is empty, instances: %s,",
instances));
deRegisterInstances));
}
String combinedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesByKey(combinedServiceName);
if (!(instanceRedoData instanceof BatchInstanceRedoData)) {
throw new NacosException(NacosException.INVALID_PARAM, String.format(
"[Batch deRegistration] batch deRegister is not BatchInstanceRedoData type , instances: %s,",
instances));
deRegisterInstances));
}
BatchInstanceRedoData batchInstanceRedoData = (BatchInstanceRedoData) instanceRedoData;
List<Instance> allInstance = batchInstanceRedoData.getInstances();
if (CollectionUtils.isEmpty(allInstance)) {
List<Instance> allRedoInstances = batchInstanceRedoData.getInstances();
if (CollectionUtils.isEmpty(allRedoInstances)) {
throw new NacosException(NacosException.INVALID_PARAM, String.format(
"[Batch deRegistration] not found all registerInstance , serviceName%s , groupName: %s",
serviceName, groupName));
}
Map<Instance, Instance> instanceMap = instances.stream()
Map<Instance, Instance> deRegisterInstanceMap = deRegisterInstances.stream()
.collect(Collectors.toMap(Function.identity(), Function.identity()));
List<Instance> retainInstances = new ArrayList<>();
for (Instance instance : allInstance) {
if (!instanceMap.containsKey(instance)) {
retainInstances.add(instance);
for (Instance redoInstance : allRedoInstances) {
boolean needRetained = true;
Iterator<Map.Entry<Instance, Instance>> it = deRegisterInstanceMap.entrySet().iterator();
while (it.hasNext()) {
Instance deRegisterInstance = it.next().getKey();
// only compare Ip & Port because redoInstance's instanceId or serviceName might be null but deRegisterInstance's might not be null.
if (compareIpAndPort(deRegisterInstance, redoInstance)) {
needRetained = false;
// clear current entry to speed up next redoInstance comparing.
it.remove();
break;
}
}
if (needRetained) {
retainInstances.add(redoInstance);
}
}
return retainInstances;
}
private boolean compareIpAndPort(Instance deRegisterInstance, Instance redoInstance) {
return ((deRegisterInstance.getIp().equals(redoInstance.getIp()))
&& (deRegisterInstance.getPort() == redoInstance.getPort()));
}
/**
* Execute batch register operation.
*
@ -221,10 +250,32 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
redoService.instanceRegistered(serviceName, groupName);
}
/**
* Execute register operation for persistent instance.
*
* @param serviceName name of service
* @param groupName group of service
* @param instance instance to register
* @throws NacosException nacos exception
*/
public void doRegisterServiceForPersistent(String serviceName, String groupName, Instance instance) throws NacosException {
PersistentInstanceRequest request = new PersistentInstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);
}
@Override
public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}", namespaceId,
serviceName, instance);
if (instance.isEphemeral()) {
deregisterServiceForEphemeral(serviceName, groupName, instance);
} else {
doDeregisterServiceForPersistent(serviceName, groupName, instance);
}
}
private void deregisterServiceForEphemeral(String serviceName, String groupName, Instance instance) throws NacosException {
String key = NamingUtils.getGroupedName(serviceName, groupName);
InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesByKey(key);
if (instanceRedoData instanceof BatchInstanceRedoData) {
@ -253,6 +304,20 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
requestToServer(request, Response.class);
redoService.instanceDeregistered(serviceName, groupName);
}
/**
* Execute deregister operation for persistent instance.
*
* @param serviceName service name
* @param groupName group name
* @param instance instance
* @throws NacosException nacos exception
*/
public void doDeregisterServiceForPersistent(String serviceName, String groupName, Instance instance) throws NacosException {
PersistentInstanceRequest request = new PersistentInstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.DE_REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);
}
@Override
public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {
@ -366,6 +431,16 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
return rpcClient.isRunning();
}
/**
* Determine whether nacos-server supports the capability.
*
* @param abilityKey ability key
* @return true if supported, otherwise false
*/
public boolean isAbilitySupportedByServer(AbilityKey abilityKey) {
return rpcClient.getConnectionAbility(abilityKey) == AbilityStatus.SUPPORTED;
}
private <T extends Response> T requestToServer(AbstractNamingRequest request, Class<T> responseClass)
throws NacosException {
Response response = null;

View File

@ -73,7 +73,7 @@ public class NamingHttpClientManager implements Closeable {
public void shutdown() throws NacosException {
NAMING_LOGGER.warn("[NamingHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));

View File

@ -268,7 +268,6 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy {
@Override
public boolean serverHealthy() {
try {
String result = reqApi(UtilAndComs.nacosUrlBase + "/operator/metrics", new HashMap<>(8), HttpMethod.GET);
JsonNode json = JacksonUtils.toObj(result);

View File

@ -61,14 +61,14 @@ public class ConfigEncryptionFilterTest {
public void testDoFilter() throws NacosException {
configEncryptionFilter.doFilter(configRequest, null, iConfigFilterChain);
Mockito.verify(configRequest).getDataId();
Mockito.verify(configRequest).getContent();
Mockito.verify(configRequest, Mockito.atLeast(1)).getDataId();
Mockito.verify(configRequest, Mockito.atLeast(1)).getContent();
configEncryptionFilter.doFilter(null, configResponse, iConfigFilterChain);
Mockito.verify(configResponse).getDataId();
Mockito.verify(configResponse).getContent();
Mockito.verify(configResponse).getEncryptedDataKey();
Mockito.verify(configResponse, Mockito.atLeast(1)).getDataId();
Mockito.verify(configResponse, Mockito.atLeast(1)).getContent();
Mockito.verify(configResponse, Mockito.atLeast(1)).getEncryptedDataKey();
}
@Test

View File

@ -18,9 +18,12 @@
package com.alibaba.nacos.client.logging.logback;
import ch.qos.logback.classic.LoggerContext;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import static org.hamcrest.CoreMatchers.isA;
@ -31,9 +34,12 @@ public class LogbackNacosLoggingTest {
@Test
public void testLoadConfiguration() {
exceptionRule.expectCause(isA(ClassCastException.class));
exceptionRule.expectMessage("Could not initialize Logback Nacos logging from classpath:nacos-logback.xml");
LogbackNacosLogging logbackNacosLogging = new LogbackNacosLogging();
logbackNacosLogging.loadConfiguration();
ILoggerFactory loggerFactory;
if ((loggerFactory = LoggerFactory.getILoggerFactory()) != null && loggerFactory instanceof LoggerContext) {
exceptionRule.expectCause(isA(ClassCastException.class));
exceptionRule.expectMessage("Could not initialize Logback Nacos logging from classpath:nacos-logback.xml");
LogbackNacosLogging logbackNacosLogging = new LogbackNacosLogging();
logbackNacosLogging.loadConfiguration();
}
}
}

View File

@ -120,6 +120,46 @@ public class NacosNamingServiceTest {
argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
}
@Test
public void testBatchRegisterInstanceWithGroupNamePrefix() throws NacosException {
Instance instance = new Instance();
String serviceName = "service1";
String ip = "1.1.1.1";
int port = 10000;
instance.setServiceName(Constants.DEFAULT_GROUP + "@@" + serviceName);
instance.setEphemeral(true);
instance.setPort(port);
instance.setIp(ip);
List<Instance> instanceList = new ArrayList<>();
instanceList.add(instance);
//when
client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
//then
verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),
argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
}
@Test
public void testBatchRegisterInstanceWithWrongGroupNamePrefix() throws NacosException {
Instance instance = new Instance();
String serviceName = "service1";
String ip = "1.1.1.1";
int port = 10000;
instance.setServiceName("WrongGroup" + "@@" + serviceName);
instance.setEphemeral(true);
instance.setPort(port);
instance.setIp(ip);
List<Instance> instanceList = new ArrayList<>();
instanceList.add(instance);
//when
try {
client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
} catch (Exception e) {
Assert.assertTrue(e instanceof NacosException);
Assert.assertTrue(e.getMessage().contains("wrong group name prefix of instance service name"));
}
}
@Test
public void testBatchDeRegisterInstance() throws NacosException {
Instance instance = new Instance();

View File

@ -18,6 +18,7 @@
package com.alibaba.nacos.client.naming.remote;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.Service;
@ -46,7 +47,7 @@ import static org.mockito.Mockito.when;
public class NamingClientProxyDelegateTest {
@Test
public void testRegisterServiceByGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
public void testRegisterEphemeralServiceByGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
@ -100,7 +101,36 @@ public class NamingClientProxyDelegateTest {
}
@Test
public void testRegisterServiceByHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {
public void testRegisterPersistentServiceByGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
props.setProperty("serverAddr", "localhost");
final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);
InstancesChangeNotifier notifier = new InstancesChangeNotifier();
NamingClientProxyDelegate delegate = new NamingClientProxyDelegate(ns, holder, nacosClientProperties, notifier);
NamingGrpcClientProxy mockGrpcClient = Mockito.mock(NamingGrpcClientProxy.class);
Field grpcClientProxyField = NamingClientProxyDelegate.class.getDeclaredField("grpcClientProxy");
grpcClientProxyField.setAccessible(true);
grpcClientProxyField.set(delegate, mockGrpcClient);
String serviceName = "service1";
String groupName = "group1";
Instance instance = new Instance();
instance.setServiceName(serviceName);
instance.setClusterName(groupName);
instance.setIp("1.1.1.1");
instance.setPort(1);
// persistent instance
instance.setEphemeral(false);
// when server support register persistent instance by grpc, will use grpc to register
when(mockGrpcClient.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(true);
delegate.registerService(serviceName, groupName, instance);
verify(mockGrpcClient, times(1)).registerService(serviceName, groupName, instance);
}
@Test
public void testRegisterPersistentServiceByHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
@ -121,14 +151,15 @@ public class NamingClientProxyDelegateTest {
instance.setClusterName(groupName);
instance.setIp("1.1.1.1");
instance.setPort(1);
// use grpc
// persistent instance
instance.setEphemeral(false);
// when server do not support register persistent instance by grpc, will use http to register
delegate.registerService(serviceName, groupName, instance);
verify(mockHttpClient, times(1)).registerService(serviceName, groupName, instance);
}
@Test
public void testDeregisterServiceGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
public void testDeregisterEphemeralServiceGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
@ -156,13 +187,43 @@ public class NamingClientProxyDelegateTest {
}
@Test
public void testDeregisterServiceHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {
public void testDeregisterPersistentServiceGrpc() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
props.setProperty("serverAddr", "localhost");
InstancesChangeNotifier notifier = new InstancesChangeNotifier();
final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);
NamingClientProxyDelegate delegate = new NamingClientProxyDelegate(ns, holder, nacosClientProperties, notifier);
NamingGrpcClientProxy mockGrpcClient = Mockito.mock(NamingGrpcClientProxy.class);
Field grpcClientProxyField = NamingClientProxyDelegate.class.getDeclaredField("grpcClientProxy");
grpcClientProxyField.setAccessible(true);
grpcClientProxyField.set(delegate, mockGrpcClient);
String serviceName = "service1";
String groupName = "group1";
Instance instance = new Instance();
instance.setServiceName(serviceName);
instance.setClusterName(groupName);
instance.setIp("1.1.1.1");
instance.setPort(1);
// persistent instance
instance.setEphemeral(false);
// when server support deregister persistent instance by grpc, will use grpc to deregister
when(mockGrpcClient.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(true);
delegate.deregisterService(serviceName, groupName, instance);
verify(mockGrpcClient, times(1)).deregisterService(serviceName, groupName, instance);
}
@Test
public void testDeregisterPersistentServiceHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {
String ns = "ns1";
ServiceInfoHolder holder = Mockito.mock(ServiceInfoHolder.class);
Properties props = new Properties();
props.setProperty("serverAddr", "localhost");
InstancesChangeNotifier notifier = new InstancesChangeNotifier();
final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);
NamingClientProxyDelegate delegate = new NamingClientProxyDelegate(ns, holder, nacosClientProperties, notifier);
NamingHttpClientProxy mockHttpClient = Mockito.mock(NamingHttpClientProxy.class);

View File

@ -18,6 +18,8 @@
package com.alibaba.nacos.client.naming.remote.gprc;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
@ -27,6 +29,7 @@ import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;
import com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.InstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest;
import com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;
import com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse;
import com.alibaba.nacos.api.naming.remote.response.InstanceResponse;
@ -123,6 +126,8 @@ public class NamingGrpcClientProxyTest {
private Instance instance;
private Instance persistentInstance;
private String uuid;
@Rule
@ -143,7 +148,7 @@ public class NamingGrpcClientProxyTest {
Field uuidField = NamingGrpcClientProxy.class.getDeclaredField("uuid");
uuidField.setAccessible(true);
uuid = (String) uuidField.get(client);
Assert.assertNotNull(RpcClientFactory.getClient(uuid));
Field rpcClientField = NamingGrpcClientProxy.class.getDeclaredField("rpcClient");
rpcClientField.setAccessible(true);
@ -156,6 +161,12 @@ public class NamingGrpcClientProxyTest {
instance.setServiceName(SERVICE_NAME);
instance.setIp("1.1.1.1");
instance.setPort(1111);
persistentInstance = new Instance();
persistentInstance.setServiceName(SERVICE_NAME);
persistentInstance.setIp("1.1.1.1");
persistentInstance.setPort(1111);
persistentInstance.setEphemeral(false);
}
@After
@ -177,6 +188,18 @@ public class NamingGrpcClientProxyTest {
}));
}
@Test
public void testRegisterPersistentService() throws NacosException {
client.registerService(SERVICE_NAME, GROUP_NAME, persistentInstance);
verify(this.rpcClient, times(1)).request(argThat(request -> {
if (request instanceof PersistentInstanceRequest) {
PersistentInstanceRequest request1 = (PersistentInstanceRequest) request;
return request1.getType().equals(NamingRemoteConstants.REGISTER_INSTANCE);
}
return false;
}));
}
@Test
public void testRegisterServiceThrowsNacosException() throws NacosException {
expectedException.expect(NacosException.class);
@ -220,6 +243,18 @@ public class NamingGrpcClientProxyTest {
return false;
}));
}
@Test
public void testDeregisterPersistentService() throws NacosException {
client.deregisterService(SERVICE_NAME, GROUP_NAME, persistentInstance);
verify(this.rpcClient, times(1)).request(argThat(request -> {
if (request instanceof PersistentInstanceRequest) {
PersistentInstanceRequest request1 = (PersistentInstanceRequest) request;
return request1.getType().equals(NamingRemoteConstants.DE_REGISTER_INSTANCE);
}
return false;
}));
}
@Test
public void testDeregisterServiceForBatchRegistered() throws NacosException {
@ -327,6 +362,36 @@ public class NamingGrpcClientProxyTest {
}));
}
@Test
public void testBatchDeregisterServiceWithOtherPortInstance() throws NacosException {
try {
List<Instance> instanceList = new ArrayList<>();
instance.setHealthy(true);
instanceList.add(instance);
instanceList.add(new Instance());
client.batchRegisterService(SERVICE_NAME, GROUP_NAME, instanceList);
} catch (Exception ignored) {
}
response = new BatchInstanceResponse();
when(this.rpcClient.request(any())).thenReturn(response);
Instance otherPortInstance = new Instance();
otherPortInstance.setServiceName(SERVICE_NAME);
otherPortInstance.setIp("1.1.1.1");
otherPortInstance.setPort(2222);
List<Instance> instanceList = new ArrayList<>();
instanceList.add(otherPortInstance);
client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);
verify(this.rpcClient, times(2)).request(argThat(request -> {
if (request instanceof BatchInstanceRequest) {
BatchInstanceRequest request1 = (BatchInstanceRequest) request;
request1.setRequestId("1");
return request1.getInstances().size() == 2 && request1.getType()
.equals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE);
}
return false;
}));
}
@Test
public void testUpdateInstance() throws Exception {
//TODO thrown.expect(UnsupportedOperationException.class);
@ -431,6 +496,42 @@ public class NamingGrpcClientProxyTest {
Assert.assertTrue(client.serverHealthy());
verify(this.rpcClient, times(1)).isRunning();
}
@Test
public void testIsAbilitySupportedByServer1() {
when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC))
.thenReturn(AbilityStatus.SUPPORTED);
Assert.assertTrue(client.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
verify(this.rpcClient, times(1))
.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC);
}
@Test
public void testIsAbilitySupportedByServer2() {
when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC))
.thenReturn(AbilityStatus.NOT_SUPPORTED);
Assert.assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
verify(this.rpcClient, times(1))
.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC);
}
@Test
public void testIsAbilitySupportedByServer3() {
when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC))
.thenReturn(AbilityStatus.UNKNOWN);
Assert.assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
verify(this.rpcClient, times(1))
.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC);
}
@Test
public void testIsAbilitySupportedByServer4() {
when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC))
.thenReturn(null);
Assert.assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC));
verify(this.rpcClient, times(1))
.getConnectionAbility(AbilityKey.SERVER_SUPPORT_PERSISTENT_INSTANCE_BY_GRPC);
}
@Test
public void testShutdown() throws Exception {

View File

@ -61,6 +61,18 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -196,9 +196,6 @@ public abstract class AbstractHttpClientFactory implements HttpClientFactory {
@SuppressWarnings("checkstyle:abbreviationaswordinname")
protected synchronized SSLContext loadSSLContext() {
if (!TlsSystemConfig.tlsEnable) {
return null;
}
try {
return TlsHelper.buildSslContext(true);
} catch (NoSuchAlgorithmException | KeyManagementException e) {

View File

@ -118,7 +118,7 @@ public final class HttpClientBeanHolder {
* @throws Exception ex
*/
public static void shutdown(String className) throws Exception {
shutdownNacostSyncRest(className);
shutdownNacosSyncRest(className);
shutdownNacosAsyncRest(className);
}
@ -128,7 +128,7 @@ public final class HttpClientBeanHolder {
* @param className HttpClientFactory implement class name
* @throws Exception ex
*/
public static void shutdownNacostSyncRest(String className) throws Exception {
public static void shutdownNacosSyncRest(String className) throws Exception {
final NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(className);
if (nacosRestTemplate != null) {
nacosRestTemplate.close();

View File

@ -66,9 +66,6 @@ public class JdkHttpClientResponse implements HttpClientResponse {
// Used to process http content_encoding, when content_encoding is GZIP, use GZIPInputStream
if (CONTENT_ENCODING.equals(contentEncoding)) {
byte[] bytes = IoUtils.tryDecompress(this.responseStream);
if (bytes == null) {
throw new IOException("decompress http response error");
}
return new ByteArrayInputStream(bytes);
}
return this.responseStream;

View File

@ -1,42 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.handler;
import com.alibaba.nacos.common.utils.JacksonUtils;
import java.io.InputStream;
import java.lang.reflect.Type;
/**
* Response handler.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public final class ResponseHandler {
public static <T> T convert(String s, Class<T> cls) throws Exception {
return JacksonUtils.toObj(s, cls);
}
public static <T> T convert(String s, Type type) throws Exception {
return JacksonUtils.toObj(s, type);
}
public static <T> T convert(InputStream inputStream, Type type) throws Exception {
return JacksonUtils.toObj(inputStream, type);
}
}

View File

@ -42,24 +42,21 @@ public class Header {
private static final String DEFAULT_CHARSET = "UTF-8";
private static final String DEFAULT_ENCODING = "gzip";
private Header() {
header = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
originalResponseHeader = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, DEFAULT_CHARSET);
//addParam(HttpHeaderConsts.ACCEPT_ENCODING, DEFAULT_ENCODING);
}
public static Header newInstance() {
return new Header();
}
/**
* Add the key and value to the header.
*
* @param key the key
* @param key the key
* @param value the value
* @return header
*/
@ -77,10 +74,6 @@ public class Header {
return addParam(HttpHeaderConsts.CONTENT_TYPE, contentType);
}
public Header build() {
return this;
}
public String getValue(String key) {
return header.get(key);
}
@ -146,7 +139,7 @@ public class Header {
*
* <p>Currently only corresponds to the response header of JDK.
*
* @param key original response header key
* @param key original response header key
* @param values original response header values
*/
public void addOriginalResponseHeader(String key, List<String> values) {
@ -179,7 +172,7 @@ public class Header {
private String analysisCharset(String contentType) {
String[] values = contentType.split(";");
String charset = Constants.ENCODE;
if (values.length == 0) {
if (values.length == 1) {
return charset;
}
for (String value : values) {

View File

@ -21,7 +21,6 @@ import com.alibaba.nacos.common.utils.MapUtil;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -80,20 +79,6 @@ public class Query {
return this;
}
/**
* Add query parameters from KV list. KV list: odd index is key, even index is value.
*
* @param list KV list
*/
public void initParams(List<String> list) {
if ((list.size() & 1) != 0) {
throw new IllegalArgumentException("list size must be a multiple of 2");
}
for (int i = 0; i < list.size(); ) {
addParam(list.get(i++), list.get(i++));
}
}
/**
* Print query as a http url param string. Like K=V&K=V.
*
@ -122,8 +107,8 @@ public class Query {
}
public void clear() {
isEmpty = false;
params.clear();
isEmpty = true;
}
public boolean isEmpty() {

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.packagescan.util.PathMatcher;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.ArrayList;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import java.io.ByteArrayInputStream;
import java.io.IOException;

View File

@ -16,8 +16,8 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractObjectUtils;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractObjectUtils;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.alibaba.nacos.common.utils.StringUtils;

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.packagescan.util.ResourceUtils;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.alibaba.nacos.common.utils.StringUtils;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.StringUtils;
import java.io.File;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import java.io.IOException;
import java.io.InputStream;

View File

@ -18,7 +18,7 @@ package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.packagescan.util.PathMatcher;
import com.alibaba.nacos.common.packagescan.util.ResourceUtils;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.alibaba.nacos.common.utils.ReflectUtils;
import com.alibaba.nacos.common.utils.StringUtils;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import java.io.File;
import java.io.FileNotFoundException;

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.packagescan.util.ResourceUtils;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.utils.StringUtils;
import java.io.File;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.common.packagescan.resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.AbstractAssert;
import com.alibaba.nacos.common.packagescan.util.NestedIoException;
import java.io.File;

View File

@ -1,11 +1,11 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@ -14,7 +14,10 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.utils;
package com.alibaba.nacos.common.packagescan.util;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.Collection;
import java.util.Map;

View File

@ -1,11 +1,11 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.utils;
package com.alibaba.nacos.common.packagescan.util;
import java.lang.reflect.Array;
import java.util.Arrays;

View File

@ -17,7 +17,6 @@
package com.alibaba.nacos.common.packagescan.util;
import com.alibaba.nacos.common.packagescan.resource.Resource;
import com.alibaba.nacos.common.utils.AbstractAssert;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.alibaba.nacos.common.utils.StringUtils;

View File

@ -29,9 +29,9 @@ public enum ConnectionType {
*/
GRPC("GRPC", "Grpc Connection");
String type;
final String type;
String name;
final String name;
public static ConnectionType getByType(String type) {
ConnectionType[] values = ConnectionType.values();
@ -57,15 +57,6 @@ public enum ConnectionType {
return type;
}
/**
* Setter method for property <tt>type</tt>.
*
* @param type value to be assigned to property type
*/
public void setType(String type) {
this.type = type;
}
/**
* Getter method for property <tt>name</tt>.
*
@ -74,13 +65,4 @@ public enum ConnectionType {
public String getName() {
return name;
}
/**
* Setter method for property <tt>name</tt>.
*
* @param name value to be assigned to property name
*/
public void setName(String name) {
this.name = name;
}
}

View File

@ -44,7 +44,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
@ -83,7 +82,7 @@ public abstract class RpcClient implements Closeable {
private final BlockingQueue<ReconnectContext> reconnectionSignal = new ArrayBlockingQueue<>(1);
protected volatile Connection currentConnection;
private String tenant;
private long lastActiveTimeStamp = System.currentTimeMillis();
@ -101,9 +100,9 @@ public abstract class RpcClient implements Closeable {
private static final Pattern EXCLUDE_PROTOCOL_PATTERN = Pattern.compile("(?<=\\w{1,5}://)(.*)");
protected RpcClientConfig rpcClientConfig;
protected final ResourceLoader resourceLoader = new DefaultResourceLoader();
static {
PayloadRegistry.init();
}
@ -117,7 +116,7 @@ public abstract class RpcClient implements Closeable {
this.serverListFactory = serverListFactory;
init();
}
protected void init() {
if (this.serverListFactory != null) {
rpcClientStatus.compareAndSet(RpcClientStatus.WAIT_INIT, RpcClientStatus.INITIALIZED);
@ -126,10 +125,6 @@ public abstract class RpcClient implements Closeable {
}
}
public Map<String, String> labels() {
return Collections.unmodifiableMap(rpcClientConfig.labels());
}
/**
* init server list factory. only can init once.
*
@ -170,7 +165,7 @@ public abstract class RpcClient implements Closeable {
/**
* Notify when client new connected.
*
* @param connection connection has connected
* @param connection connection has connected
*/
protected void notifyConnected(Connection connection) {
if (connectionEventListeners.isEmpty()) {
@ -277,8 +272,8 @@ public abstract class RpcClient implements Closeable {
if (isShutdown()) {
break;
}
ReconnectContext reconnectContext = reconnectionSignal.poll(rpcClientConfig.connectionKeepAlive(),
TimeUnit.MILLISECONDS);
ReconnectContext reconnectContext = reconnectionSignal
.poll(rpcClientConfig.connectionKeepAlive(), TimeUnit.MILLISECONDS);
if (reconnectContext == null) {
// check alive time.
if (System.currentTimeMillis() - lastActiveTimeStamp >= rpcClientConfig.connectionKeepAlive()) {
@ -296,8 +291,8 @@ public abstract class RpcClient implements Closeable {
break;
}
boolean statusFLowSuccess = RpcClient.this.rpcClientStatus.compareAndSet(
rpcClientStatus, RpcClientStatus.UNHEALTHY);
boolean statusFLowSuccess = RpcClient.this.rpcClientStatus
.compareAndSet(rpcClientStatus, RpcClientStatus.UNHEALTHY);
if (statusFLowSuccess) {
reconnectContext = new ReconnectContext(null, false);
} else {
@ -364,9 +359,10 @@ public abstract class RpcClient implements Closeable {
}
if (connectToServer != null) {
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}] Success to connect to server [{}] on start up, connectionId = {}", rpcClientConfig.name(),
connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId());
LoggerUtils
.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up, connectionId = {}",
rpcClientConfig.name(), connectToServer.serverInfo.getAddress(),
connectToServer.getConnectionId());
this.currentConnection = connectToServer;
rpcClientStatus.set(RpcClientStatus.RUNNING);
eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED, currentConnection));
@ -400,8 +396,8 @@ public abstract class RpcClient implements Closeable {
ConnectResetRequest connectResetRequest = (ConnectResetRequest) request;
if (StringUtils.isNotBlank(connectResetRequest.getServerIp())) {
ServerInfo serverInfo = resolveServerInfo(
connectResetRequest.getServerIp() + Constants.COLON
+ connectResetRequest.getServerPort());
connectResetRequest.getServerIp() + Constants.COLON + connectResetRequest
.getServerPort());
switchServerAsync(serverInfo, false);
} else {
switchServerAsync();
@ -418,15 +414,15 @@ public abstract class RpcClient implements Closeable {
}
}
/**.
* invoke after receiving reset request
/**
* . invoke after receiving reset request
*
* @param request request for resetting
*/
protected void afterReset(ConnectResetRequest request) {
// hook for GrpcClient
}
@Override
public void shutdown() throws NacosException {
LOGGER.info("Shutdown rpc client, set status to shutdown");
@ -451,8 +447,8 @@ public abstract class RpcClient implements Closeable {
if (reTryTimes > 1) {
Thread.sleep(random.nextInt(500));
}
Response response = this.currentConnection.request(healthCheckRequest,
rpcClientConfig.healthCheckTimeOut());
Response response = this.currentConnection
.request(healthCheckRequest, rpcClientConfig.healthCheckTimeOut());
// not only check server is ok, also check connection is register.
return response != null && response.isSuccess();
} catch (Exception e) {
@ -508,9 +504,10 @@ public abstract class RpcClient implements Closeable {
// 2.create a new channel to new server
Connection connectionNew = connectToServer(serverInfo);
if (connectionNew != null) {
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}] Success to connect a server [{}], connectionId = {}", rpcClientConfig.name(),
serverInfo.getAddress(), connectionNew.getConnectionId());
LoggerUtils
.printIfInfoEnabled(LOGGER, "[{}] Success to connect a server [{}], connectionId = {}",
rpcClientConfig.name(), serverInfo.getAddress(),
connectionNew.getConnectionId());
// successfully create a new connect.
if (currentConnection != null) {
LoggerUtils.printIfInfoEnabled(LOGGER,
@ -579,8 +576,9 @@ public abstract class RpcClient implements Closeable {
}
} catch (Exception e) {
LoggerUtils.printIfWarnEnabled(LOGGER, "[{}] Fail to reconnect to server, error is {}",
rpcClientConfig.name(), e);
LoggerUtils
.printIfWarnEnabled(LOGGER, "[{}] Fail to reconnect to server, error is {}", rpcClientConfig.name(),
e);
}
}
@ -713,8 +711,8 @@ public abstract class RpcClient implements Closeable {
int retryTimes = 0;
Throwable exceptionToThrow = null;
long start = System.currentTimeMillis();
while (retryTimes <= rpcClientConfig.retryTimes()
&& System.currentTimeMillis() < start + callback.getTimeout()) {
while (retryTimes <= rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + callback
.getTimeout()) {
boolean waitReconnect = false;
try {
if (this.currentConnection == null || !isRunning()) {
@ -763,8 +761,8 @@ public abstract class RpcClient implements Closeable {
int retryTimes = 0;
long start = System.currentTimeMillis();
Exception exceptionToThrow = null;
while (retryTimes <= rpcClientConfig.retryTimes()
&& System.currentTimeMillis() < start + rpcClientConfig.timeOutMills()) {
while (retryTimes <= rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + rpcClientConfig
.timeOutMills()) {
boolean waitReconnect = false;
try {
if (this.currentConnection == null || !isRunning()) {
@ -979,7 +977,7 @@ public abstract class RpcClient implements Closeable {
}
}
public class ConnectionEvent {
public static class ConnectionEvent {
public static final int CONNECTED = 1;
@ -988,7 +986,7 @@ public abstract class RpcClient implements Closeable {
int eventType;
Connection connection;
public ConnectionEvent(int eventType, Connection connection) {
this.eventType = eventType;
this.connection = connection;
@ -1012,7 +1010,7 @@ public abstract class RpcClient implements Closeable {
return rpcClientConfig.labels();
}
class ReconnectContext {
static class ReconnectContext {
public ReconnectContext(ServerInfo serverInfo, boolean onRequestFail) {
this.onRequestFail = onRequestFail;
@ -1031,7 +1029,7 @@ public abstract class RpcClient implements Closeable {
public void setTenant(String tenant) {
this.tenant = tenant;
}
/**
* Return ability of current connection.
*

View File

@ -74,19 +74,18 @@ public class RpcClientFactory {
public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels) {
return createClient(clientName, connectionType, null, null, labels);
}
public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels,
RpcClientTlsConfig tlsConfig) {
RpcClientTlsConfig tlsConfig) {
return createClient(clientName, connectionType, null, null, labels, tlsConfig);
}
public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer
threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels) {
public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels) {
return createClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);
}
/**
* create a rpc client.
*
@ -98,21 +97,15 @@ public class RpcClientFactory {
* @return rpc client.
*/
public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
if (!ConnectionType.GRPC.equals(connectionType)) {
throw new UnsupportedOperationException("unsupported connection type :" + connectionType.getType());
}
return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {
LOGGER.info("[RpcClientFactory] create a new rpc client of " + clientName);
try {
return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);
} catch (Throwable throwable) {
LOGGER.error("Error to init GrpcSdkClient for client name :" + clientName, throwable);
throw throwable;
}
return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);
});
}
@ -124,15 +117,15 @@ public class RpcClientFactory {
* @return rpc client.
*/
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Map<String, String> labels) {
Map<String, String> labels) {
return createClusterClient(clientName, connectionType, null, null, labels);
}
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
return createClusterClient(clientName, connectionType, null, null, labels, tlsConfig);
}
/**
* create a rpc client.
*
@ -143,29 +136,31 @@ public class RpcClientFactory {
* @return rpc client.
*/
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {
Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {
return createClusterClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);
}
/**
* createClusterClient.
* @param clientName client name.
* @param connectionType connectionType.
*
* @param clientName client name.
* @param connectionType connectionType.
* @param threadPoolCoreSize coreSize.
* @param threadPoolMaxSize threadPoolSize.
* @param labels tables.
* @param tlsConfig tlsConfig.
* @param threadPoolMaxSize threadPoolSize.
* @param labels tables.
* @param tlsConfig tlsConfig.
* @return
*/
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels,
RpcClientTlsConfig tlsConfig) {
if (!ConnectionType.GRPC.equals(connectionType)) {
throw new UnsupportedOperationException("unsupported connection type :" + connectionType.getType());
}
return CLIENT_MAP.computeIfAbsent(clientName,
clientNameInner -> new GrpcClusterClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize,
labels, tlsConfig));
clientNameInner -> new GrpcClusterClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels,
tlsConfig));
}
}

View File

@ -18,10 +18,9 @@ package com.alibaba.nacos.common.remote.client;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashSet;
@ -33,64 +32,64 @@ import java.util.Set;
* @author githubcheng2978.
*/
public class RpcConstants {
public static final String NACOS_CLIENT_RPC = "nacos.remote.client.rpc";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_ENABLE = NACOS_CLIENT_RPC + ".tls.enable";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_PROVIDER = NACOS_CLIENT_RPC + ".tls.provider";
@RpcConfigLabel
public static final String RPC_CLIENT_MUTUAL_AUTH = NACOS_CLIENT_RPC + ".tls.mutualAuth";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_PROTOCOLS = NACOS_CLIENT_RPC + ".tls.protocols";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_CIPHERS = NACOS_CLIENT_RPC + ".tls.ciphers";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_CERT_CHAIN_PATH = NACOS_CLIENT_RPC + ".tls.certChainFile";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_CERT_KEY = NACOS_CLIENT_RPC + ".tls.certPrivateKey";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_TRUST_PWD = NACOS_CLIENT_RPC + ".tls.certPrivateKeyPassword";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH = NACOS_CLIENT_RPC + ".tls.trustCollectionChainPath";
public static final String RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH =
NACOS_CLIENT_RPC + ".tls.trustCollectionChainPath";
@RpcConfigLabel
public static final String RPC_CLIENT_TLS_TRUST_ALL = NACOS_CLIENT_RPC + ".tls.trustAll";
private static final Set<String> CONFIG_NAMES = new HashSet<>();
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
protected @interface RpcConfigLabel {
}
static {
Class clazz = RpcConstants.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(
RpcConfigLabel.class)) {
if (declaredField.getType().equals(String.class) && null != declaredField
.getAnnotation(RpcConfigLabel.class)) {
try {
CONFIG_NAMES.add((String) declaredField.get(null));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalAccessException ignored) {
}
}
}
}
public static Set<String> getRpcParams() {
return Collections.unmodifiableSet(CONFIG_NAMES);
}

View File

@ -251,59 +251,59 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig {
* @return Builder
*/
public Builder fromProperties(Properties properties) {
if (properties.contains(GrpcConstants.GRPC_NAME)) {
if (properties.containsKey(GrpcConstants.GRPC_NAME)) {
this.name = properties.getProperty(GrpcConstants.GRPC_NAME);
}
if (properties.contains(GrpcConstants.GRPC_RETRY_TIMES)) {
if (properties.containsKey(GrpcConstants.GRPC_RETRY_TIMES)) {
this.retryTimes = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_RETRY_TIMES));
}
if (properties.contains(GrpcConstants.GRPC_TIMEOUT_MILLS)) {
if (properties.containsKey(GrpcConstants.GRPC_TIMEOUT_MILLS)) {
this.timeOutMills = Long.parseLong(properties.getProperty(GrpcConstants.GRPC_TIMEOUT_MILLS));
}
if (properties.contains(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)) {
if (properties.containsKey(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)) {
this.connectionKeepAlive = Long
.parseLong(properties.getProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME));
}
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)) {
if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)) {
this.threadPoolKeepAlive = Long
.parseLong(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME));
}
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)) {
if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)) {
this.threadPoolCoreSize = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE));
}
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)) {
if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)) {
this.threadPoolMaxSize = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE));
}
if (properties.contains(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)) {
if (properties.containsKey(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)) {
this.serverCheckTimeOut = Long
.parseLong(properties.getProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT));
}
if (properties.contains(GrpcConstants.GRPC_QUEUESIZE)) {
if (properties.containsKey(GrpcConstants.GRPC_QUEUESIZE)) {
this.threadPoolQueueSize = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_QUEUESIZE));
}
if (properties.contains(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)) {
if (properties.containsKey(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)) {
this.maxInboundMessageSize = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE));
}
if (properties.contains(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)) {
if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)) {
this.channelKeepAlive = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME));
}
if (properties.contains(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)) {
if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)) {
this.capabilityNegotiationTimeout = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT));
}
if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) {
if (properties.containsKey(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) {
this.healthCheckRetryTimes = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES));
}
if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)) {
if (properties.containsKey(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)) {
this.healthCheckTimeOut = Long
.parseLong(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT));
}
if (properties.contains(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)) {
if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)) {
this.channelKeepAliveTimeout = Integer
.parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT));
}
@ -414,8 +414,9 @@ public class DefaultGrpcClientConfig implements GrpcClientConfig {
return this;
}
public void setCapabilityNegotiationTimeout(long capabilityNegotiationTimeout) {
public Builder setCapabilityNegotiationTimeout(long capabilityNegotiationTimeout) {
this.capabilityNegotiationTimeout = capabilityNegotiationTimeout;
return this;
}
/**

View File

@ -33,18 +33,18 @@ import com.alibaba.nacos.api.remote.response.SetupAckResponse;
import com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder;
import com.alibaba.nacos.common.packagescan.resource.Resource;
import com.alibaba.nacos.common.remote.ConnectionType;
import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;
import com.alibaba.nacos.common.remote.client.RpcClientStatus;
import com.alibaba.nacos.common.remote.client.RpcClient;
import com.alibaba.nacos.common.remote.client.ServerListFactory;
import com.alibaba.nacos.common.remote.client.Connection;
import com.alibaba.nacos.common.remote.client.RpcClient;
import com.alibaba.nacos.common.remote.client.RpcClientStatus;
import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;
import com.alibaba.nacos.common.remote.client.ServerListFactory;
import com.alibaba.nacos.common.remote.client.ServerRequestHandler;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.LoggerUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.common.utils.TlsTypeResolve;
import com.alibaba.nacos.common.utils.ThreadFactoryBuilder;
import com.alibaba.nacos.common.utils.TlsTypeResolve;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.google.common.util.concurrent.ListenableFuture;
import io.grpc.CompressorRegistry;
import io.grpc.DecompressorRegistry;
@ -60,10 +60,10 @@ import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.HashMap;
import java.util.Optional;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
@ -89,12 +89,12 @@ public abstract class GrpcClient extends RpcClient {
* Block to wait setup success response.
*/
private final RecAbilityContext recAbilityContext = new RecAbilityContext(null);
/**
* for receiving server abilities.
*/
private SetupRequestHandler setupRequestHandler;
@Override
public ConnectionType getConnectionType() {
return ConnectionType.GRPC;
@ -108,7 +108,7 @@ public abstract class GrpcClient extends RpcClient {
public GrpcClient(String name) {
this(DefaultGrpcClientConfig.newBuilder().setName(name).build());
}
/**
* constructor.
*
@ -140,7 +140,7 @@ public abstract class GrpcClient extends RpcClient {
this.clientConfig = clientConfig;
initSetupHandler();
}
/**
* setup handler.
*/
@ -188,17 +188,17 @@ public abstract class GrpcClient extends RpcClient {
grpcExecutor.shutdown();
}
}
/**
* Create a stub using a channel.
*
* @param managedChannelTemp channel.
* @return if server check success,return a non-null stub.
*/
private RequestGrpc.RequestFutureStub createNewChannelStub(ManagedChannel managedChannelTemp) {
protected RequestGrpc.RequestFutureStub createNewChannelStub(ManagedChannel managedChannelTemp) {
return RequestGrpc.newFutureStub(managedChannelTemp);
}
/**
* create a new channel with specific server address.
*
@ -209,15 +209,15 @@ public abstract class GrpcClient extends RpcClient {
private ManagedChannel createNewManagedChannel(String serverIp, int serverPort) {
LOGGER.info("grpc client connection server:{} ip,serverPort:{},grpcTslConfig:{}", serverIp, serverPort,
JacksonUtils.toJson(clientConfig.tlsConfig()));
ManagedChannelBuilder<?> managedChannelBuilder = buildChannel(serverIp, serverPort, buildSslContext()).executor(
grpcExecutor).compressorRegistry(CompressorRegistry.getDefaultInstance())
ManagedChannelBuilder<?> managedChannelBuilder = buildChannel(serverIp, serverPort, buildSslContext())
.executor(grpcExecutor).compressorRegistry(CompressorRegistry.getDefaultInstance())
.decompressorRegistry(DecompressorRegistry.getDefaultInstance())
.maxInboundMessageSize(clientConfig.maxInboundMessageSize())
.keepAliveTime(clientConfig.channelKeepAlive(), TimeUnit.MILLISECONDS)
.keepAliveTimeout(clientConfig.channelKeepAliveTimeout(), TimeUnit.MILLISECONDS);
return managedChannelBuilder.build();
}
/**
* shutdown a channel.
*
@ -237,9 +237,6 @@ public abstract class GrpcClient extends RpcClient {
*/
private Response serverCheck(String ip, int port, RequestGrpc.RequestFutureStub requestBlockingStub) {
try {
if (requestBlockingStub == null) {
return null;
}
ServerCheckRequest serverCheckRequest = new ServerCheckRequest();
Payload grpcRequest = GrpcUtils.convert(serverCheckRequest);
ListenableFuture<Payload> responseFuture = requestBlockingStub.request(grpcRequest);
@ -291,8 +288,8 @@ public abstract class GrpcClient extends RpcClient {
} catch (Exception e) {
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}]Handle server request exception: {}",
grpcConn.getConnectionId(), payload.toString(), e.getMessage());
Response errResponse = ErrorResponse.build(NacosException.CLIENT_ERROR,
"Handle server request error");
Response errResponse = ErrorResponse
.build(NacosException.CLIENT_ERROR, "Handle server request error");
errResponse.setRequestId(request.getRequestId());
sendResponse(errResponse);
}
@ -366,7 +363,7 @@ public abstract class GrpcClient extends RpcClient {
int port = serverInfo.getServerPort() + rpcPortOffset();
ManagedChannel managedChannel = createNewManagedChannel(serverInfo.getServerIp(), port);
RequestGrpc.RequestFutureStub newChannelStubTemp = createNewChannelStub(managedChannel);
Response response = serverCheck(serverInfo.getServerIp(), port, newChannelStubTemp);
if (!(response instanceof ServerCheckResponse)) {
shuntDownChannel(managedChannel);
@ -376,9 +373,9 @@ public abstract class GrpcClient extends RpcClient {
// ability table will be null if server doesn't support ability table
ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response;
connectionId = serverCheckResponse.getConnectionId();
BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc.newStub(
newChannelStubTemp.getChannel());
BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc
.newStub(newChannelStubTemp.getChannel());
GrpcConnection grpcConn = new GrpcConnection(serverInfo, grpcExecutor);
grpcConn.setConnectionId(connectionId);
// if not supported, it will be false
@ -388,10 +385,10 @@ public abstract class GrpcClient extends RpcClient {
// promise null if no abilities receive
grpcConn.setAbilityTable(null);
}
//create stream request and bind connection event to this connection.
StreamObserver<Payload> payloadStreamObserver = bindRequestStream(biRequestStreamStub, grpcConn);
// stream observer to send response to server
grpcConn.setPayloadStreamObserver(payloadStreamObserver);
grpcConn.setGrpcFutureServiceStub(newChannelStubTemp);
@ -401,8 +398,8 @@ public abstract class GrpcClient extends RpcClient {
conSetupRequest.setClientVersion(VersionUtils.getFullClientVersion());
conSetupRequest.setLabels(super.getLabels());
// set ability table
conSetupRequest.setAbilityTable(
NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(abilityMode()));
conSetupRequest
.setAbilityTable(NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(abilityMode()));
conSetupRequest.setTenant(super.getTenant());
grpcConn.sendRequest(conSetupRequest);
// wait for response
@ -427,14 +424,14 @@ public abstract class GrpcClient extends RpcClient {
}
return null;
}
/**
* ability mode: sdk client or cluster client.
*
* @return mode
*/
protected abstract AbilityMode abilityMode();
@Override
protected void afterReset(ConnectResetRequest request) {
recAbilityContext.release(null);
@ -454,14 +451,14 @@ public abstract class GrpcClient extends RpcClient {
* way to block client.
*/
private volatile CountDownLatch blocker;
private volatile boolean needToSync = false;
public RecAbilityContext(Connection connection) {
this.connection = connection;
this.blocker = new CountDownLatch(1);
}
/**
* whether to sync for ability table.
*
@ -470,7 +467,7 @@ public abstract class GrpcClient extends RpcClient {
public boolean isNeedToSync() {
return this.needToSync;
}
/**
* reset with new connection which is waiting for ability table.
*
@ -481,7 +478,7 @@ public abstract class GrpcClient extends RpcClient {
this.blocker = new CountDownLatch(1);
this.needToSync = true;
}
/**
* notify sync by abilities.
*
@ -503,7 +500,7 @@ public abstract class GrpcClient extends RpcClient {
* await for abilities.
*
* @param timeout timeout.
* @param unit unit.
* @param unit unit.
* @throws InterruptedException by blocker.
*/
public void await(long timeout, TimeUnit unit) throws InterruptedException {
@ -512,16 +509,17 @@ public abstract class GrpcClient extends RpcClient {
}
this.needToSync = false;
}
/**
* check whether receive abilities.
*
* @param connection conn.
* @return whether receive abilities.
* @param connection conn.
* @return whether receive abilities.
*/
public boolean check(Connection connection) {
if (!connection.isAbilitiesSet()) {
LOGGER.error("Client don't receive server abilities table even empty table but server supports ability negotiation."
LOGGER.error(
"Client don't receive server abilities table even empty table but server supports ability negotiation."
+ " You can check if it is need to adjust the timeout of ability negotiation by property: {}"
+ " if always fail to connect.",
GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT);
@ -532,26 +530,26 @@ public abstract class GrpcClient extends RpcClient {
return true;
}
}
/**
* Setup response handler.
*/
class SetupRequestHandler implements ServerRequestHandler {
private final RecAbilityContext abilityContext;
public SetupRequestHandler(RecAbilityContext abilityContext) {
this.abilityContext = abilityContext;
}
@Override
public Response requestReply(Request request, Connection connection) {
// if finish setup
if (request instanceof SetupAckRequest) {
SetupAckRequest setupAckRequest = (SetupAckRequest) request;
// remove and count down
recAbilityContext.release(Optional.ofNullable(setupAckRequest.getAbilityTable())
.orElse(new HashMap<>(0)));
recAbilityContext
.release(Optional.ofNullable(setupAckRequest.getAbilityTable()).orElse(new HashMap<>(0)));
return new SetupAckResponse();
}
return null;
@ -562,14 +560,14 @@ public abstract class GrpcClient extends RpcClient {
if (sslContext.isPresent()) {
return NettyChannelBuilder.forAddress(serverIp, port).negotiationType(NegotiationType.TLS)
.sslContext(sslContext.get());
} else {
return ManagedChannelBuilder.forAddress(serverIp, port).usePlaintext();
}
}
private Optional<SslContext> buildSslContext() {
RpcClientTlsConfig tlsConfig = clientConfig.tlsConfig();
if (!tlsConfig.getEnableTls()) {
return Optional.empty();
@ -579,7 +577,7 @@ public abstract class GrpcClient extends RpcClient {
if (StringUtils.isNotBlank(tlsConfig.getSslProvider())) {
builder.sslProvider(TlsTypeResolve.getSslProvider(tlsConfig.getSslProvider()));
}
if (StringUtils.isNotBlank(tlsConfig.getProtocols())) {
builder.protocols(tlsConfig.getProtocols().split(","));
}
@ -595,10 +593,10 @@ public abstract class GrpcClient extends RpcClient {
Resource resource = resourceLoader.getResource(tlsConfig.getTrustCollectionCertFile());
builder.trustManager(resource.getInputStream());
}
if (tlsConfig.getMutualAuthEnable()) {
if (StringUtils.isBlank(tlsConfig.getCertChainFile()) || StringUtils.isBlank(
tlsConfig.getCertPrivateKey())) {
if (StringUtils.isBlank(tlsConfig.getCertChainFile()) || StringUtils
.isBlank(tlsConfig.getCertPrivateKey())) {
throw new IllegalArgumentException("client certChainFile or certPrivateKey must be not null");
}
Resource certChainFile = resourceLoader.getResource(tlsConfig.getCertChainFile());

View File

@ -172,16 +172,14 @@ public class GrpcConnection extends Connection {
if (this.payloadStreamObserver != null) {
try {
payloadStreamObserver.onCompleted();
} catch (Throwable throwable) {
//ignore.
} catch (Throwable ignored) {
}
}
if (this.channel != null && !channel.isShutdown()) {
try {
this.channel.shutdownNow();
} catch (Throwable throwable) {
//ignore.
} catch (Throwable ignored) {
}
}
}

View File

@ -100,8 +100,7 @@ public class GrpcConstants {
GRpcConfigLabel.class)) {
try {
CONFIG_NAMES.add((String) declaredField.get(null));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalAccessException ignored) {
}
}
}

View File

@ -62,9 +62,7 @@ public class GrpcUtils {
// request body .
byte[] jsonBytes = convertRequestToByte(request);
return payloadBuilder
.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.build();
return payloadBuilder.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes))).build();
}
@ -83,8 +81,7 @@ public class GrpcUtils {
Payload.Builder builder = Payload.newBuilder();
return builder
.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
return builder.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.setMetadata(newMeta).build();
}
@ -99,8 +96,7 @@ public class GrpcUtils {
byte[] jsonBytes = JacksonUtils.toJsonBytes(response);
Metadata.Builder metaBuilder = Metadata.newBuilder().setType(response.getClass().getSimpleName());
return Payload.newBuilder()
.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
return Payload.newBuilder().setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.setMetadata(metaBuilder.build()).build();
}
@ -132,50 +128,5 @@ public class GrpcUtils {
throw new RemoteException(NacosException.SERVER_ERROR,
"Unknown payload type:" + payload.getMetadata().getType());
}
}
public static class PlainRequest {
String type;
Object body;
/**
* Getter method for property <tt>type</tt>.
*
* @return property value of type
*/
public String getType() {
return type;
}
/**
* Setter method for property <tt>type</tt>.
*
* @param type value to be assigned to property type
*/
public void setType(String type) {
this.type = type;
}
/**
* Getter method for property <tt>body</tt>.
*
* @return property value of body
*/
public Object getBody() {
return body;
}
/**
* Setter method for property <tt>body</tt>.
*
* @param body value to be assigned to property body
*/
public void setBody(Object body) {
this.body = body;
}
}
}

View File

@ -27,7 +27,7 @@ public class ConnectionAlreadyClosedException extends RemoteException {
private static final int CONNECTION_ALREADY_CLOSED = 600;
public ConnectionAlreadyClosedException(String msg) {
super(CONNECTION_ALREADY_CLOSED);
super(CONNECTION_ALREADY_CLOSED, msg);
}
public ConnectionAlreadyClosedException() {

View File

@ -43,7 +43,7 @@ import static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public final class ClassUtils {
private ClassUtils() {
}
@ -241,7 +241,7 @@ public final class ClassUtils {
*/
public static Class<?> forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError {
AbstractAssert.notNull(name, "Name must not be null");
Objects.requireNonNull(name, "Name must not be null");
Class<?> clazz = resolvePrimitiveClassName(name);
if (clazz == null) {
@ -386,7 +386,7 @@ public final class ClassUtils {
* @return the corresponding resource path, pointing to the class
*/
public static String convertClassNameToResourcePath(String className) {
AbstractAssert.notNull(className, "Class name must not be null");
Objects.requireNonNull(className, "Class name must not be null");
return className.replace(PACKAGE_SEPARATOR, PATH_SEPARATOR);
}
@ -397,7 +397,7 @@ public final class ClassUtils {
* @return the corresponding resource path, pointing to the class
*/
public static String resourcePathToConvertClassName(String className) {
AbstractAssert.notNull(className, "Class name must not be null");
Objects.requireNonNull(className, "Class name must not be null");
return className.replace(PATH_SEPARATOR, PACKAGE_SEPARATOR);
}
}

View File

@ -1,14 +1,10 @@
/**
* 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.
* 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;
@ -22,7 +18,7 @@ import java.util.regex.Pattern;
*/
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName", "PMD.ClassNamingShouldBeCamelRule"})
public class InetAddressValidator {
private InetAddressValidator() {
}
@ -59,9 +55,8 @@ public class InetAddressValidator {
.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.
* 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.
@ -71,9 +66,8 @@ public class InetAddressValidator {
}
/**
* 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.
* 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.
@ -83,9 +77,8 @@ public class InetAddressValidator {
}
/**
* 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.
* 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.
@ -95,13 +88,8 @@ public class InetAddressValidator {
}
/**
* 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
* 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.
@ -112,11 +100,9 @@ public class InetAddressValidator {
}
/**
* 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'
* 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.
@ -143,9 +129,8 @@ public class InetAddressValidator {
}
/**
* 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'
* 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
@ -159,8 +144,8 @@ public class InetAddressValidator {
}
/**
* 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.
* 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.
@ -176,27 +161,4 @@ public class InetAddressValidator {
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;
}
}

View File

@ -24,7 +24,6 @@ import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -33,7 +32,6 @@ import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -46,7 +44,7 @@ import java.util.zip.GZIPOutputStream;
* @author nacos
*/
public class IoUtils {
private IoUtils() {
}
@ -75,11 +73,7 @@ public class IoUtils {
if (!isGzipStream(raw)) {
return raw;
}
try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(raw));
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copy(gis, out);
return out.toByteArray();
}
return tryDecompress(new ByteArrayInputStream(raw));
}
/**
@ -276,31 +270,6 @@ public class IoUtils {
}
}
/**
* Copy File.
*
* @param source source file path
* @param target target file path
* @throws IOException io exception
*/
public static void copyFile(String source, String target) throws IOException {
File sf = new File(source);
if (!sf.exists()) {
throw new IllegalArgumentException("source file does not exist.");
}
File tf = new File(target);
if (!tf.getParentFile().mkdirs()) {
throw new RuntimeException("failed to create parent directory.");
}
if (!tf.exists() && !tf.createNewFile()) {
throw new RuntimeException("failed to create target file.");
}
try (FileChannel sc = new FileInputStream(sf).getChannel();
FileChannel tc = new FileOutputStream(tf).getChannel()) {
sc.transferTo(0, sc.size(), tc);
}
}
/**
* Judge whether is Gzip stream.
*

View File

@ -16,9 +16,6 @@
package com.alibaba.nacos.common.utils;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
@ -26,7 +23,6 @@ import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
/**
@ -36,7 +32,7 @@ import java.util.StringTokenizer;
* @author zzq
*/
public class StringUtils {
private StringUtils() {
}
@ -226,108 +222,6 @@ public class StringUtils {
return stringBuilder.toString();
}
public static String escapeJavaScript(String str) {
return escapeJavaStyleString(str, true, true);
}
private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes, boolean escapeForwardSlash) {
if (str == null) {
return null;
}
try {
StringWriter writer = new StringWriter(str.length() * 2);
escapeJavaStyleString(writer, str, escapeSingleQuotes, escapeForwardSlash);
return writer.toString();
} catch (IOException ioe) {
// this should never ever happen while writing to a StringWriter
return null;
}
}
private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote,
boolean escapeForwardSlash) throws IOException {
if (out == null) {
throw new IllegalArgumentException("The Writer must not be null");
}
if (str == null) {
return;
}
int sz;
sz = str.length();
for (int i = 0; i < sz; i++) {
char ch = str.charAt(i);
// handle unicode
if (ch > 0xfff) {
out.write("\\u" + hex(ch));
} else if (ch > 0xff) {
out.write("\\u0" + hex(ch));
} else if (ch > 0x7f) {
out.write("\\u00" + hex(ch));
} else if (ch < 32) {
switch (ch) {
case '\b':
out.write('\\');
out.write('b');
break;
case '\n':
out.write('\\');
out.write('n');
break;
case '\t':
out.write('\\');
out.write('t');
break;
case '\f':
out.write('\\');
out.write('f');
break;
case '\r':
out.write('\\');
out.write('r');
break;
default:
if (ch > 0xf) {
out.write("\\u00" + hex(ch));
} else {
out.write("\\u000" + hex(ch));
}
break;
}
} else {
switch (ch) {
case '\'':
if (escapeSingleQuote) {
out.write('\\');
}
out.write('\'');
break;
case '"':
out.write('\\');
out.write('"');
break;
case '\\':
out.write('\\');
out.write('\\');
break;
case '/':
if (escapeForwardSlash) {
out.write('\\');
}
out.write('/');
break;
default:
out.write(ch);
break;
}
}
}
}
private static String hex(char ch) {
return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH);
}
/**
* Checks if CharSequence contains a search CharSequence irrespective of case, handling {@code null}.
* Case-insensitivity is defined as by {@link String#equalsIgnoreCase(String)}.
@ -503,10 +397,6 @@ public class StringUtils {
return str.split(separatorChars);
}
private static String[] tokenizeLocaleSource(String localeSource) {
return tokenizeToStringArray(localeSource, "_ ", false, false);
}
/**
* Tokenize the given {@code String} into a {@code String} array via a {@link StringTokenizer}.
*
@ -899,21 +789,17 @@ public class StringUtils {
* @return the capitalized {@code String}
*/
public static String capitalize(String str) {
return changeFirstCharacterCase(str, true);
return changeFirstCharacterCase(str);
}
private static String changeFirstCharacterCase(String str, boolean capitalize) {
private static String changeFirstCharacterCase(String str) {
if (!hasLength(str)) {
return str;
}
char baseChar = str.charAt(0);
char updatedChar;
if (capitalize) {
updatedChar = Character.toUpperCase(baseChar);
} else {
updatedChar = Character.toLowerCase(baseChar);
}
updatedChar = Character.toUpperCase(baseChar);
if (baseChar == updatedChar) {
return str;
}

View File

@ -29,25 +29,12 @@ import java.util.concurrent.TimeUnit;
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public final class ThreadUtils {
private ThreadUtils() {
}
private static final int THREAD_MULTIPLER = 2;
/**
* Wait.
*
* @param object load object
*/
public static void objectWait(Object object) {
try {
object.wait();
} catch (InterruptedException ignore) {
Thread.interrupted();
}
}
/**
* Sleep.
*

View File

@ -1,217 +0,0 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.utils;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* container for top n counter metrics, increment and remove cost O(1) time.
*
* @author <a href="mailto:liuyixiao0821@gmail.com">liuyixiao</a>
*/
public class TopnCounterMetricsContainer {
/**
* dataId -> count.
*/
private ConcurrentHashMap<String, AtomicInteger> dataCount;
/**
* count -> node.
*/
private ConcurrentHashMap<Integer, DoublyLinkedNode> specifiedCountDataIdSets;
private DoublyLinkedNode dummyHead;
public TopnCounterMetricsContainer() {
dataCount = new ConcurrentHashMap<>();
specifiedCountDataIdSets = new ConcurrentHashMap<>();
dummyHead = new DoublyLinkedNode(null, null, null, -1);
dummyHead.next = new DoublyLinkedNode(null, dummyHead, new ConcurrentHashSet<>(), 0);
specifiedCountDataIdSets.put(0, dummyHead.next);
}
public List<Pair<String, AtomicInteger>> getTopNCounter(int n) {
List<Pair<String, AtomicInteger>> topnCounter = new LinkedList<>();
DoublyLinkedNode curr = dummyHead;
while (curr.next != null && topnCounter.size() < n) {
for (String dataId : curr.next.dataSet) {
// use inner AtomicInteger to reflect change to prometheus
topnCounter.add(new Pair<>(dataId, dataCount.get(dataId)));
if (topnCounter.size() == n) {
break;
}
}
curr = curr.next;
}
return topnCounter;
}
/**
* put(String dataId, 0).
*
* @param dataId data name or data key.
*/
public void put(String dataId) {
put(dataId, 0);
}
/**
* put new data into container, if already exist, update it.
* this method could be slow (O(N)), most time use increment.
*
* @param dataId data name or data key.
* @param count data count.
*/
public void put(String dataId, int count) {
if (dataCount.containsKey(dataId)) {
removeFromSpecifiedCountDataIdSets(dataId);
dataCount.get(dataId).set(count);
} else {
dataCount.put(dataId, new AtomicInteger(count));
}
insertIntoSpecifiedCountDataIdSets(dataId, count);
}
/**
* get data count by dataId.
*
* @param dataId data name or data key.
* @return data count or -1 if not exist.
*/
public int get(String dataId) {
if (dataCount.containsKey(dataId)) {
return dataCount.get(dataId).get();
}
return -1;
}
/**
* increment the count of dataId.
*
* @param dataId data name or data key.
*/
public void increment(String dataId) {
if (!dataCount.containsKey(dataId)) {
put(dataId);
}
DoublyLinkedNode prev = removeFromSpecifiedCountDataIdSets(dataId);
int newCount = dataCount.get(dataId).incrementAndGet();
if (!isDummyHead(prev) && prev.count == newCount) {
insertIntoSpecifiedCountDataIdSets(dataId, prev);
} else {
// prev.count > newCount
DoublyLinkedNode newNode = new DoublyLinkedNode(prev.next, prev, new ConcurrentHashSet<>(), newCount);
if (prev.next != null) {
prev.next.prev = newNode;
}
prev.next = newNode;
newNode.dataSet.add(dataId);
specifiedCountDataIdSets.put(newCount, newNode);
}
}
/**
* remove data.
*
* @param dataId data name or data key.
* @return data count or null if data is not exist.
*/
public AtomicInteger remove(String dataId) {
if (dataCount.containsKey(dataId)) {
removeFromSpecifiedCountDataIdSets(dataId);
return dataCount.remove(dataId);
}
return null;
}
/**
* remove all data.
*/
public void removeAll() {
for (String dataId : dataCount.keySet()) {
removeFromSpecifiedCountDataIdSets(dataId);
}
dataCount.clear();
}
private DoublyLinkedNode removeFromSpecifiedCountDataIdSets(String dataId) {
int count = dataCount.get(dataId).get();
DoublyLinkedNode node = specifiedCountDataIdSets.get(count);
node.dataSet.remove(dataId);
// keep the 0 count node.
if (node.dataSet.size() == 0 && node.count != 0) {
node.prev.next = node.next;
if (node.next != null) {
node.next.prev = node.prev;
}
specifiedCountDataIdSets.remove(node.count);
}
return node.prev;
}
private void insertIntoSpecifiedCountDataIdSets(String dataId, int count) {
if (specifiedCountDataIdSets.containsKey(count)) {
specifiedCountDataIdSets.get(count).dataSet.add(dataId);
} else {
DoublyLinkedNode prev = dummyHead;
while (prev.next != null) {
if (prev.next.count < count) {
break;
} else {
prev = prev.next;
}
}
DoublyLinkedNode newNode = new DoublyLinkedNode(prev.next, prev, new ConcurrentHashSet<>(), count);
if (prev.next != null) {
prev.next.prev = newNode;
}
prev.next = newNode;
newNode.dataSet.add(dataId);
specifiedCountDataIdSets.put(count, newNode);
}
}
private void insertIntoSpecifiedCountDataIdSets(String dataId, DoublyLinkedNode targetSet) {
targetSet.dataSet.add(dataId);
}
private boolean isDummyHead(DoublyLinkedNode node) {
return node.count == -1;
}
private class DoublyLinkedNode {
public DoublyLinkedNode next;
public DoublyLinkedNode prev;
public ConcurrentHashSet<String> dataSet;
public int count;
public DoublyLinkedNode(DoublyLinkedNode next, DoublyLinkedNode prev, ConcurrentHashSet<String> dataSet, int count) {
this.next = next;
this.prev = prev;
this.dataSet = dataSet;
this.count = count;
}
}
}

View File

@ -0,0 +1,18 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class ClassUtilsTestMockClass {
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
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.slf4j.Logger;
import java.lang.reflect.Field;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@RunWith(MockitoJUnitRunner.class)
public class AbstractApacheHttpClientFactoryTest {
@Mock
private Logger logger;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testCreateNacosRestTemplate() throws NoSuchFieldException, IllegalAccessException {
HttpClientFactory factory = new AbstractApacheHttpClientFactory() {
@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().build();
}
@Override
protected Logger assignLogger() {
return logger;
}
};
NacosRestTemplate template = factory.createNacosRestTemplate();
assertNotNull(template);
Field field = NacosRestTemplate.class.getDeclaredField("requestClient");
field.setAccessible(true);
HttpClientRequest requestClient = (HttpClientRequest) field.get(template);
assertTrue(requestClient instanceof DefaultHttpClientRequest);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.tls.TlsSystemConfig;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import static org.junit.Assert.assertNotNull;
@RunWith(MockitoJUnitRunner.class)
public class AbstractHttpClientFactoryTest {
@Mock
private Logger logger;
@After
public void tearDown() throws Exception {
TlsSystemConfig.tlsEnable = false;
}
@Test
public void testCreateNacosRestTemplateWithSsl() throws Exception {
TlsSystemConfig.tlsEnable = true;
HttpClientFactory httpClientFactory = new DefaultHttpClientFactory(logger);
NacosRestTemplate nacosRestTemplate = httpClientFactory.createNacosRestTemplate();
assertNotNull(nacosRestTemplate);
}
@Test
public void testCreateNacosAsyncRestTemplate() {
HttpClientFactory httpClientFactory = new AbstractHttpClientFactory() {
@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().setMaxConnTotal(10).setMaxConnPerRoute(10).build();
}
@Override
protected Logger assignLogger() {
return logger;
}
};
NacosAsyncRestTemplate nacosRestTemplate = httpClientFactory.createNacosAsyncRestTemplate();
assertNotNull(nacosRestTemplate);
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import org.apache.http.client.methods.HttpRequestBase;
import org.junit.Assert;
import org.junit.Test;
public class BaseHttpMethodTest {
@Test
public void testHttpGet() {
BaseHttpMethod method = BaseHttpMethod.GET;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("GET", request.getMethod());
}
@Test
public void testHttpGetLarge() {
BaseHttpMethod method = BaseHttpMethod.GET_LARGE;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("GET", request.getMethod());
}
@Test
public void testHttpPost() {
BaseHttpMethod method = BaseHttpMethod.POST;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("POST", request.getMethod());
}
@Test
public void testHttpPut() {
BaseHttpMethod method = BaseHttpMethod.PUT;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("PUT", request.getMethod());
}
@Test
public void testHttpDelete() {
BaseHttpMethod method = BaseHttpMethod.DELETE;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("DELETE", request.getMethod());
}
@Test
public void testHttpDeleteLarge() {
BaseHttpMethod method = BaseHttpMethod.DELETE_LARGE;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("DELETE", request.getMethod());
}
@Test
public void testHttpHead() {
BaseHttpMethod method = BaseHttpMethod.HEAD;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("HEAD", request.getMethod());
}
@Test
public void testHttpTrace() {
BaseHttpMethod method = BaseHttpMethod.TRACE;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("TRACE", request.getMethod());
}
@Test
public void testHttpPatch() {
BaseHttpMethod method = BaseHttpMethod.PATCH;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("PATCH", request.getMethod());
}
@Test
public void testHttpOptions() {
BaseHttpMethod method = BaseHttpMethod.OPTIONS;
HttpRequestBase request = method.init("http://example.com");
Assert.assertEquals("TRACE", request.getMethod());
}
@Test
public void testSourceOf() {
BaseHttpMethod method = BaseHttpMethod.sourceOf("GET");
Assert.assertEquals(BaseHttpMethod.GET, method);
}
@Test(expected = IllegalArgumentException.class)
public void testSourceOfNotFound() {
BaseHttpMethod.sourceOf("Not Found");
}
}

View File

@ -0,0 +1,145 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
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.slf4j.Logger;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class HttpClientBeanHolderTest {
private Map<String, NacosRestTemplate> cachedRestTemplateMap;
private Map<String, NacosRestTemplate> restMap;
private Map<String, NacosAsyncRestTemplate> cachedAsyncRestTemplateMap;
private Map<String, NacosAsyncRestTemplate> restAsyncMap;
@Mock
private NacosRestTemplate mockRestTemplate;
@Mock
private NacosAsyncRestTemplate mockAsyncRestTemplate;
@Mock
private HttpClientFactory mockFactory;
@Before
public void setUp() throws Exception {
cachedRestTemplateMap = new HashMap<>();
cachedAsyncRestTemplateMap = new HashMap<>();
restMap = (Map<String, NacosRestTemplate>) getCachedMap("SINGLETON_REST");
restAsyncMap = (Map<String, NacosAsyncRestTemplate>) getCachedMap("SINGLETON_ASYNC_REST");
cachedRestTemplateMap.putAll(restMap);
cachedAsyncRestTemplateMap.putAll(restAsyncMap);
restMap.clear();
restAsyncMap.clear();
when(mockFactory.createNacosRestTemplate()).thenReturn(mockRestTemplate);
when(mockFactory.createNacosAsyncRestTemplate()).thenReturn(mockAsyncRestTemplate);
}
@After
public void tearDown() throws Exception {
restMap.putAll(cachedRestTemplateMap);
restAsyncMap.putAll(cachedAsyncRestTemplateMap);
cachedRestTemplateMap.clear();
cachedAsyncRestTemplateMap.clear();
}
private Object getCachedMap(String mapName) throws NoSuchFieldException, IllegalAccessException {
Field field = HttpClientBeanHolder.class.getDeclaredField(mapName);
field.setAccessible(true);
return field.get(HttpClientBeanHolder.class);
}
@Test
public void testGetNacosRestTemplateWithDefault() {
assertTrue(restMap.isEmpty());
NacosRestTemplate actual = HttpClientBeanHolder.getNacosRestTemplate((Logger) null);
assertEquals(1, restMap.size());
NacosRestTemplate duplicateGet = HttpClientBeanHolder.getNacosRestTemplate((Logger) null);
assertEquals(1, restMap.size());
assertEquals(actual, duplicateGet);
}
@Test(expected = NullPointerException.class)
public void testGetNacosRestTemplateForNullFactory() {
HttpClientBeanHolder.getNacosRestTemplate((HttpClientFactory) null);
}
@Test
public void testGetNacosRestTemplateWithCustomFactory() {
assertTrue(restMap.isEmpty());
HttpClientBeanHolder.getNacosRestTemplate((Logger) null);
assertEquals(1, restMap.size());
NacosRestTemplate actual = HttpClientBeanHolder.getNacosRestTemplate(mockFactory);
assertEquals(2, restMap.size());
assertEquals(mockRestTemplate, actual);
}
@Test
public void testGetNacosAsyncRestTemplateWithDefault() {
assertTrue(restAsyncMap.isEmpty());
NacosAsyncRestTemplate actual = HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);
assertEquals(1, restAsyncMap.size());
NacosAsyncRestTemplate duplicateGet = HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);
assertEquals(1, restAsyncMap.size());
assertEquals(actual, duplicateGet);
}
@Test(expected = NullPointerException.class)
public void testGetNacosAsyncRestTemplateForNullFactory() {
HttpClientBeanHolder.getNacosAsyncRestTemplate((HttpClientFactory) null);
}
@Test
public void testGetNacosAsyncRestTemplateWithCustomFactory() {
assertTrue(restAsyncMap.isEmpty());
HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);
assertEquals(1, restAsyncMap.size());
NacosAsyncRestTemplate actual = HttpClientBeanHolder.getNacosAsyncRestTemplate(mockFactory);
assertEquals(2, restAsyncMap.size());
assertEquals(mockAsyncRestTemplate, actual);
}
@Test
public void shutdown() throws Exception {
HttpClientBeanHolder.getNacosRestTemplate((Logger) null);
HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);
assertEquals(1, restMap.size());
assertEquals(1, restAsyncMap.size());
HttpClientBeanHolder.shutdown(DefaultHttpClientFactory.class.getName());
assertEquals(0, restMap.size());
assertEquals(0, restAsyncMap.size());
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class HttpClientConfigTest {
@Test
public void testGetConTimeOutMillis() {
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
assertEquals(1000, config.getConTimeOutMillis());
}
@Test
public void testGetReadTimeOutMillis() {
HttpClientConfig config = HttpClientConfig.builder().setReadTimeOutMillis(2000).build();
assertEquals(2000, config.getReadTimeOutMillis());
}
@Test
public void testGetConnTimeToLive() {
HttpClientConfig config = HttpClientConfig.builder().setConnectionTimeToLive(3000, TimeUnit.MILLISECONDS)
.build();
assertEquals(3000, config.getConnTimeToLive());
}
@Test
public void testGetConnTimeToLiveTimeUnit() {
HttpClientConfig config = HttpClientConfig.builder().setConnectionTimeToLive(4000, TimeUnit.SECONDS).build();
assertEquals(TimeUnit.SECONDS, config.getConnTimeToLiveTimeUnit());
}
@Test
public void testGetConnectionRequestTimeout() {
HttpClientConfig config = HttpClientConfig.builder().setConnectionRequestTimeout(5000).build();
assertEquals(5000, config.getConnectionRequestTimeout());
}
@Test
public void testGetMaxRedirects() {
HttpClientConfig config = HttpClientConfig.builder().setMaxRedirects(60).build();
assertEquals(60, config.getMaxRedirects());
}
@Test
public void testGetMaxConnTotal() {
HttpClientConfig config = HttpClientConfig.builder().setMaxConnTotal(70).build();
assertEquals(70, config.getMaxConnTotal());
}
@Test
public void testGetMaxConnPerRoute() {
HttpClientConfig config = HttpClientConfig.builder().setMaxConnPerRoute(80).build();
assertEquals(80, config.getMaxConnPerRoute());
}
@Test
public void testGetContentCompressionEnabled() {
HttpClientConfig config = HttpClientConfig.builder().setContentCompressionEnabled(false).build();
assertFalse(config.getContentCompressionEnabled());
}
@Test
public void testGetIoThreadCount() {
HttpClientConfig config = HttpClientConfig.builder().setIoThreadCount(90).build();
assertEquals(90, config.getIoThreadCount());
}
@Test
public void testGetUserAgent() {
HttpClientConfig config = HttpClientConfig.builder().setUserAgent("testUserAgent").build();
assertEquals("testUserAgent", config.getUserAgent());
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.param.Header;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HttpRestResultTest {
@Test
public void testSetHeader() {
HttpRestResult<String> result = new HttpRestResult<>();
result.setData("test data");
Header header = Header.newInstance();
result.setHeader(header);
assertEquals(header, result.getHeader());
assertEquals("test data", result.getData());
}
@Test
public void testFullConstructor() {
Header header = Header.newInstance();
HttpRestResult<String> result = new HttpRestResult<>(header, 200, "test data", "message");
assertEquals(header, result.getHeader());
assertEquals("test data", result.getData());
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.client.handler.BeanResponseHandler;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.handler.RestResultResponseHandler;
import com.alibaba.nacos.common.http.client.handler.StringResponseHandler;
import com.alibaba.nacos.common.model.RestResult;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import java.lang.reflect.Type;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(MockitoJUnitRunner.class)
public class AbstractNacosRestTemplateTest {
@Mock
private ResponseHandler mockResponseHandler;
MockNacosRestTemplate restTemplate;
@Before
public void setUp() throws Exception {
restTemplate = new MockNacosRestTemplate(null);
restTemplate.registerResponseHandler(MockNacosRestTemplate.class.getName(), mockResponseHandler);
}
@Test
public void testSelectResponseHandlerForNull() {
assertTrue(restTemplate.testFindResponseHandler(null) instanceof StringResponseHandler);
}
@Test
public void testSelectResponseHandlerForRestResult() {
assertTrue(restTemplate.testFindResponseHandler(RestResult.class) instanceof RestResultResponseHandler);
}
@Test
public void testSelectResponseHandlerForDefault() {
assertTrue(restTemplate
.testFindResponseHandler(AbstractNacosRestTemplateTest.class) instanceof BeanResponseHandler);
}
@Test
public void testSelectResponseHandlerForCustom() {
assertEquals(mockResponseHandler, restTemplate.testFindResponseHandler(MockNacosRestTemplate.class));
}
private static class MockNacosRestTemplate extends AbstractNacosRestTemplate {
public MockNacosRestTemplate(Logger logger) {
super(logger);
}
private ResponseHandler testFindResponseHandler(Type responseType) {
return super.selectResponseHandler(responseType);
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
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 java.net.URI;
import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class InterceptingHttpClientRequestTest {
@Mock
private HttpClientRequest httpClientRequest;
@Mock
private HttpClientRequestInterceptor interceptor;
@Mock
private HttpClientResponse interceptorResponse;
@Mock
private HttpClientResponse httpClientResponse;
InterceptingHttpClientRequest clientRequest;
@Before
public void setUp() throws Exception {
List<HttpClientRequestInterceptor> interceptorList = new LinkedList<>();
interceptorList.add(interceptor);
clientRequest = new InterceptingHttpClientRequest(httpClientRequest, interceptorList.listIterator());
when(interceptor.intercept()).thenReturn(interceptorResponse);
when(httpClientRequest.execute(any(), any(), any())).thenReturn(httpClientResponse);
}
@After
public void tearDown() throws Exception {
clientRequest.close();
}
@Test
public void testExecuteIntercepted() throws Exception {
when(interceptor.isIntercept(any(), any(), any())).thenReturn(true);
HttpClientResponse response = clientRequest
.execute(URI.create("http://example.com"), "GET", new RequestHttpEntity(Header.EMPTY, Query.EMPTY));
assertEquals(interceptorResponse, response);
}
@Test
public void testExecuteNotIntercepted() throws Exception {
HttpClientResponse response = clientRequest
.execute(URI.create("http://example.com"), "GET", new RequestHttpEntity(Header.EMPTY, Query.EMPTY));
assertEquals(httpClientResponse, response);
}
}

View File

@ -0,0 +1,176 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.client.request.AsyncHttpClientRequest;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
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.slf4j.Logger;
import java.util.HashMap;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NacosAsyncRestTemplateTest {
private static final String TEST_URL = "http://127.0.0.1:8848/nacos/test";
@Mock
private AsyncHttpClientRequest requestClient;
@Mock
private Logger logger;
@Mock
private Callback<String> mockCallback;
private NacosAsyncRestTemplate restTemplate;
@Before
public void setUp() throws Exception {
restTemplate = new NacosAsyncRestTemplate(logger, requestClient);
when(logger.isDebugEnabled()).thenReturn(true);
}
@After
public void tearDown() throws Exception {
restTemplate.close();
}
@Test
public void testGet() throws Exception {
restTemplate.get(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);
verify(requestClient).execute(any(), eq("GET"), any(), any(), eq(mockCallback));
}
@Test
public void testGetWithException() throws Exception {
doThrow(new RuntimeException("test")).when(requestClient).execute(any(), any(), any(), any(), any());
restTemplate.get(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);
verify(requestClient).execute(any(), eq("GET"), any(), any(), eq(mockCallback));
verify(mockCallback).onError(any(RuntimeException.class));
}
@Test
public void testGetLarge() throws Exception {
restTemplate.getLarge(TEST_URL, Header.EMPTY, Query.EMPTY, new Object(), String.class, mockCallback);
verify(requestClient).execute(any(), eq("GET-LARGE"), any(), any(), eq(mockCallback));
}
@Test
public void testDeleteWithBody() throws Exception {
restTemplate.delete(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);
verify(requestClient).execute(any(), eq("DELETE"), any(), any(), eq(mockCallback));
}
@Test
public void testDeleteLarge() throws Exception {
restTemplate.delete(TEST_URL, Header.EMPTY, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("DELETE_LARGE"), any(), any(), eq(mockCallback));
}
@Test
public void testPut() throws Exception {
restTemplate.put(TEST_URL, Header.EMPTY, Query.EMPTY, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("PUT"), any(), any(), eq(mockCallback));
}
@Test
public void testPutJson() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.putJson(TEST_URL, header, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("PUT"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutJsonWithQuery() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.putJson(TEST_URL, header, Query.EMPTY, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("PUT"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutForm() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.putForm(TEST_URL, header, new HashMap<>(), String.class, mockCallback);
verify(requestClient).execute(any(), eq("PUT"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutFormWithQuery() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.putForm(TEST_URL, header, Query.EMPTY, new HashMap<>(), String.class, mockCallback);
verify(requestClient).execute(any(), eq("PUT"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPost() throws Exception {
restTemplate.post(TEST_URL, Header.EMPTY, Query.EMPTY, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("POST"), any(), any(), eq(mockCallback));
}
@Test
public void testPostJson() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.postJson(TEST_URL, header, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("POST"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostJsonWithQuery() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.postJson(TEST_URL, header, Query.EMPTY, "body", String.class, mockCallback);
verify(requestClient).execute(any(), eq("POST"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostForm() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.postForm(TEST_URL, header, new HashMap<>(), String.class, mockCallback);
verify(requestClient).execute(any(), eq("POST"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostFormWithQuery() throws Exception {
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
restTemplate.postForm(TEST_URL, header, Query.EMPTY, new HashMap<>(), String.class, mockCallback);
verify(requestClient).execute(any(), eq("POST"), any(), any(), eq(mockCallback));
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
}

View File

@ -0,0 +1,358 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
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.slf4j.Logger;
import java.io.ByteArrayInputStream;
import java.util.Collections;
import java.util.HashMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NacosRestTemplateTest {
@Mock
private HttpClientRequest requestClient;
@Mock
private Logger logger;
@Mock
private HttpClientResponse mockResponse;
@Mock
private HttpClientRequestInterceptor interceptor;
private NacosRestTemplate restTemplate;
@Before
public void setUp() throws Exception {
restTemplate = new NacosRestTemplate(logger, requestClient);
when(logger.isDebugEnabled()).thenReturn(true);
when(mockResponse.getHeaders()).thenReturn(Header.EMPTY);
when(interceptor.isIntercept(any(), any(), any())).thenReturn(true);
when(interceptor.intercept()).thenReturn(mockResponse);
}
@After
public void tearDown() throws Exception {
restTemplate.close();
}
@Test
public void testGetWithDefaultConfig() throws Exception {
when(requestClient.execute(any(), eq("GET"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpRestResult<String> result = restTemplate
.get("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testGetWithCustomConfig() throws Exception {
when(requestClient.execute(any(), eq("GET"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
HttpRestResult<String> result = restTemplate
.get("http://127.0.0.1:8848/nacos/test", config, Header.EMPTY, Query.EMPTY, String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testGetWithInterceptor() throws Exception {
when(mockResponse.getStatusCode()).thenReturn(300);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test interceptor".getBytes()));
restTemplate.setInterceptors(Collections.singletonList(interceptor));
HttpRestResult<String> result = restTemplate
.get("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, String.class);
assertFalse(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test interceptor", result.getMessage());
}
@Test(expected = RuntimeException.class)
public void testGetWithException() throws Exception {
when(requestClient.execute(any(), eq("GET"), any())).thenThrow(new RuntimeException("test"));
restTemplate.get("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, String.class);
}
@Test
public void testGetLarge() throws Exception {
when(requestClient.execute(any(), eq("GET-LARGE"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpRestResult<String> result = restTemplate
.getLarge("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, new Object(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testDeleteWithDefaultConfig() throws Exception {
when(requestClient.execute(any(), eq("DELETE"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpRestResult<String> result = restTemplate
.delete("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testDeleteWithCustomConfig() throws Exception {
when(requestClient.execute(any(), eq("DELETE"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
HttpRestResult<String> result = restTemplate
.delete("http://127.0.0.1:8848/nacos/test", config, Header.EMPTY, Query.EMPTY, String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testPut() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpRestResult<String> result = restTemplate
.put("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, new Object(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testPutJson() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.putJson("http://127.0.0.1:8848/nacos/test", header, "body", String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutJsonWithQuery() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.putJson("http://127.0.0.1:8848/nacos/test", header, Query.EMPTY, "body", String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutForm() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.putForm("http://127.0.0.1:8848/nacos/test", header, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutFormWithQuery() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.putForm("http://127.0.0.1:8848/nacos/test", header, Query.EMPTY, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPutFormWithConfig() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.putForm("http://127.0.0.1:8848/nacos/test", config, header, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPost() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpRestResult<String> result = restTemplate
.post("http://127.0.0.1:8848/nacos/test", Header.EMPTY, Query.EMPTY, new Object(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testPostJson() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.postJson("http://127.0.0.1:8848/nacos/test", header, "body", String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostJsonWithQuery() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.postJson("http://127.0.0.1:8848/nacos/test", header, Query.EMPTY, "body", String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostForm() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.postForm("http://127.0.0.1:8848/nacos/test", header, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostFormWithQuery() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.postForm("http://127.0.0.1:8848/nacos/test", header, Query.EMPTY, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testPostFormWithConfig() throws Exception {
when(requestClient.execute(any(), eq("POST"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.postForm("http://127.0.0.1:8848/nacos/test", config, header, new HashMap<>(), String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testExchangeForm() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);
HttpRestResult<String> result = restTemplate
.exchangeForm("http://127.0.0.1:8848/nacos/test", header, Query.EMPTY, new HashMap<>(), "PUT",
String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testExchange() throws Exception {
when(requestClient.execute(any(), eq("PUT"), any())).thenReturn(mockResponse);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream("test".getBytes()));
HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();
HttpRestResult<String> result = restTemplate
.exchange("http://127.0.0.1:8848/nacos/test", config, Header.EMPTY, Query.EMPTY, new Object(), "PUT",
String.class);
assertTrue(result.ok());
assertEquals(Header.EMPTY, result.getHeader());
assertEquals("test", result.getData());
}
@Test
public void testGetInterceptors() {
assertTrue(restTemplate.getInterceptors().isEmpty());
restTemplate.setInterceptors(Collections.singletonList(interceptor));
assertEquals(1, restTemplate.getInterceptors().size());
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.handler;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class BeanResponseHandlerTest {
@Test
public void testConvertResult() throws Exception {
List<Integer> testCase = new LinkedList<>();
for (int i = 0; i < 10; i++) {
testCase.add(i);
}
byte[] bytes = JacksonUtils.toJsonBytes(testCase);
InputStream inputStream = new ByteArrayInputStream(bytes);
HttpClientResponse response = mock(HttpClientResponse.class);
when(response.getBody()).thenReturn(inputStream);
when(response.getHeaders()).thenReturn(Header.EMPTY);
when(response.getStatusCode()).thenReturn(200);
BeanResponseHandler<List<Integer>> beanResponseHandler = new BeanResponseHandler<>();
beanResponseHandler.setResponseType(List.class);
HttpRestResult<List<Integer>> actual = beanResponseHandler.handle(response);
assertEquals(200, actual.getCode());
assertEquals(testCase, actual.getData());
assertNull(actual.getMessage());
assertEquals(Header.EMPTY, actual.getHeader());
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.handler;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class RestResultResponseHandlerTest {
@Test
public void testConvertResult() throws Exception {
RestResult<String> testCase = RestResult.<String>builder().withCode(200).withData("ok").withMsg("msg").build();
InputStream inputStream = new ByteArrayInputStream(JacksonUtils.toJsonBytes(testCase));
HttpClientResponse response = mock(HttpClientResponse.class);
when(response.getBody()).thenReturn(inputStream);
when(response.getHeaders()).thenReturn(Header.EMPTY);
when(response.getStatusCode()).thenReturn(200);
RestResultResponseHandler<String> handler = new RestResultResponseHandler<>();
handler.setResponseType(RestResult.class);
HttpRestResult<String> actual = handler.handle(response);
assertEquals(testCase.getCode(), actual.getCode());
assertEquals(testCase.getData(), actual.getData());
assertEquals(testCase.getMessage(), actual.getMessage());
assertEquals(Header.EMPTY, actual.getHeader());
}
}

View File

@ -0,0 +1,161 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.ExceptionEvent;
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 java.net.URI;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class DefaultAsyncHttpClientRequestTest {
@Mock
private CloseableHttpAsyncClient client;
@Mock
private DefaultConnectingIOReactor ioReactor;
@Mock
private Callback callback;
@Mock
private ResponseHandler responseHandler;
private RequestConfig defaultConfig;
DefaultAsyncHttpClientRequest httpClientRequest;
private URI uri;
@Before
public void setUp() throws Exception {
defaultConfig = RequestConfig.DEFAULT;
httpClientRequest = new DefaultAsyncHttpClientRequest(client, ioReactor, defaultConfig);
uri = URI.create("http://127.0.0.1:8080");
}
@After
public void tearDown() throws Exception {
httpClientRequest.close();
}
@Test
public void testExecuteOnFail() throws Exception {
Header header = Header.newInstance();
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
RuntimeException exception = new RuntimeException("test");
when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {
((FutureCallback) invocationOnMock.getArgument(1)).failed(exception);
return null;
});
httpClientRequest.execute(uri, "PUT", httpEntity, responseHandler, callback);
verify(callback).onError(exception);
}
@Test
public void testExecuteOnCancel() throws Exception {
Header header = Header.newInstance();
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {
((FutureCallback) invocationOnMock.getArgument(1)).cancelled();
return null;
});
httpClientRequest.execute(uri, "PUT", httpEntity, responseHandler, callback);
verify(callback).onCancel();
}
@Test
public void testExecuteOnComplete() throws Exception {
Header header = Header.newInstance();
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
HttpResponse response = mock(HttpResponse.class);
HttpRestResult restResult = new HttpRestResult();
when(responseHandler.handle(any())).thenReturn(restResult);
when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {
((FutureCallback) invocationOnMock.getArgument(1)).completed(response);
return null;
});
httpClientRequest.execute(uri, "PUT", httpEntity, responseHandler, callback);
verify(callback).onReceive(restResult);
}
@Test
public void testExecuteOnCompleteWithException() throws Exception {
Header header = Header.newInstance();
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
HttpResponse response = mock(HttpResponse.class);
RuntimeException exception = new RuntimeException("test");
when(responseHandler.handle(any())).thenThrow(exception);
when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {
((FutureCallback) invocationOnMock.getArgument(1)).completed(response);
return null;
});
httpClientRequest.execute(uri, "PUT", httpEntity, responseHandler, callback);
verify(callback).onError(exception);
}
@Test
public void testExecuteException() throws Exception {
Header header = Header.newInstance();
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
IllegalStateException exception = new IllegalStateException("test");
when(client.execute(any(), any())).thenThrow(exception);
when(ioReactor.getAuditLog()).thenReturn(Collections.singletonList(new ExceptionEvent(exception, new Date())));
try {
httpClientRequest.execute(uri, "PUT", httpEntity, responseHandler, callback);
} catch (Exception e) {
assertEquals(exception, e);
}
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
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 java.lang.reflect.Field;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class DefaultHttpClientRequestTest {
@Mock
private CloseableHttpClient client;
@Mock
private CloseableHttpResponse response;
private RequestConfig defaultConfig;
DefaultHttpClientRequest httpClientRequest;
private boolean isForm;
private boolean withConfig;
private URI uri;
@Before
public void setUp() throws Exception {
defaultConfig = RequestConfig.DEFAULT;
httpClientRequest = new DefaultHttpClientRequest(client, defaultConfig);
when(client.execute(argThat(httpUriRequest -> {
HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) httpUriRequest;
boolean result = isForm == (entityRequest.getEntity() instanceof UrlEncodedFormEntity);
HttpRequestBase baseHttpRequest = (HttpRequestBase) httpUriRequest;
if (withConfig) {
result &= null != baseHttpRequest.getConfig();
}
return result;
}))).thenReturn(response);
uri = URI.create("http://127.0.0.1:8080");
}
@After
public void tearDown() throws Exception {
isForm = false;
withConfig = false;
httpClientRequest.close();
}
@Test
public void testExecuteForFormWithoutConfig() throws Exception {
isForm = true;
Header header = Header.newInstance()
.addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);
HttpClientResponse actual = httpClientRequest.execute(uri, "PUT", httpEntity);
assertEquals(response, getActualResponse(actual));
}
@Test
public void testExecuteForFormWithConfig() throws Exception {
isForm = true;
withConfig = true;
Header header = Header.newInstance()
.addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
Map<String, String> body = new HashMap<>();
body.put("test", "test");
RequestHttpEntity httpEntity = new RequestHttpEntity(HttpClientConfig.builder().build(), header, Query.EMPTY,
body);
HttpClientResponse actual = httpClientRequest.execute(uri, "PUT", httpEntity);
assertEquals(response, getActualResponse(actual));
}
@Test
public void testExecuteForOther() throws Exception {
Header header = Header.newInstance();
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, "body");
HttpClientResponse actual = httpClientRequest.execute(uri, "PUT", httpEntity);
assertEquals(response, getActualResponse(actual));
}
private CloseableHttpResponse getActualResponse(HttpClientResponse actual)
throws IllegalAccessException, NoSuchFieldException {
Field field = actual.getClass().getDeclaredField("response");
field.setAccessible(true);
return (CloseableHttpResponse) field.get(actual);
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
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 java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JdkHttpClientRequestTest {
@Mock
private HttpURLConnection connection;
@Mock
private URI uri;
@Mock
private URL url;
@Mock
private OutputStream outputStream;
JdkHttpClientRequest httpClientRequest;
private HttpClientConfig httpClientConfig;
@Before
public void setUp() throws Exception {
when(uri.toURL()).thenReturn(url);
when(url.openConnection()).thenReturn(connection);
when(connection.getOutputStream()).thenReturn(outputStream);
httpClientConfig = HttpClientConfig.builder().build();
httpClientRequest = new JdkHttpClientRequest(httpClientConfig);
}
@After
public void tearDown() throws Exception {
httpClientRequest.close();
}
@Test
public void testExecuteNormal() throws Exception {
Header header = Header.newInstance();
HttpClientConfig config = HttpClientConfig.builder().build();
RequestHttpEntity httpEntity = new RequestHttpEntity(config, header, Query.EMPTY, "a=bo&dy");
HttpClientResponse response = httpClientRequest.execute(uri, "GET", httpEntity);
byte[] writeBytes = "a=bo&dy".getBytes(StandardCharsets.UTF_8);
verify(outputStream).write(writeBytes, 0, writeBytes.length);
assertEquals(connection, getActualConnection(response));
}
@Test
public void testExecuteForm() throws Exception {
Header header = Header.newInstance();
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpClientConfig config = HttpClientConfig.builder().build();
Map<String, String> body = new HashMap<>();
body.put("a", "bo&dy");
RequestHttpEntity httpEntity = new RequestHttpEntity(config, header, Query.EMPTY, body);
HttpClientResponse response = httpClientRequest.execute(uri, "GET", httpEntity);
byte[] writeBytes = HttpUtils.encodingParams(body, StandardCharsets.UTF_8.name())
.getBytes(StandardCharsets.UTF_8);
verify(outputStream).write(writeBytes, 0, writeBytes.length);
assertEquals(connection, getActualConnection(response));
}
@Test
public void testExecuteEmptyBody() throws Exception {
Header header = Header.newInstance();
RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY);
HttpClientResponse response = httpClientRequest.execute(uri, "GET", httpEntity);
verify(outputStream, never()).write(any(), eq(0), anyInt());
assertEquals(connection, getActualConnection(response));
}
private HttpURLConnection getActualConnection(HttpClientResponse actual)
throws IllegalAccessException, NoSuchFieldException {
Field field = actual.getClass().getDeclaredField("conn");
field.setAccessible(true);
return (HttpURLConnection) field.get(actual);
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.response;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
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 java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class DefaultClientHttpResponseTest {
@Mock
private HttpResponse response;
@Mock
private StatusLine statusLine;
@Mock
private HttpEntity httpEntity;
@Mock
private InputStream inputStream;
@Mock
private Header header;
DefaultClientHttpResponse clientHttpResponse;
@Before
public void setUp() throws Exception {
when(httpEntity.getContent()).thenReturn(inputStream);
when(response.getEntity()).thenReturn(httpEntity);
when(response.getStatusLine()).thenReturn(statusLine);
when(response.getAllHeaders()).thenReturn(new Header[] {header});
when(header.getName()).thenReturn("testName");
when(header.getValue()).thenReturn("testValue");
clientHttpResponse = new DefaultClientHttpResponse(response);
}
@After
public void tearDown() throws Exception {
clientHttpResponse.close();
}
@Test
public void testGetStatusCode() {
when(statusLine.getStatusCode()).thenReturn(200);
assertEquals(200, clientHttpResponse.getStatusCode());
}
@Test
public void testGetStatusText() {
when(statusLine.getReasonPhrase()).thenReturn("test");
assertEquals("test", clientHttpResponse.getStatusText());
}
@Test
public void testGetHeaders() {
assertEquals(3, clientHttpResponse.getHeaders().getHeader().size());
assertEquals("testValue", clientHttpResponse.getHeaders().getValue("testName"));
}
@Test
public void testGetBody() throws IOException {
assertEquals(inputStream, clientHttpResponse.getBody());
}
@Test
public void testCloseResponseWithException() {
when(response.getEntity()).thenThrow(new RuntimeException("test"));
clientHttpResponse.close();
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client.response;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.utils.IoUtils;
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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JdkClientHttpResponseTest {
@Mock
private HttpURLConnection connection;
@Mock
private InputStream inputStream;
private Map<String, List<String>> headers;
JdkHttpClientResponse clientHttpResponse;
@Before
public void setUp() throws Exception {
headers = new HashMap<>();
headers.put("testName", Collections.singletonList("testValue"));
when(connection.getHeaderFields()).thenReturn(headers);
clientHttpResponse = new JdkHttpClientResponse(connection);
}
@After
public void tearDown() throws Exception {
clientHttpResponse.close();
}
@Test
public void testGetStatusCode() throws IOException {
when(connection.getResponseCode()).thenReturn(200);
assertEquals(200, clientHttpResponse.getStatusCode());
}
@Test
public void testGetStatusText() throws IOException {
when(connection.getResponseMessage()).thenReturn("test");
assertEquals("test", clientHttpResponse.getStatusText());
}
@Test
public void testGetHeaders() {
assertEquals(3, clientHttpResponse.getHeaders().getHeader().size());
assertEquals("testValue", clientHttpResponse.getHeaders().getValue("testName"));
}
@Test
public void testGetBody() throws IOException {
when(connection.getInputStream()).thenReturn(inputStream);
assertEquals(inputStream, clientHttpResponse.getBody());
}
@Test
public void testGetBodyWithGzip() throws IOException {
byte[] testCase = IoUtils.tryCompress("test", StandardCharsets.UTF_8.name());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(testCase);
when(connection.getInputStream()).thenReturn(byteArrayInputStream);
headers.put(HttpHeaderConsts.CONTENT_ENCODING, Collections.singletonList("gzip"));
assertEquals("test", IoUtils.toString(clientHttpResponse.getBody(), StandardCharsets.UTF_8.name()));
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.handler;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.TypeUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ResponseHandlerTest {
private final ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
@Test
public void testDeserializationType() throws Exception {
String json = JacksonUtils.toJson(list);
ArrayList<Integer> tmp = ResponseHandler.convert(json, TypeUtils.parameterize(List.class, Integer.class));
Assert.assertEquals(list, tmp);
}
@Test
public void testRestResult() throws Exception {
String json = "{\"code\":200,\"message\":null,\"data\":[{\"USERNAME\":\"nacos\",\"PASSWORD\":"
+ "\"$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu\",\"ENABLED\":true}]}";
RestResult<Object> result = ResponseHandler.convert(json, TypeUtils.parameterize(RestResult.class, Object.class));
Assert.assertEquals(200, result.getCode());
Assert.assertNull(result.getMessage());
Assert.assertNotNull(result.getData());
}
@Test
public void testDeserializationClass() throws Exception {
String json = JacksonUtils.toJson(list);
ArrayList<Integer> tmp = ResponseHandler.convert(json, TypeUtils.parameterize(List.class, Integer.class));
Assert.assertEquals(list, tmp);
}
}

View File

@ -16,16 +16,122 @@
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class HeaderTest {
@Test
public void testSetContentType() {
Header header = Header.newInstance();
header.setContentType(null);
assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
header.setContentType(MediaType.MULTIPART_FORM_DATA);
assertEquals(MediaType.MULTIPART_FORM_DATA, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testHeaderKyeIgnoreCase() {
Header header = Header.newInstance();
header.addParam("Content-Encoding", "gzip");
assertEquals("gzip", header.getValue("content-encoding"));
}
@Test
public void testToList() {
Header header = Header.newInstance();
List<String> list = header.toList();
assertTrue(list.contains(HttpHeaderConsts.CONTENT_TYPE));
assertTrue(list.contains(MediaType.APPLICATION_JSON));
assertEquals(1, list.indexOf(MediaType.APPLICATION_JSON) - list.indexOf(HttpHeaderConsts.CONTENT_TYPE));
assertTrue(list.contains(HttpHeaderConsts.ACCEPT_CHARSET));
assertTrue(list.contains("UTF-8"));
assertEquals(1, list.indexOf("UTF-8") - list.indexOf(HttpHeaderConsts.ACCEPT_CHARSET));
}
@Test
public void testAddAllForMap() {
Map<String, String> map = new HashMap<>();
map.put("test1", "test2");
map.put("test3", "test4");
Header header = Header.newInstance();
header.addAll(map);
assertEquals("test2", header.getValue("test1"));
assertEquals("test4", header.getValue("test3"));
assertEquals(4, header.getHeader().size());
}
@Test
public void testAddAllForList() {
List<String> list = new ArrayList<>(4);
list.add("test1");
list.add("test2");
list.add("test3");
list.add("test4");
Header header = Header.newInstance();
header.addAll(list);
assertEquals("test2", header.getValue("test1"));
assertEquals("test4", header.getValue("test3"));
assertEquals(4, header.getHeader().size());
}
@Test(expected = IllegalArgumentException.class)
public void testAddAllForListWithWrongLength() {
List<String> list = new ArrayList<>(3);
list.add("test1");
list.add("test2");
list.add("test3");
Header header = Header.newInstance();
header.addAll(list);
}
@Test
public void testAddOriginalResponseHeader() {
List<String> list = new ArrayList<>(4);
list.add("test1");
list.add("test2");
list.add("test3");
list.add("test4");
Header header = Header.newInstance();
header.addOriginalResponseHeader("test", list);
assertEquals("test1", header.getValue("test"));
assertEquals(1, header.getOriginalResponseHeader().size());
assertEquals(list, header.getOriginalResponseHeader().get("test"));
}
@Test
public void testGetCharset() {
Header header = Header.newInstance();
assertEquals("UTF-8", header.getCharset());
header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, null);
header.setContentType(MediaType.APPLICATION_JSON);
assertEquals("UTF-8", header.getCharset());
header.setContentType("application/json;charset=GBK");
assertEquals("GBK", header.getCharset());
header.setContentType("application/json");
assertEquals("UTF-8", header.getCharset());
header.setContentType("");
assertEquals("UTF-8", header.getCharset());
}
@Test
public void testClear() {
Header header = Header.newInstance();
header.addOriginalResponseHeader("test", Collections.singletonList("test"));
assertEquals(3, header.getHeader().size());
assertEquals(1, header.getOriginalResponseHeader().size());
header.clear();
assertEquals(0, header.getHeader().size());
assertEquals(0, header.getOriginalResponseHeader().size());
assertEquals("Header{headerToMap={}}", header.toString());
}
}

View File

@ -59,4 +59,13 @@ public class MediaTypeTest {
assertEquals(excepted, mediaType.toString());
}
@Test(expected = IllegalArgumentException.class)
public void testValueOfWithEmpty() {
MediaType.valueOf("");
}
@Test(expected = IllegalArgumentException.class)
public void testValueOfWithEmpty2() {
MediaType.valueOf("", "UTF-8");
}
}

View File

@ -17,7 +17,6 @@
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.naming.CommonParams;
import org.junit.Assert;
import org.junit.Test;
import java.net.URLEncoder;
@ -26,11 +25,13 @@ import java.util.LinkedHashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class QueryTest {
@Test
public void testToQueryUrl() {
public void testInitParams() {
Map<String, String> parameters = new LinkedHashMap<String, String>();
parameters.put(CommonParams.NAMESPACE_ID, "namespace");
parameters.put(CommonParams.SERVICE_NAME, "service");
@ -41,16 +42,27 @@ public class QueryTest {
parameters.put("weight", String.valueOf(1.0));
parameters.put("ephemeral", String.valueOf(true));
String excepted = "namespaceId=namespace&serviceName=service&groupName=group&ip=1.1.1.1&port=9999&weight=1.0&ephemeral=true";
assertEquals(excepted, Query.newInstance().initParams(parameters).toQueryUrl());
Query actual = Query.newInstance().initParams(parameters);
assertEquals(excepted, actual.toQueryUrl());
assertEquals("namespace", actual.getValue(CommonParams.NAMESPACE_ID));
}
@Test
public void testToQueryUrl2() throws Exception {
Query query = Query.newInstance().addParam("key-1", "value-1")
.addParam("key-2", "value-2");
public void testAddParams() throws Exception {
Query query = Query.newInstance().addParam("key-1", "value-1").addParam("key-2", "value-2");
String s1 = query.toQueryUrl();
String s2 = "key-1=" + URLEncoder.encode("value-1", StandardCharsets.UTF_8.name())
+ "&key-2=" + URLEncoder.encode("value-2", StandardCharsets.UTF_8.name());
Assert.assertEquals(s1, s2);
String s2 = "key-1=" + URLEncoder.encode("value-1", StandardCharsets.UTF_8.name()) + "&key-2=" + URLEncoder
.encode("value-2", StandardCharsets.UTF_8.name());
assertEquals(s2, s1);
assertEquals("value-1", query.getValue("key-1"));
}
@Test
public void testClear() {
Query query = Query.newInstance().addParam("key-1", "value-1").addParam("key-2", "value-2");
assertFalse(query.isEmpty());
assertEquals("value-1", query.getValue("key-1"));
query.clear();
assertTrue(query.isEmpty());
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.remote;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class ConnectionTypeTest {
@Test
public void testGetByType() {
ConnectionType connectionType = ConnectionType.getByType("GRPC");
assertNotNull(connectionType);
assertEquals("GRPC", connectionType.getType());
assertEquals("Grpc Connection", connectionType.getName());
}
@Test
public void testGetByNonExistType() {
ConnectionType connectionType = ConnectionType.getByType("HTTP");
assertNull(connectionType);
}
}

View File

@ -16,24 +16,28 @@
package com.alibaba.nacos.common.remote;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.ErrorResponse;
import org.junit.BeforeClass;
import org.junit.Test;
public class PayloadRegistryTest extends TestCase {
import static org.junit.Assert.assertNull;
public class PayloadRegistryTest {
public void setUp() throws Exception {
super.setUp();
}
public void tearDown() throws Exception {
@BeforeClass
public static void setUpBefore() {
PayloadRegistry.init();
}
@Test
public void testInit() {
PayloadRegistry.init();
Assert.assertNotNull(PayloadRegistry.getClassByType("NotifySubscriberResponse"));
Assert.assertNotNull(PayloadRegistry.getClassByType("InstanceRequest"));
public void testRegisterInvalidClass() {
PayloadRegistry.register("test", Request.class);
assertNull(PayloadRegistry.getClassByType("test"));
}
@Test(expected = RuntimeException.class)
public void testRegisterDuplicated() {
PayloadRegistry.register("ErrorResponse", ErrorResponse.class);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.remote;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class TlsConfigTest {
@Test
public void testTlsConfig() {
TlsConfig tlsConfig = new TlsConfig();
assertFalse(tlsConfig.getEnableTls());
assertFalse(tlsConfig.getMutualAuthEnable());
assertNull(tlsConfig.getProtocols());
assertNull(tlsConfig.getCiphers());
assertFalse(tlsConfig.getTrustAll());
assertNull(tlsConfig.getTrustCollectionCertFile());
assertNull(tlsConfig.getCertPrivateKeyPassword());
assertNull(tlsConfig.getCertPrivateKey());
assertNull(tlsConfig.getCertChainFile());
assertEquals("", tlsConfig.getSslProvider());
// Set values
tlsConfig.setEnableTls(true);
tlsConfig.setMutualAuthEnable(true);
tlsConfig.setProtocols("TLSv1.1,TLSv1.2,TLSv1.3");
tlsConfig.setCiphers("cipher1,cipher2");
tlsConfig.setTrustAll(true);
tlsConfig.setTrustCollectionCertFile("certFile");
tlsConfig.setCertPrivateKeyPassword("password");
tlsConfig.setCertPrivateKey("privateKey");
tlsConfig.setCertChainFile("chainFile");
tlsConfig.setSslProvider("OPENSSL");
// Test values
assertTrue(tlsConfig.getEnableTls());
assertTrue(tlsConfig.getMutualAuthEnable());
assertEquals("TLSv1.1,TLSv1.2,TLSv1.3", tlsConfig.getProtocols());
assertEquals("cipher1,cipher2", tlsConfig.getCiphers());
assertTrue(tlsConfig.getTrustAll());
assertEquals("certFile", tlsConfig.getTrustCollectionCertFile());
assertEquals("password", tlsConfig.getCertPrivateKeyPassword());
assertEquals("privateKey", tlsConfig.getCertPrivateKey());
assertEquals("chainFile", tlsConfig.getCertChainFile());
assertEquals("OPENSSL", tlsConfig.getSslProvider());
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.remote.client;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.RequestCallBack;
import com.alibaba.nacos.api.remote.RequestFuture;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.Response;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class ConnectionTest {
Connection connection;
@Before
public void setUp() throws Exception {
connection = new Connection(new RpcClient.ServerInfo("127.0.0.1", 8848)) {
@Override
public Response request(Request request, long timeoutMills) throws NacosException {
return null;
}
@Override
public RequestFuture requestFuture(Request request) throws NacosException {
return null;
}
@Override
public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException {
}
@Override
public void close() {
}
};
}
@After
public void tearDown() throws Exception {
connection.close();
}
@Test
public void testSetConnectionId() {
assertNull(connection.getConnectionId());
connection.setConnectionId("testConnectionId");
assertEquals("testConnectionId", connection.getConnectionId());
}
@Test
public void testGetConnectionAbility() {
assertFalse(connection.isAbilitiesSet());
assertEquals(AbilityStatus.UNKNOWN, connection.getConnectionAbility(AbilityKey.SDK_CLIENT_TEST_1));
connection.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_TEST_2.getName(), true));
assertTrue(connection.isAbilitiesSet());
assertEquals(AbilityStatus.UNKNOWN, connection.getConnectionAbility(AbilityKey.SDK_CLIENT_TEST_1));
assertEquals(AbilityStatus.SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_TEST_2));
connection.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_TEST_2.getName(), false));
assertEquals(AbilityStatus.NOT_SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_TEST_2));
}
@Test
public void testSetAbandon() {
assertFalse(connection.isAbandon());
connection.setAbandon(true);
assertTrue(connection.isAbandon());
}
}

View File

@ -16,10 +16,19 @@
package com.alibaba.nacos.common.remote.client;
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.RequestCallBack;
import com.alibaba.nacos.api.remote.request.ClientDetectionRequest;
import com.alibaba.nacos.api.remote.request.ConnectResetRequest;
import com.alibaba.nacos.api.remote.request.HealthCheckRequest;
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.ClientDetectionResponse;
import com.alibaba.nacos.api.remote.response.ConnectResetResponse;
import com.alibaba.nacos.api.remote.response.ErrorResponse;
import com.alibaba.nacos.api.remote.response.HealthCheckResponse;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.remote.ConnectionType;
import com.alibaba.nacos.common.remote.client.grpc.DefaultGrpcClientConfig;
import com.alibaba.nacos.common.remote.client.grpc.GrpcConnection;
@ -38,17 +47,28 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -159,7 +179,7 @@ public class RpcClientTest {
}
@After
public void tearDown() throws IllegalAccessException {
public void tearDown() throws IllegalAccessException, NacosException {
rpcClientConfig.labels().clear();
rpcClient.rpcClientStatus.set(RpcClientStatus.WAIT_INIT);
serverListFactoryField.set(rpcClient, null);
@ -167,6 +187,7 @@ public class RpcClientTest {
rpcClient.currentConnection = null;
System.clearProperty("nacos.server.port");
rpcClient.eventLinkedBlockingQueue.clear();
rpcClient.shutdown();
}
@Test
@ -263,6 +284,7 @@ public class RpcClientTest {
map.put("labelKey2", "labelValue2");
when(rpcClientConfig.labels()).thenReturn(map);
assertEquals(1, rpcClient.getLabels().size());
assertEquals("test", rpcClient.getName());
}
@Test
@ -319,14 +341,17 @@ public class RpcClientTest {
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "10.10.10.10::8848")).getAddress());
assertEquals("10.10.10.10:8848",
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "10.10.10.10:8848")).getAddress());
assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
"http://10.10.10.10:8848")).getAddress());
assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
"http://10.10.10.10::8848")).getAddress());
assertEquals("10.10.10.10:8848",
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10:8848"))
.getAddress());
assertEquals("10.10.10.10:8848",
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10::8848"))
.getAddress());
assertEquals("10.10.10.10:8848",
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10")).getAddress());
assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
"https://10.10.10.10::8848")).getAddress());
assertEquals("10.10.10.10:8848",
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "https://10.10.10.10::8848"))
.getAddress());
}
@Test
@ -336,11 +361,30 @@ public class RpcClientTest {
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10")).getAddress());
}
@Test
public void testRequestSuccess() throws NacosException, NoSuchFieldException, IllegalAccessException {
rpcClient.currentConnection = connection;
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
when(connection.request(any(), anyLong())).thenReturn(new HealthCheckResponse());
Field lastActiveTimeStampField = RpcClient.class.getDeclaredField("lastActiveTimeStamp");
lastActiveTimeStampField.setAccessible(true);
final long lastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);
Response response = rpcClient.request(new HealthCheckRequest());
assertTrue(response instanceof HealthCheckResponse);
assertTrue(lastActiveTimeStamp <= (long) lastActiveTimeStampField.get(rpcClient));
}
@Test(expected = NacosException.class)
public void testRequestWithoutAnyTry() throws NacosException {
when(rpcClientConfig.retryTimes()).thenReturn(-1);
rpcClient.request(null);
}
@Test(expected = NacosException.class)
public void testRequestWhenClientAlreadyShutDownThenThrowException() throws NacosException {
rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);
rpcClient.currentConnection = connection;
rpcClient.request(null, 10000);
rpcClient.request(null);
}
@Test(expected = NacosException.class)
@ -348,7 +392,6 @@ public class RpcClientTest {
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
rpcClient.currentConnection = connection;
doReturn(null).when(connection).request(any(), anyLong());
rpcClient.request(null, 10000);
}
@ -357,7 +400,6 @@ public class RpcClientTest {
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
rpcClient.currentConnection = connection;
doReturn(new ErrorResponse()).when(connection).request(any(), anyLong());
rpcClient.request(null, 10000);
}
@ -381,6 +423,22 @@ public class RpcClientTest {
Assert.assertNotNull(exception);
}
@Test
public void testAsyncRequestSuccess() throws NacosException {
rpcClient.currentConnection = connection;
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
RequestCallBack<?> requestCallBack = mock(RequestCallBack.class);
when(requestCallBack.getTimeout()).thenReturn(1000L);
rpcClient.asyncRequest(null, requestCallBack);
verify(connection).asyncRequest(any(), any());
}
@Test(expected = NacosException.class)
public void testAsyncRequestWithoutAnyTry() throws NacosException {
when(rpcClientConfig.retryTimes()).thenReturn(-1);
rpcClient.asyncRequest(null, null);
}
@Test(expected = NacosException.class)
public void testAsyncRequestWhenClientAlreadyShutDownThenThrowException() throws NacosException {
rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);
@ -411,6 +469,12 @@ public class RpcClientTest {
assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
}
@Test(expected = NacosException.class)
public void testRequestFutureWithoutAnyTry() throws NacosException {
when(rpcClientConfig.retryTimes()).thenReturn(-1);
rpcClient.requestFuture(null);
}
@Test(expected = NacosException.class)
public void testRequestFutureWhenClientAlreadyShutDownThenThrowException() throws NacosException {
rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);
@ -419,8 +483,7 @@ public class RpcClientTest {
}
@Test
public void testRequestFutureWhenRetryReachMaxRetryTimesThenSwitchServer()
throws NacosException, IllegalAccessException {
public void testRequestFutureWhenRetryReachMaxRetryTimesThenSwitchServer() throws NacosException {
when(rpcClientConfig.timeOutMills()).thenReturn(5000L);
when(rpcClientConfig.retryTimes()).thenReturn(3);
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
@ -489,12 +552,13 @@ public class RpcClientTest {
}
@Override
public Connection connectToServer(ServerInfo serverInfo) throws Exception {
public Connection connectToServer(ServerInfo serverInfo) {
return null;
}
};
rpcClient.shutdown();
assertTrue(rpcClient.isShutdown());
}
@Test
@ -622,7 +686,7 @@ public class RpcClientTest {
}
@Override
public Connection connectToServer(ServerInfo serverInfo) throws Exception {
public Connection connectToServer(ServerInfo serverInfo) {
return null;
}
@ -647,4 +711,435 @@ public class RpcClientTest {
});
rpcClient.handleServerRequest(request);
}
@Test
public void testNotifyDisConnectedForEmpty() {
rpcClient.notifyDisConnected(null);
verify(rpcClientConfig, never()).name();
}
@Test
public void testNotifyDisConnected() {
ConnectionEventListener listener = mock(ConnectionEventListener.class);
rpcClient.registerConnectionListener(listener);
rpcClient.notifyDisConnected(null);
verify(listener).onDisConnect(null);
verify(rpcClientConfig, times(2)).name();
}
@Test
public void testNotifyDisConnectedException() {
ConnectionEventListener listener = mock(ConnectionEventListener.class);
rpcClient.registerConnectionListener(listener);
doThrow(new RuntimeException("test")).when(listener).onDisConnect(null);
rpcClient.notifyDisConnected(null);
verify(rpcClientConfig, times(3)).name();
}
@Test
public void testNotifyConnectedForEmpty() {
rpcClient.notifyConnected(null);
verify(rpcClientConfig, never()).name();
}
@Test
public void testNotifyConnected() {
ConnectionEventListener listener = mock(ConnectionEventListener.class);
rpcClient.registerConnectionListener(listener);
rpcClient.notifyConnected(null);
verify(listener).onConnected(null);
verify(rpcClientConfig, times(2)).name();
}
@Test
public void testNotifyConnectedException() {
ConnectionEventListener listener = mock(ConnectionEventListener.class);
rpcClient.registerConnectionListener(listener);
doThrow(new RuntimeException("test")).when(listener).onConnected(null);
rpcClient.notifyConnected(null);
verify(rpcClientConfig, times(3)).name();
}
@Test
public void testStartClient() throws NacosException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(new Function<RpcClient.ServerInfo, Connection>() {
private int count;
@Override
public Connection apply(RpcClient.ServerInfo serverInfo) {
if (count == 0) {
count++;
throw new RuntimeException("test");
}
return connection;
}
});
try {
rpcClient.start();
assertTrue(rpcClient.isRunning());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testStartClientWithFailed() throws NacosException, InterruptedException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
try {
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(1000);
assertFalse(rpcClient.isRunning());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testStartClientAfterShutdown() throws NacosException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
rpcClient.shutdown();
rpcClient.start();
assertTrue(rpcClient.isShutdown());
}
@Test
public void testDisConnectionEventAfterStart() throws NacosException, InterruptedException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);
ConnectionEventListener listener = mock(ConnectionEventListener.class);
rpcClient.registerConnectionListener(listener);
try {
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(100);
rpcClient.eventLinkedBlockingQueue.put(new RpcClient.ConnectionEvent(0, connection));
TimeUnit.MILLISECONDS.sleep(100);
verify(listener).onDisConnect(connection);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithNullConnection() throws NacosException, InterruptedException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
try {
when(rpcClientConfig.connectionKeepAlive()).thenReturn(-1L);
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(100);
verify(rpcClientConfig, never()).healthCheckRetryTimes();
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithConnectionHealthCheckFail()
throws NacosException, InterruptedException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(new Function<RpcClient.ServerInfo, Connection>() {
private int count;
@Override
public Connection apply(RpcClient.ServerInfo serverInfo) {
if (count == 0) {
count++;
return connection;
}
return null;
}
});
try {
when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(500);
assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithConnectionHealthCheckSuccess()
throws NacosException, InterruptedException, NoSuchFieldException, IllegalAccessException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);
when(connection.request(any(Request.class), anyLong())).thenReturn(new HealthCheckResponse());
try {
Field lastActiveTimeStampField = RpcClient.class.getDeclaredField("lastActiveTimeStamp");
lastActiveTimeStampField.setAccessible(true);
final long lastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);
when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(100);
assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());
long newLastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);
assertTrue(newLastActiveTimeStamp > lastActiveTimeStamp);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithActiveTimeIsNew()
throws NacosException, InterruptedException, NoSuchFieldException, IllegalAccessException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);
try {
Field lastActiveTimeStampField = RpcClient.class.getDeclaredField("lastActiveTimeStamp");
lastActiveTimeStampField.setAccessible(true);
long setTime = System.currentTimeMillis() + 10000;
lastActiveTimeStampField.set(rpcClient, setTime);
when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);
rpcClient.start();
TimeUnit.MILLISECONDS.sleep(100);
assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());
long newLastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);
assertEquals(setTime, newLastActiveTimeStamp);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithOldServiceInfo()
throws NacosException, InterruptedException, IllegalAccessException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
when(serverListFactory.getServerList()).thenReturn(Collections.singletonList("127.0.0.1:8848"));
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);
try {
rpcClient.start();
RpcClient.ReconnectContext reconnectContext = new RpcClient.ReconnectContext(
new RpcClient.ServerInfo("127.0.0.1", 0), false);
((BlockingQueue<RpcClient.ReconnectContext>) reconnectionSignalField.get(rpcClient)).put(reconnectContext);
TimeUnit.MILLISECONDS.sleep(100);
assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());
assertEquals(8848, reconnectContext.serverInfo.serverPort);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectContextAfterStartWithNewServiceInfo()
throws NacosException, InterruptedException, IllegalAccessException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
when(serverListFactory.getServerList()).thenReturn(Collections.singletonList("1.1.1.1:8848"));
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);
try {
rpcClient.start();
RpcClient.ReconnectContext reconnectContext = new RpcClient.ReconnectContext(
new RpcClient.ServerInfo("127.0.0.1", 0), false);
((BlockingQueue<RpcClient.ReconnectContext>) reconnectionSignalField.get(rpcClient)).put(reconnectContext);
TimeUnit.MILLISECONDS.sleep(100);
assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());
assertNull(reconnectContext.serverInfo);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testHandleConnectionResetRequestWithoutServer() throws NacosException, InterruptedException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848", "1.1.1.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> {
connection.serverInfo = serverInfo;
return connection;
});
try {
rpcClient.start();
Response response = rpcClient.handleServerRequest(new ConnectResetRequest());
assertTrue(response instanceof ConnectResetResponse);
TimeUnit.MILLISECONDS.sleep(500);
assertEquals("1.1.1.1", connection.serverInfo.getServerIp());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testHandleConnectionResetRequestWithServer() throws NacosException, InterruptedException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848", "1.1.1.1:8848");
List<String> serverList = new LinkedList<>();
serverList.add("127.0.0.1:8848");
serverList.add("1.1.1.1:8848");
serverList.add("2.2.2.2:8848");
when(serverListFactory.getServerList()).thenReturn(serverList);
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> {
connection.serverInfo = serverInfo;
return connection;
});
try {
rpcClient.start();
ConnectResetRequest connectResetRequest = new ConnectResetRequest();
connectResetRequest.setServerIp("2.2.2.2");
connectResetRequest.setServerPort("8848");
Response response = rpcClient.handleServerRequest(connectResetRequest);
assertTrue(response instanceof ConnectResetResponse);
TimeUnit.MILLISECONDS.sleep(500);
assertEquals("2.2.2.2", connection.serverInfo.getServerIp());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testHandleConnectionResetRequestWithException() throws NacosException, InterruptedException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848", "1.1.1.1:8848");
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
RpcClient rpcClient = buildTestStartClient(serverInfo -> {
connection.serverInfo = serverInfo;
return connection;
});
try {
rpcClient.start();
System.setProperty("nacos.server.port", "2.2.2.2");
ConnectResetRequest connectResetRequest = new ConnectResetRequest();
connectResetRequest.setServerIp("2.2.2.2");
Response response = rpcClient.handleServerRequest(connectResetRequest);
assertTrue(response instanceof ConnectResetResponse);
TimeUnit.MILLISECONDS.sleep(500);
assertEquals("127.0.0.1", connection.serverInfo.getServerIp());
} finally {
rpcClient.shutdown();
}
}
@Test
public void testHandleClientDetectionRequest() throws NacosException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
try {
rpcClient.start();
Response response = rpcClient.handleServerRequest(new ClientDetectionRequest());
assertTrue(response instanceof ClientDetectionResponse);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testHandleOtherRequest() throws NacosException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
try {
rpcClient.start();
Response response = rpcClient.handleServerRequest(new HealthCheckRequest());
assertNull(response);
} finally {
rpcClient.shutdown();
}
}
@Test
public void testReconnectForRequestFailButHealthCheckOK() throws NacosException {
RpcClient rpcClient = buildTestStartClient(serverInfo -> null);
rpcClient.currentConnection = connection;
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
when(connection.request(any(Request.class), anyLong())).thenReturn(new HealthCheckResponse());
rpcClient.reconnect(null, true);
assertTrue(rpcClient.isRunning());
}
@Test
public void testReconnectFailTimes() throws NacosException {
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:8848");
when(serverListFactory.getServerList()).thenReturn(Collections.singletonList("127.0.0.1:8848"));
final AtomicInteger count = new AtomicInteger(0);
RpcClient rpcClient = buildTestStartClient(serverInfo -> {
int actual = count.incrementAndGet();
return actual > 3 ? connection : null;
});
rpcClient.currentConnection = connection;
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
long start = System.currentTimeMillis();
rpcClient.reconnect(null, false);
assertTrue(rpcClient.isRunning());
assertTrue(System.currentTimeMillis() - start > 400);
}
@Test
public void testGetCurrentServer() {
assertNull(rpcClient.getCurrentServer());
rpcClient.currentConnection = connection;
rpcClient.serverListFactory(serverListFactory);
connection.serverInfo = new RpcClient.ServerInfo("127.0.0.1", 8848);
assertNotNull(rpcClient.getCurrentServer());
}
@Test
public void testCurrentRpcServer() throws IllegalAccessException {
when(serverListFactory.getCurrentServer()).thenReturn("127.0.0.1:8848");
serverListFactoryField.set(rpcClient, serverListFactory);
RpcClient.ServerInfo serverInfo = rpcClient.currentRpcServer();
assertEquals("127.0.0.1", serverInfo.getServerIp());
assertEquals(8848, serverInfo.getServerPort());
assertEquals("127.0.0.1:8848", serverInfo.getAddress());
}
private RpcClient buildTestStartClient(Function<RpcClient.ServerInfo, Connection> function) {
return new RpcClient(rpcClientConfig, serverListFactory) {
@Override
public ConnectionType getConnectionType() {
return ConnectionType.GRPC;
}
@Override
public int rpcPortOffset() {
return 0;
}
@Override
public Connection connectToServer(ServerInfo serverInfo) {
return function.apply(serverInfo);
}
};
}
@Test
public void testServerInfoSet() {
RpcClient.ServerInfo serverInfo = new RpcClient.ServerInfo();
String ip = "127.0.0.1";
int port = 80;
serverInfo.setServerIp(ip);
serverInfo.setServerPort(port);
assertEquals("127.0.0.1:80", serverInfo.getAddress());
assertEquals(port, serverInfo.getServerPort());
assertEquals(ip, serverInfo.getServerIp());
String expected = "{serverIp = '127.0.0.1', server main port = 80}";
assertEquals(expected, serverInfo.toString());
}
@Test
public void testSetTenant() {
String tenant = "testTenant";
assertNull(rpcClient.getTenant());
rpcClient.setTenant(tenant);
assertEquals(tenant, rpcClient.getTenant());
}
@Test
public void testGetConnectionAbilityWithNullConnection() {
AbilityStatus abilityStatus = rpcClient.getConnectionAbility(AbilityKey.SERVER_TEST_1);
assertNull(abilityStatus);
}
@Test
public void testGetConnectionAbilityWithReadyConnection() {
when(connection.getConnectionAbility(AbilityKey.SERVER_TEST_1)).thenReturn(AbilityStatus.SUPPORTED);
rpcClient.currentConnection = connection;
AbilityStatus abilityStatus = rpcClient.getConnectionAbility(AbilityKey.SERVER_TEST_1);
assertNotNull(abilityStatus);
assertEquals(AbilityStatus.SUPPORTED, abilityStatus);
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.remote.client;
import org.junit.Test;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class RpcClientTlsConfigTest {
@Test
public void testEnableTls() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_ENABLE, "true");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertTrue(tlsConfig.getEnableTls());
}
@Test
public void testSslProvider() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_PROVIDER, "provider");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("provider", tlsConfig.getSslProvider());
}
@Test
public void testMutualAuthEnable() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_MUTUAL_AUTH, "true");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertTrue(tlsConfig.getMutualAuthEnable());
}
@Test
public void testProtocols() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_PROTOCOLS, "protocols");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("protocols", tlsConfig.getProtocols());
}
@Test
public void testCiphers() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CIPHERS, "ciphers");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("ciphers", tlsConfig.getCiphers());
}
@Test
public void testTrustCollectionCertFile() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH, "trustCollectionCertFile");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("trustCollectionCertFile", tlsConfig.getTrustCollectionCertFile());
}
@Test
public void testCertChainFile() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CERT_CHAIN_PATH, "certChainFile");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("certChainFile", tlsConfig.getCertChainFile());
}
@Test
public void testCertPrivateKey() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CERT_KEY, "certPrivateKey");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("certPrivateKey", tlsConfig.getCertPrivateKey());
}
@Test
public void testTrustAll() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_ALL, "true");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertTrue(tlsConfig.getTrustAll());
}
@Test
public void testCertPrivateKeyPassword() {
Properties properties = new Properties();
properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_PWD, "trustPwd");
RpcClientTlsConfig tlsConfig = RpcClientTlsConfig.properties(properties);
assertEquals("trustPwd", tlsConfig.getCertPrivateKeyPassword());
}
}

Some files were not shown because too many files have changed in this diff Show More