Merge branch 'apache-3.1' into 3.1.5-release

This commit is contained in:
Albumen Kevin 2023-01-17 11:17:56 +08:00
commit 92f7ac6656
23 changed files with 822 additions and 158 deletions

View File

@ -14,10 +14,10 @@ env:
SHOW_ERROR_DETAIL: 1
#multi-version size limit
VERSIONS_LIMIT: 4
ALL_REMOTE_VERSION: true
CANDIDATE_VERSIONS: '
spring.version:4.3.30.RELEASE;
spring-boot.version:1.5.22.RELEASE;
spring-boot.version:2.4.1;
spring.version:5.3.24;
spring-boot.version:2.7.6;
'
jobs:
@ -216,7 +216,7 @@ jobs:
integration-test-prepare:
runs-on: ubuntu-latest
env:
JOB_COUNT: 3
JOB_COUNT: 5
steps:
- uses: actions/checkout@v3
with:
@ -237,12 +237,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
strategy:
fail-fast: false
matrix:
job_id: [1, 2, 3]
jdk: [ 8, 11, 17, 19 ]
job_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v3
with:
@ -269,10 +270,10 @@ jobs:
with:
name: test-list
path: test/jobs/
- name: "Set up JDK 8"
- name: "Set up JDK ${{matrix.jdk}}"
uses: actions/setup-java@v1
with:
java-version: 8
java-version: ${{matrix.jdk}}
- name: "Init Candidate Versions"
run: |
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
@ -287,7 +288,7 @@ jobs:
if: always()
uses: actions/upload-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/*-result*
integration-test-result:
@ -295,7 +296,10 @@ jobs:
if: always()
runs-on: ubuntu-latest
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
strategy:
matrix:
jdk: [ 8, 11, 17, 19 ]
steps:
- uses: actions/checkout@v3
with:
@ -304,12 +308,11 @@ jobs:
- name: "Download test result"
uses: actions/download-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/
- name: "Merge test result"
run: ./test/scripts/merge-test-results.sh
error-code-inspecting:
runs-on: ubuntu-latest
steps:

View File

@ -14,10 +14,10 @@ env:
SHOW_ERROR_DETAIL: 1
#multi-version size limit
VERSIONS_LIMIT: 4
ALL_REMOTE_VERSION: true
CANDIDATE_VERSIONS: '
spring.version:4.3.30.RELEASE;
spring-boot.version:1.5.22.RELEASE;
spring-boot.version:2.4.1;
spring.version:5.3.24;
spring-boot.version:2.7.6;
'
jobs:
@ -216,7 +216,7 @@ jobs:
integration-test-prepare:
runs-on: ubuntu-latest
env:
JOB_COUNT: 3
JOB_COUNT: 5
steps:
- uses: actions/checkout@v3
with:
@ -237,12 +237,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
strategy:
fail-fast: false
matrix:
job_id: [1, 2, 3]
jdk: [ 8, 11, 17, 19 ]
job_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v3
with:
@ -269,10 +270,10 @@ jobs:
with:
name: test-list
path: test/jobs/
- name: "Set up JDK 8"
- name: "Set up JDK ${{matrix.jdk}}"
uses: actions/setup-java@v1
with:
java-version: 8
java-version: ${{matrix.jdk}}
- name: "Init Candidate Versions"
run: |
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
@ -287,7 +288,7 @@ jobs:
if: always()
uses: actions/upload-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/*-result*
integration-test-result:
@ -295,7 +296,10 @@ jobs:
if: always()
runs-on: ubuntu-latest
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
strategy:
matrix:
jdk: [ 8, 11, 17, 19 ]
steps:
- uses: actions/checkout@v3
with:
@ -304,7 +308,7 @@ jobs:
- name: "Download test result"
uses: actions/download-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/
- name: "Merge test result"
run: ./test/scripts/merge-test-results.sh

View File

@ -15,10 +15,10 @@ env:
SHOW_ERROR_DETAIL: 1
#multi-version size limit
VERSIONS_LIMIT: 4
ALL_REMOTE_VERSION: true
CANDIDATE_VERSIONS: '
spring.version:4.3.30.RELEASE;
spring-boot.version:1.5.22.RELEASE;
spring-boot.version:2.4.1;
spring.version:5.3.24;
spring-boot.version:2.7.6;
'
jobs:
@ -212,7 +212,7 @@ jobs:
integration-test-prepare:
runs-on: ubuntu-latest
env:
JOB_COUNT: 3
JOB_COUNT: 5
steps:
- uses: actions/checkout@v3
with:
@ -222,7 +222,7 @@ jobs:
run: |
bash ./test/scripts/prepare-test.sh
- name: "Upload test list"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: test-list
path: test/jobs
@ -233,12 +233,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
strategy:
fail-fast: false
matrix:
job_id: [1, 2, 3]
jdk: [ 8, 11 ]
job_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v3
with:
@ -261,15 +262,14 @@ jobs:
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
${{ runner.os }}-dubbo-snapshot-
- name: "Download test list"
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: test-list
path: test/jobs/
- name: "Set up JDK 8"
uses: actions/setup-java@v3
- name: "Set up JDK ${{matrix.jdk}}"
uses: actions/setup-java@v1
with:
java-version: 8
distribution: 'zulu'
java-version: ${{matrix.jdk}}
- name: "Init Candidate Versions"
run: |
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
@ -282,9 +282,9 @@ jobs:
run: cd test && bash ./run-tests.sh
- name: "Upload test result"
if: always()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/*-result*
integration-test-result:
@ -292,21 +292,23 @@ jobs:
if: always()
runs-on: ubuntu-latest
env:
JAVA_VER: 8
JAVA_VER: ${{matrix.jdk}}
strategy:
matrix:
jdk: [ 8, 11 ]
steps:
- uses: actions/checkout@v3
with:
repository: 'apache/dubbo-samples'
ref: master
- name: "Download test result"
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: test-result
name: test-result-${{matrix.jdk}}
path: test/jobs/
- name: "Merge test result"
run: ./test/scripts/merge-test-results.sh
error-code-inspecting:
runs-on: ubuntu-latest
steps:

View File

@ -113,6 +113,7 @@ public class ClassUtils {
PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, int.class);
PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, long.class);
PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, short.class);
PRIMITIVE_WRAPPER_TYPE_MAP.put(Void.class, void.class);
Set<Class<?>> primitiveTypeNames = new HashSet<>(32);
primitiveTypeNames.addAll(PRIMITIVE_WRAPPER_TYPE_MAP.values());
@ -163,7 +164,7 @@ public class ClassUtils {
if (cl == null) {
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable ex) {
} catch (Exception ignored) {
// Cannot access thread context ClassLoader - falling back to system class loader...
}
if (cl == null) {
@ -173,7 +174,7 @@ public class ClassUtils {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader();
} catch (Throwable ex) {
} catch (Exception ignored) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
@ -475,7 +476,7 @@ public class ClassUtils {
public static boolean isPresent(String className, ClassLoader classLoader) {
try {
forName(className, classLoader);
} catch (Throwable ignored) { // Ignored
} catch (Exception ignored) { // Ignored
return false;
}
return true;
@ -493,7 +494,7 @@ public class ClassUtils {
Class<?> targetClass = null;
try {
targetClass = forName(className, classLoader);
} catch (Throwable ignored) { // Ignored
} catch (Exception ignored) { // Ignored
}
return targetClass;
}

View File

@ -17,12 +17,20 @@
package org.apache.dubbo.configcenter.support.nacos;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigItem;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.MD5Utils;
@ -34,17 +42,12 @@ import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractSharedListener;
import com.alibaba.nacos.api.exception.NacosException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_ERROR_NACOS;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INTERRUPTED;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
import static org.apache.dubbo.common.utils.StringUtils.HYPHEN_CHAR;
@ -64,6 +67,12 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
private Properties nacosProperties;
private static final String NACOS_RETRY_KEY = "nacos.retry";
private static final String NACOS_RETRY_WAIT_KEY = "nacos.retry-wait";
private static final String NACOS_CHECK_KEY = "nacos.check";
/**
* The nacos configService
*/
@ -83,16 +92,49 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
}
private NacosConfigServiceWrapper buildConfigService(URL url) {
ConfigService configService = null;
int retryTimes = url.getPositiveParameter(NACOS_RETRY_KEY, 10);
int sleepMsBetweenRetries = url.getPositiveParameter(NACOS_RETRY_WAIT_KEY, 1000);
boolean check = url.getParameter(NACOS_CHECK_KEY, true);
ConfigService tmpConfigServices = null;
try {
configService = NacosFactory.createConfigService(nacosProperties);
} catch (NacosException e) {
if (logger.isErrorEnabled()) {
logger.error(CONFIG_ERROR_NACOS, "", "", e.getMessage(), e);
for (int i = 0; i < retryTimes + 1; i++) {
tmpConfigServices = NacosFactory.createConfigService(nacosProperties);
if (!check || (UP.equals(tmpConfigServices.getServerStatus()) && testConfigService(tmpConfigServices))) {
break;
} else {
logger.warn(LoggerCodeConstants.CONFIG_ERROR_NACOS, "", "",
"Failed to connect to nacos config server. " +
(i < retryTimes ? "Dubbo will try to retry in " + sleepMsBetweenRetries + ". " : "Exceed retry max times.") +
"Try times: " + (i + 1));
}
tmpConfigServices.shutDown();
tmpConfigServices = null;
Thread.sleep(sleepMsBetweenRetries);
}
} catch (NacosException e) {
logger.error(CONFIG_ERROR_NACOS, "", "", e.getErrMsg(), e);
throw new IllegalStateException(e);
} catch (InterruptedException e) {
logger.error(INTERNAL_INTERRUPTED, "", "", "Interrupted when creating nacos config service client.", e);
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
return new NacosConfigServiceWrapper(configService);
if (tmpConfigServices == null) {
logger.error(CONFIG_ERROR_NACOS, "", "", "Failed to create nacos config service client. Reason: server status check failed.");
throw new IllegalStateException("Failed to create nacos config service client. Reason: server status check failed.");
}
return new NacosConfigServiceWrapper(tmpConfigServices);
}
private boolean testConfigService(ConfigService configService) {
try {
configService.getConfig("Dubbo-Nacos-Test", "Dubbo-Nacos-Test", DEFAULT_TIMEOUT);
return true;
} catch (NacosException e) {
return false;
}
}
private Properties buildNacosProperties(URL url) {

View File

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.configcenter.support.nacos;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
public class MockConfigService implements ConfigService {
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
return null;
}
@Override
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException {
return null;
}
@Override
public void addListener(String dataId, String group, Listener listener) throws NacosException {
}
@Override
public boolean publishConfig(String dataId, String group, String content) throws NacosException {
return false;
}
@Override
public boolean publishConfig(String dataId, String group, String content, String type) throws NacosException {
return false;
}
@Override
public boolean publishConfigCas(String dataId, String group, String content, String casMd5) throws NacosException {
return false;
}
@Override
public boolean publishConfigCas(String dataId, String group, String content, String casMd5, String type) throws NacosException {
return false;
}
@Override
public boolean removeConfig(String dataId, String group) throws NacosException {
return false;
}
@Override
public void removeListener(String dataId, String group, Listener listener) {
}
@Override
public String getServerStatus() {
return null;
}
@Override
public void shutDown() throws NacosException {
}
}

View File

@ -0,0 +1,122 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.configcenter.support.nacos;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.dubbo.common.URL;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.DOWN;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static org.mockito.ArgumentMatchers.any;
class RetryTest {
@Test
void testRetryCreate() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
ConfigService mock = new MockConfigService() {
@Override
public String getServerStatus() {
return atomicInteger.incrementAndGet() > 10 ? UP : DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> new NacosDynamicConfiguration(url));
try {
new NacosDynamicConfiguration(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testDisable() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
ConfigService mock = new MockConfigService() {
@Override
public String getServerStatus() {
return DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10)
.addParameter("nacos.check", "false");
try {
new NacosDynamicConfiguration(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testRequest() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
ConfigService mock = new MockConfigService() {
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
if (atomicInteger.incrementAndGet() > 10) {
return "";
} else {
throw new NacosException();
}
}
@Override
public String getServerStatus() {
return UP;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> new NacosDynamicConfiguration(url));
try {
new NacosDynamicConfiguration(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
}

View File

@ -100,7 +100,7 @@
<httpclient_version>4.5.13</httpclient_version>
<httpcore_version>4.4.6</httpcore_version>
<fastjson_version>1.2.83</fastjson_version>
<fastjson2_version>2.0.21</fastjson2_version>
<fastjson2_version>2.0.23</fastjson2_version>
<zookeeper_version>3.4.14</zookeeper_version>
<curator_version>4.2.0</curator_version>
<curator_test_version>2.12.0</curator_test_version>

View File

@ -17,11 +17,24 @@
package org.apache.dubbo.metadata.store.nacos;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigItem;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
import org.apache.dubbo.common.utils.JsonUtils;
import org.apache.dubbo.common.utils.MD5Utils;
import org.apache.dubbo.common.utils.StringUtils;
@ -38,23 +51,15 @@ import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractSharedListener;
import com.alibaba.nacos.api.exception.NacosException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_ERROR_NACOS;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INTERRUPTED;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_NACOS_EXCEPTION;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
@ -81,23 +86,63 @@ public class NacosMetadataReport extends AbstractMetadataReport {
private MD5Utils md5Utils = new MD5Utils();
private static final String NACOS_RETRY_KEY = "nacos.retry";
private static final String NACOS_RETRY_WAIT_KEY = "nacos.retry-wait";
private static final String NACOS_CHECK_KEY = "nacos.check";
public NacosMetadataReport(URL url) {
super(url);
this.configService = buildConfigService(url);
group = url.getParameter(GROUP_KEY, DEFAULT_ROOT);
}
public NacosConfigServiceWrapper buildConfigService(URL url) {
private NacosConfigServiceWrapper buildConfigService(URL url) {
Properties nacosProperties = buildNacosProperties(url);
int retryTimes = url.getPositiveParameter(NACOS_RETRY_KEY, 10);
int sleepMsBetweenRetries = url.getPositiveParameter(NACOS_RETRY_WAIT_KEY, 1000);
boolean check = url.getParameter(NACOS_CHECK_KEY, true);
ConfigService tmpConfigServices = null;
try {
configService = new NacosConfigServiceWrapper(NacosFactory.createConfigService(nacosProperties));
} catch (NacosException e) {
if (logger.isErrorEnabled()) {
logger.error(REGISTRY_NACOS_EXCEPTION, "", "", e.getErrMsg(), e);
for (int i = 0; i < retryTimes + 1; i++) {
tmpConfigServices = NacosFactory.createConfigService(nacosProperties);
if (!check || (UP.equals(tmpConfigServices.getServerStatus()) && testConfigService(tmpConfigServices))) {
break;
} else {
logger.warn(LoggerCodeConstants.CONFIG_ERROR_NACOS, "", "",
"Failed to connect to nacos config server. " +
(i < retryTimes ? "Dubbo will try to retry in " + sleepMsBetweenRetries + ". " : "Exceed retry max times.") +
"Try times: " + (i + 1));
}
tmpConfigServices.shutDown();
tmpConfigServices = null;
Thread.sleep(sleepMsBetweenRetries);
}
} catch (NacosException e) {
logger.error(CONFIG_ERROR_NACOS, "", "", e.getErrMsg(), e);
throw new IllegalStateException(e);
} catch (InterruptedException e) {
logger.error(INTERNAL_INTERRUPTED, "", "", "Interrupted when creating nacos config service client.", e);
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
return configService;
if (tmpConfigServices == null) {
logger.error(CONFIG_ERROR_NACOS, "", "", "Failed to create nacos config service client. Reason: server status check failed.");
throw new IllegalStateException("Failed to create nacos config service client. Reason: server status check failed.");
}
return new NacosConfigServiceWrapper(tmpConfigServices);
}
private boolean testConfigService(ConfigService configService) {
try {
configService.getConfig("Dubbo-Nacos-Test", "Dubbo-Nacos-Test", 3000L);
return true;
} catch (NacosException e) {
return false;
}
}
private Properties buildNacosProperties(URL url) {

View File

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.store.nacos;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
public class MockConfigService implements ConfigService {
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
return null;
}
@Override
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException {
return null;
}
@Override
public void addListener(String dataId, String group, Listener listener) throws NacosException {
}
@Override
public boolean publishConfig(String dataId, String group, String content) throws NacosException {
return false;
}
@Override
public boolean publishConfig(String dataId, String group, String content, String type) throws NacosException {
return false;
}
@Override
public boolean publishConfigCas(String dataId, String group, String content, String casMd5) throws NacosException {
return false;
}
@Override
public boolean publishConfigCas(String dataId, String group, String content, String casMd5, String type) throws NacosException {
return false;
}
@Override
public boolean removeConfig(String dataId, String group) throws NacosException {
return false;
}
@Override
public void removeListener(String dataId, String group, Listener listener) {
}
@Override
public String getServerStatus() {
return null;
}
@Override
public void shutDown() throws NacosException {
}
}

View File

@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metadata.store.nacos;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.dubbo.common.URL;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.DOWN;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static org.mockito.ArgumentMatchers.any;
class RetryTest {
@Test
void testRetryCreate() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
ConfigService mock = new MockConfigService() {
@Override
public String getServerStatus() {
return atomicInteger.incrementAndGet() > 10 ? UP : DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> new NacosMetadataReport(url));
try {
new NacosMetadataReport(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testDisable() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
ConfigService mock = new MockConfigService() {
@Override
public String getServerStatus() {
return DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10)
.addParameter("nacos.check", "false");
try {
new NacosMetadataReport(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testRequest() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
ConfigService mock = new MockConfigService() {
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
if (atomicInteger.incrementAndGet() > 10) {
return "";
} else {
throw new NacosException();
}
}
@Override
public String getServerStatus() {
return UP;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createConfigService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> new NacosMetadataReport(url));
try {
new NacosMetadataReport(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
}

View File

@ -296,12 +296,23 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
throw new UnsupportedOperationException("Service discovery implementation does not support lookup of url list.");
}
protected void doUpdate(ServiceInstance oldServiceInstance, ServiceInstance newServiceInstance) throws RuntimeException {
/**
* Update Service Instance. Unregister and then register by default.
* Can be override if registry support update instance directly.
* <br/>
* NOTICE: Remind to update {@link AbstractServiceDiscovery#serviceInstance}'s reference if updated
* and report metadata by {@link AbstractServiceDiscovery#reportMetadata(MetadataInfo)}
*
* @param oldServiceInstance origin service instance
* @param newServiceInstance new service instance
*/
protected void doUpdate(ServiceInstance oldServiceInstance, ServiceInstance newServiceInstance) {
this.doUnregister(oldServiceInstance);
if (!EMPTY_REVISION.equals(getExportedServicesRevision(serviceInstance))) {
reportMetadata(serviceInstance.getServiceMetadata());
this.serviceInstance = newServiceInstance;
this.serviceInstance = newServiceInstance;
if (!EMPTY_REVISION.equals(getExportedServicesRevision(newServiceInstance))) {
reportMetadata(newServiceInstance.getServiceMetadata());
this.doRegister(newServiceInstance);
}
}

View File

@ -117,7 +117,7 @@ public class NacosNamingServiceWrapper {
logger.warn(LoggerCodeConstants.REGISTRY_NACOS_EXCEPTION, "", "",
"Failed to request nacos naming server. " +
(times < retryTimes ? "Dubbo will try to retry in " + sleepMsBetweenRetries + ". " : "Exceed retry max times.") +
"Try times: " + times + 1, e);
"Try times: " + (times + 1), e);
if (times < retryTimes) {
try {
Thread.sleep(sleepMsBetweenRetries);
@ -151,7 +151,7 @@ public class NacosNamingServiceWrapper {
logger.warn(LoggerCodeConstants.REGISTRY_NACOS_EXCEPTION, "", "",
"Failed to request nacos naming server. " +
(times < retryTimes ? "Dubbo will try to retry in " + sleepMsBetweenRetries + ". " : "Exceed retry max times.") +
"Try times: " + times + 1, e);
"Try times: " + (times + 1), e);
if (times < retryTimes) {
try {
Thread.sleep(sleepMsBetweenRetries);

View File

@ -113,13 +113,15 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
if (!Objects.equals(oldServiceInstance.getServiceName(), newServiceInstance.getServiceName()) ||
!Objects.equals(oldServiceInstance.getAddress(), newServiceInstance.getAddress()) ||
!Objects.equals(oldServiceInstance.getPort(), newServiceInstance.getPort())) {
// ignore if host-ip changed
// Ignore if host-ip changed. Should unregister first.
super.doUpdate(oldServiceInstance, newServiceInstance);
return;
}
try {
this.serviceInstance = newServiceInstance;
reportMetadata(newServiceInstance.getServiceMetadata());
// override without unregister
this.doRegister(newServiceInstance);
} catch (Exception e) {

View File

@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Properties;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
@ -39,8 +40,10 @@ import static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;
import static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static com.alibaba.nacos.client.naming.utils.UtilAndComs.NACOS_NAMING_LOG_NAME;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INTERRUPTED;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_NACOS_EXCEPTION;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
@ -57,6 +60,8 @@ public class NacosNamingServiceUtils {
private static final String NACOS_RETRY_KEY = "nacos.retry";
private static final String NACOS_CHECK_KEY = "nacos.check";
private static final String NACOS_RETRY_WAIT_KEY = "nacos.retry-wait";
@ -119,20 +124,51 @@ public class NacosNamingServiceUtils {
*/
public static NacosNamingServiceWrapper createNamingService(URL connectionURL) {
Properties nacosProperties = buildNacosProperties(connectionURL);
NamingService namingService;
int retryTimes = connectionURL.getPositiveParameter(NACOS_RETRY_KEY, 10);
int sleepMsBetweenRetries = connectionURL.getPositiveParameter(NACOS_RETRY_WAIT_KEY, 1000);
boolean check = connectionURL.getParameter(NACOS_CHECK_KEY, true);
NamingService namingService = null;
try {
namingService = NacosFactory.createNamingService(nacosProperties);
} catch (NacosException e) {
if (logger.isErrorEnabled()) {
logger.error(REGISTRY_NACOS_EXCEPTION, "", "", e.getErrMsg(), e);
for (int i = 0; i < retryTimes + 1; i++) {
namingService = NacosFactory.createNamingService(nacosProperties);
if (!check || (UP.equals(namingService.getServerStatus()) && testNamingService(namingService))) {
break;
} else {
logger.warn(LoggerCodeConstants.REGISTRY_NACOS_EXCEPTION, "", "",
"Failed to connect to nacos naming server. " +
(i < retryTimes ? "Dubbo will try to retry in " + sleepMsBetweenRetries + ". " : "Exceed retry max times.") +
"Try times: " + (i + 1));
}
namingService.shutDown();
namingService = null;
Thread.sleep(sleepMsBetweenRetries);
}
} catch (NacosException e) {
logger.error(REGISTRY_NACOS_EXCEPTION, "", "", e.getErrMsg(), e);
throw new IllegalStateException(e);
} catch (InterruptedException e) {
logger.error(INTERNAL_INTERRUPTED, "", "", "Interrupted when creating nacos naming service client.", e);
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
int retryTimes = connectionURL.getParameter(NACOS_RETRY_KEY, 10);
int sleepMsBetweenRetries = connectionURL.getParameter(NACOS_RETRY_WAIT_KEY, 10);
if (namingService == null) {
logger.error(REGISTRY_NACOS_EXCEPTION, "", "", "Failed to create nacos naming service client. Reason: server status check failed.");
throw new IllegalStateException("Failed to create nacos naming service client. Reason: server status check failed.");
}
return new NacosNamingServiceWrapper(namingService, retryTimes, sleepMsBetweenRetries);
}
private static boolean testNamingService(NamingService namingService) {
try {
namingService.getAllInstances("Dubbo-Nacos-Test", false);
return true;
} catch (NacosException e) {
return false;
}
}
private static Properties buildNacosProperties(URL url) {
Properties properties = new Properties();
setServerAddr(url, properties);

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.registry.nacos;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -42,7 +41,7 @@ class NacosRegistryFactoryTest {
@Test
void testCreateRegistryCacheKey() {
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":8080");
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":8080?nacos.check=false");
String registryCacheKey1 = nacosRegistryFactory.createRegistryCacheKey(url);
String registryCacheKey2 = nacosRegistryFactory.createRegistryCacheKey(url);
Assertions.assertEquals(registryCacheKey1, registryCacheKey2);
@ -50,7 +49,7 @@ class NacosRegistryFactoryTest {
@Test
void testCreateRegistryCacheKeyWithNamespace() {
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":8080?namespace=test");
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":8080?namespace=test&nacos.check=false");
String registryCacheKey1 = nacosRegistryFactory.createRegistryCacheKey(url);
String registryCacheKey2 = nacosRegistryFactory.createRegistryCacheKey(url);
Assertions.assertEquals(registryCacheKey1, registryCacheKey2);

View File

@ -69,7 +69,7 @@ class NacosRegistryTest {
int nacosServerPort = NetUtils.getAvailablePort();
this.registryUrl = URL.valueOf("nacos://localhost:" + nacosServerPort);
this.registryUrl = URL.valueOf("nacos://localhost:" + nacosServerPort + "?nacos.check=false");
this.nacosRegistryFactory = new NacosRegistryFactory();

View File

@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -42,7 +41,7 @@ class NacosServiceDiscoveryFactoryTest {
@Test
void testGetServiceDiscoveryWithCache() {
URL url = URL.valueOf("dubbo://test:8080");
URL url = URL.valueOf("dubbo://test:8080?nacos.check=false");
ServiceDiscovery discovery = nacosServiceDiscoveryFactory.createDiscovery(url);
Assertions.assertTrue(discovery instanceof NacosServiceDiscovery);

View File

@ -16,6 +16,12 @@
*/
package org.apache.dubbo.registry.nacos;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.config.ApplicationConfig;
@ -25,10 +31,6 @@ import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
@ -37,11 +39,9 @@ import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.util.collections.Sets;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -63,7 +63,7 @@ class NacosServiceDiscoveryTest {
private static final String LOCALHOST = "127.0.0.1";
protected URL registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort());
protected URL registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort() + "?nacos.check=false");
private NacosServiceDiscovery nacosServiceDiscovery;
@ -79,7 +79,7 @@ class NacosServiceDiscoveryTest {
public NacosServiceDiscoveryGroupTest1() {
super();
group = "test-group1";
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort()).addParameter("group", group);
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort() + "?nacos.check=false").addParameter("group", group);
}
}
@ -87,7 +87,7 @@ class NacosServiceDiscoveryTest {
public NacosServiceDiscoveryGroupTest2() {
super();
group = "test-group2";
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort()).addParameter("group", group);
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort() + "?nacos.check=false").addParameter("group", group);
}
}
@ -97,7 +97,7 @@ class NacosServiceDiscoveryTest {
public NacosServiceDiscoveryGroupTest3() {
super();
group = DEFAULT_GROUP;
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort()).addParameter("group", "test-group3");
registryUrl = URL.valueOf("nacos://127.0.0.1:" + NetUtils.getAvailablePort() + "?nacos.check=false").addParameter("group", "test-group3");
}
@BeforeAll

View File

@ -16,19 +16,30 @@
*/
package org.apache.dubbo.registry.nacos.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.registry.nacos.MockNamingService;
import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.DOWN;
import static com.alibaba.nacos.client.constant.Constants.HealthCheck.UP;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
/**
@ -67,8 +78,94 @@ class NacosNamingServiceUtilsTest {
@Test
void testCreateNamingService() {
URL url = URL.valueOf("test://test:8080/test?backup=backup");
URL url = URL.valueOf("test://test:8080/test?backup=backup&nacos.check=false");
NacosNamingServiceWrapper namingService = NacosNamingServiceUtils.createNamingService(url);
Assertions.assertNotNull(namingService);
}
@Test
void testRetryCreate() throws NacosException {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
NamingService mock = new MockNamingService() {
@Override
public String getServerStatus() {
return atomicInteger.incrementAndGet() > 10 ? UP : DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> NacosNamingServiceUtils.createNamingService(url));
try {
NacosNamingServiceUtils.createNamingService(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testDisable() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
NamingService mock = new MockNamingService() {
@Override
public String getServerStatus() {
return DOWN;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10)
.addParameter("nacos.check", "false");
try {
NacosNamingServiceUtils.createNamingService(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
@Test
void testRequest() {
try (MockedStatic<NacosFactory> nacosFactoryMockedStatic = Mockito.mockStatic(NacosFactory.class)) {
AtomicInteger atomicInteger = new AtomicInteger(0);
NamingService mock = new MockNamingService() {
@Override
public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {
if (atomicInteger.incrementAndGet() > 10) {
return null;
} else {
throw new NacosException();
}
}
@Override
public String getServerStatus() {
return UP;
}
};
nacosFactoryMockedStatic.when(() -> NacosFactory.createNamingService((Properties) any())).thenReturn(mock);
URL url = URL.valueOf("nacos://127.0.0.1:8848")
.addParameter("nacos.retry", 5)
.addParameter("nacos.retry-wait", 10);
Assertions.assertThrows(IllegalStateException.class, () -> NacosNamingServiceUtils.createNamingService(url));
try {
NacosNamingServiceUtils.createNamingService(url);
} catch (Throwable t) {
Assertions.fail(t);
}
}
}
}

View File

@ -120,7 +120,7 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> newInstance = build(newServiceInstance);
if (!Objects.equals(newInstance.getName(), oldInstance.getName()) ||
!Objects.equals(newInstance.getId(), oldInstance.getId())) {
// ignore if id changed
// Ignore if id changed. Should unregister first.
super.doUpdate(oldServiceInstance, newServiceInstance);
return;
}

View File

@ -17,23 +17,25 @@
package org.apache.dubbo.rpc.protocol.tri;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.serialize.MultipleSerialization;
import org.apache.dubbo.common.serialize.support.DefaultSerializationSelector;
import org.apache.dubbo.common.stream.StreamObserver;
import org.apache.dubbo.config.Constants;
import org.apache.dubbo.rpc.model.MethodDescriptor;
import org.apache.dubbo.rpc.model.PackableMethod;
import com.google.protobuf.Message;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.serialize.MultipleSerialization;
import org.apache.dubbo.common.serialize.support.DefaultSerializationSelector;
import org.apache.dubbo.common.stream.StreamObserver;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.config.Constants;
import org.apache.dubbo.rpc.model.MethodDescriptor;
import org.apache.dubbo.rpc.model.PackableMethod;
import com.google.protobuf.Message;
import static org.apache.dubbo.common.constants.CommonConstants.$ECHO;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME;
@ -91,8 +93,7 @@ public class ReflectionPackableMethod implements PackableMethod {
.getExtension(url.getParameter(Constants.MULTI_SERIALIZATION_KEY,
CommonConstants.DEFAULT_KEY));
this.requestPack = new WrapRequestPack(serialization, url, serializeName, actualRequestTypes,
singleArgument);
this.requestPack = new WrapRequestPack(serialization, url, serializeName, singleArgument);
this.responsePack = new WrapResponsePack(serialization, url, actualResponseType);
this.requestUnpack = new WrapRequestUnpack(serialization, url, actualRequestTypes);
this.responseUnpack = new WrapResponseUnpack(serialization, url, actualResponseType);
@ -322,10 +323,16 @@ public class ReflectionPackableMethod implements PackableMethod {
@Override
public byte[] pack(Object obj) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
multipleSerialization.serialize(url, serialize, actualResponseType, obj, bos);
Class<?> clz;
if (obj != null) {
clz = obj.getClass();
} else {
clz = actualResponseType;
}
multipleSerialization.serialize(url, serialize, clz, obj, bos);
return TripleCustomerProtocolWapper.TripleResponseWrapper.Builder.newBuilder()
.setSerializeType(serialize)
.setType(actualResponseType.getName())
.setType(clz.getName())
.setData(bos.toByteArray())
.build()
.toByteArray();
@ -334,15 +341,17 @@ public class ReflectionPackableMethod implements PackableMethod {
private static class WrapResponseUnpack implements UnPack {
private final Map<String, Class<?>> classCache = new ConcurrentHashMap<>();
private final MultipleSerialization serialization;
private final URL url;
private final Class<?> returnClass;
private final Class<?> actualResponseType;
private WrapResponseUnpack(MultipleSerialization serialization, URL url, Class<?> returnClass) {
private WrapResponseUnpack(MultipleSerialization serialization, URL url, Class<?> actualResponseType) {
this.serialization = serialization;
this.url = url;
this.returnClass = returnClass;
this.actualResponseType = actualResponseType;
}
@Override
@ -351,7 +360,8 @@ public class ReflectionPackableMethod implements PackableMethod {
.parseFrom(data);
final String serializeType = convertHessianFromWrapper(wrapper.getSerializeType());
ByteArrayInputStream bais = new ByteArrayInputStream(wrapper.getData());
return serialization.deserialize(url, serializeType, returnClass, bais);
Class<?> clz = getClassFromCache(wrapper.getType(), classCache, actualResponseType);
return serialization.deserialize(url, serializeType, clz, bais);
}
}
@ -359,21 +369,16 @@ public class ReflectionPackableMethod implements PackableMethod {
private final String serialize;
private final MultipleSerialization multipleSerialization;
private final String[] argumentsType;
private final URL url;
private final boolean singleArgument;
private final Class<?>[] actualRequestTypes;
private WrapRequestPack(MultipleSerialization multipleSerialization,
URL url,
String serialize,
Class<?>[] actualRequestTypes,
boolean singleArgument) {
this.url = url;
this.serialize = convertHessianToWrapper(serialize);
this.multipleSerialization = multipleSerialization;
this.actualRequestTypes = actualRequestTypes;
this.argumentsType = Stream.of(actualRequestTypes).map(Class::getName).toArray(String[]::new);
this.singleArgument = singleArgument;
}
@ -387,10 +392,8 @@ public class ReflectionPackableMethod implements PackableMethod {
}
final TripleCustomerProtocolWapper.TripleRequestWrapper.Builder builder = TripleCustomerProtocolWapper.TripleRequestWrapper.Builder.newBuilder();
builder.setSerializeType(serialize);
for (String type : argumentsType) {
builder.addArgTypes(type);
}
for (Object argument : arguments) {
builder.addArgTypes(argument.getClass().getName());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
multipleSerialization.serialize(url, serialize, argument.getClass(), argument, bos);
builder.addArgs(bos.toByteArray());
@ -433,6 +436,8 @@ public class ReflectionPackableMethod implements PackableMethod {
private class WrapRequestUnpack implements UnPack {
private final Map<String, Class<?>> classCache = new ConcurrentHashMap<>();
private final MultipleSerialization serialization;
private final URL url;
@ -453,11 +458,32 @@ public class ReflectionPackableMethod implements PackableMethod {
for (int i = 0; i < wrapper.getArgs().size(); i++) {
ByteArrayInputStream bais = new ByteArrayInputStream(
wrapper.getArgs().get(i));
ret[i] = serialization.deserialize(url, wrapper.getSerializeType(),
actualRequestTypes[i],
bais);
String className = wrapper.getArgTypes().get(i);
Class<?> clz = getClassFromCache(className, classCache, actualRequestTypes[i]);
ret[i] = serialization.deserialize(url, wrapper.getSerializeType(), clz, bais);
}
return ret;
}
}
private static Class<?> getClassFromCache(String className, Map<String, Class<?>> classCache, Class<?> expectedClass) {
if (expectedClass.getName().equals(className)) {
return expectedClass;
}
Class<?> clz = classCache.get(className);
if (clz == null) {
try {
clz = ClassUtils.forName(className);
} catch (Throwable e) {
// To catch IllegalStateException, LinkageError, ClassNotFoundException
clz = expectedClass;
}
classCache.put(className, clz);
}
return clz;
}
}

View File

@ -46,13 +46,13 @@ public class ReflectionAbstractServerCall extends AbstractServerCall {
private List<MethodDescriptor> methodDescriptors;
public ReflectionAbstractServerCall(Invoker<?> invoker,
ServerStream serverStream,
FrameworkModel frameworkModel,
String acceptEncoding,
String serviceName,
String methodName,
List<HeaderFilter> headerFilters,
Executor executor) {
ServerStream serverStream,
FrameworkModel frameworkModel,
String acceptEncoding,
String serviceName,
String methodName,
List<HeaderFilter> headerFilters,
Executor executor) {
super(invoker, serverStream, frameworkModel,
getServiceDescriptor(invoker.getUrl()),
acceptEncoding, serviceName, methodName,
@ -155,10 +155,8 @@ public class ReflectionAbstractServerCall extends AbstractServerCall {
if (isClosed()) {
return null;
}
if (serviceDescriptor != null) {
ClassLoadUtil.switchContextLoader(
serviceDescriptor.getServiceInterfaceClass().getClassLoader());
}
ClassLoadUtil.switchContextLoader(
invoker.getUrl().getServiceModel().getClassLoader());
return packableMethod.getRequestUnpack().unpack(data);
}