Merge branch '3.2' into Fixed-pojoutils-class-issues

This commit is contained in:
earthchen 2024-06-24 12:55:33 +08:00 committed by GitHub
commit b46a2390d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
102 changed files with 964 additions and 263 deletions

View File

@ -43,7 +43,7 @@ jobs:
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 8
java-version: 21
- uses: actions/cache@v3
name: "Cache local Maven repository"
with:

2
.gitignore vendored
View File

@ -11,6 +11,8 @@ target/
.settings/
.project
.classpath
.externalToolBuilders
maven-eclipse.xml
# idea ignore
.idea/

View File

@ -93,23 +93,23 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
// Provided by BitList only
public List<E> getOriginList() {
public synchronized List<E> getOriginList() {
return originList;
}
public void addIndex(int index) {
public synchronized void addIndex(int index) {
this.rootSet.set(index);
}
public int totalSetSize() {
public synchronized int totalSetSize() {
return this.originList.size();
}
public boolean indexExist(int index) {
public synchronized boolean indexExist(int index) {
return this.rootSet.get(index);
}
public E getByIndex(int index) {
public synchronized E getByIndex(int index) {
return this.originList.get(index);
}
@ -120,7 +120,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
* @param target target bitList
* @return this bitList only contains those elements contain in both two list and source bitList's tailList
*/
public BitList<E> and(BitList<E> target) {
public synchronized BitList<E> and(BitList<E> target) {
rootSet.and(target.rootSet);
if (target.getTailList() != null) {
target.getTailList().forEach(this::addToTailList);
@ -128,28 +128,28 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
return this;
}
public BitList<E> or(BitList<E> target) {
public synchronized BitList<E> or(BitList<E> target) {
BitSet resultSet = (BitSet) rootSet.clone();
resultSet.or(target.rootSet);
return new BitList<>(originList, resultSet, tailList);
}
public boolean hasMoreElementInTailList() {
public synchronized boolean hasMoreElementInTailList() {
return CollectionUtils.isNotEmpty(tailList);
}
public List<E> getTailList() {
public synchronized List<E> getTailList() {
return tailList;
}
public void addToTailList(E e) {
public synchronized void addToTailList(E e) {
if (tailList == null) {
tailList = new LinkedList<>();
}
tailList.add(e);
}
public E randomSelectOne() {
public synchronized E randomSelectOne() {
int originSize = originList.size();
int tailSize = tailList != null ? tailList.size() : 0;
int totalSize = originSize + tailSize;
@ -181,18 +181,18 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
// Provided by JDK List interface
@Override
public int size() {
public synchronized int size() {
return rootSet.cardinality() + (CollectionUtils.isNotEmpty(tailList) ? tailList.size() : 0);
}
@Override
public boolean contains(Object o) {
public synchronized boolean contains(Object o) {
int idx = originList.indexOf(o);
return (idx >= 0 && rootSet.get(idx)) || (CollectionUtils.isNotEmpty(tailList) && tailList.contains(o));
}
@Override
public Iterator<E> iterator() {
public synchronized Iterator<E> iterator() {
return new BitListIterator<>(this, 0);
}
@ -205,7 +205,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
* Notice: It is not recommended adding duplicated element.
*/
@Override
public boolean add(E e) {
public synchronized boolean add(E e) {
int index = originList.indexOf(e);
if (index > -1) {
rootSet.set(index);
@ -225,7 +225,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
* If the element is not contained in originList, try to remove from tailList.
*/
@Override
public boolean remove(Object o) {
public synchronized boolean remove(Object o) {
int idx = originList.indexOf(o);
if (idx > -1 && rootSet.get(idx)) {
rootSet.set(idx, false);
@ -242,7 +242,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
* This may change the default behaviour when adding new element later.
*/
@Override
public void clear() {
public synchronized void clear() {
rootSet.clear();
// to remove references
originList = Collections.emptyList();
@ -252,7 +252,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public E get(int index) {
public synchronized E get(int index) {
int bitIndex = -1;
if (index < 0) {
throw new IndexOutOfBoundsException();
@ -272,7 +272,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public E remove(int index) {
public synchronized E remove(int index) {
int bitIndex = -1;
if (index >= rootSet.cardinality()) {
if (CollectionUtils.isNotEmpty(tailList)) {
@ -290,7 +290,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public int indexOf(Object o) {
public synchronized int indexOf(Object o) {
int bitIndex = -1;
for (int i = 0; i < rootSet.cardinality(); i++) {
bitIndex = rootSet.nextSetBit(bitIndex + 1);
@ -311,7 +311,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
@Override
@SuppressWarnings("unchecked")
public boolean addAll(Collection<? extends E> c) {
public synchronized boolean addAll(Collection<? extends E> c) {
if (c instanceof BitList) {
rootSet.or(((BitList<? extends E>) c).rootSet);
if (((BitList<? extends E>) c).hasMoreElementInTailList()) {
@ -325,7 +325,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public int lastIndexOf(Object o) {
public synchronized int lastIndexOf(Object o) {
int bitIndex = -1;
int index = -1;
if (CollectionUtils.isNotEmpty(tailList)) {
@ -344,22 +344,22 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public boolean isEmpty() {
public synchronized boolean isEmpty() {
return this.rootSet.isEmpty() && CollectionUtils.isEmpty(tailList);
}
@Override
public ListIterator<E> listIterator() {
public synchronized ListIterator<E> listIterator() {
return new BitListIterator<>(this, 0);
}
@Override
public ListIterator<E> listIterator(int index) {
public synchronized ListIterator<E> listIterator(int index) {
return new BitListIterator<>(this, index);
}
@Override
public BitList<E> subList(int fromIndex, int toIndex) {
public synchronized BitList<E> subList(int fromIndex, int toIndex) {
BitSet resultSet = (BitSet) rootSet.clone();
List<E> copiedTailList = tailList == null ? null : new LinkedList<>(tailList);
if (toIndex < size()) {
@ -414,7 +414,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public boolean hasNext() {
public synchronized boolean hasNext() {
if (isInTailList) {
return tailListIterator.hasNext();
} else {
@ -428,7 +428,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public E next() {
public synchronized E next() {
if (isInTailList) {
if (tailListIterator.hasNext()) {
index += 1;
@ -457,7 +457,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public boolean hasPrevious() {
public synchronized boolean hasPrevious() {
if (isInTailList) {
boolean hasPreviousInTailList = tailListIterator.hasPrevious();
if (hasPreviousInTailList) {
@ -471,7 +471,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public E previous() {
public synchronized E previous() {
if (isInTailList) {
boolean hasPreviousInTailList = tailListIterator.hasPrevious();
if (hasPreviousInTailList) {
@ -503,17 +503,17 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public int nextIndex() {
public synchronized int nextIndex() {
return hasNext() ? index + 1 : index;
}
@Override
public int previousIndex() {
public synchronized int previousIndex() {
return index;
}
@Override
public void remove() {
public synchronized void remove() {
if (lastReturnedIndex == -1) {
throw new IllegalStateException();
} else {
@ -533,17 +533,17 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public void set(E e) {
public synchronized void set(E e) {
throw new UnsupportedOperationException("Set method is not supported in BitListIterator!");
}
@Override
public void add(E e) {
public synchronized void add(E e) {
throw new UnsupportedOperationException("Add method is not supported in BitListIterator!");
}
}
public ArrayList<E> cloneToArrayList() {
public synchronized ArrayList<E> cloneToArrayList() {
if (rootSet.cardinality() == originList.size() && (CollectionUtils.isEmpty(tailList))) {
return new ArrayList<>(originList);
}
@ -553,7 +553,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
}
@Override
public BitList<E> clone() {
public synchronized BitList<E> clone() {
return new BitList<>(
originList, (BitSet) rootSet.clone(), tailList == null ? null : new LinkedList<>(tailList));
}

View File

@ -22,6 +22,8 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -576,4 +578,44 @@ class BitListTest {
set.add(new LinkedList<>(Arrays.asList("A", "B", "C", "D", "E", "F", "G")));
Assertions.assertEquals(2, set.size());
}
@Test
void testConcurrent() throws InterruptedException {
for (int i = 0; i < 100000; i++) {
BitList<String> bitList = new BitList<>(Collections.singletonList("test"));
bitList.remove("test");
CountDownLatch countDownLatch = new CountDownLatch(1);
CountDownLatch countDownLatch2 = new CountDownLatch(2);
Thread thread1 = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
bitList.add("test");
countDownLatch2.countDown();
});
AtomicReference<BitList<String>> ref = new AtomicReference<>();
Thread thread2 = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ref.set(bitList.clone());
countDownLatch2.countDown();
});
thread1.start();
thread2.start();
countDownLatch.countDown();
countDownLatch2.await();
Assertions.assertDoesNotThrow(() -> ref.get().iterator().hasNext());
}
}
}

View File

@ -1295,6 +1295,19 @@ public /*final**/ class URL implements Serializable {
return serviceNameBuilder.toString();
}
/**
* The format is "{interface}:[version]"
*
* @return
*/
public String getCompatibleColonSeparatedKey() {
StringBuilder serviceNameBuilder = new StringBuilder();
serviceNameBuilder.append(this.getServiceInterface());
compatibleAppend(serviceNameBuilder, VERSION_KEY);
compatibleAppend(serviceNameBuilder, GROUP_KEY);
return serviceNameBuilder.toString();
}
private void append(StringBuilder target, String parameterName, boolean first) {
String parameterValue = this.getParameter(parameterName);
if (!isBlank(parameterValue)) {
@ -1307,6 +1320,14 @@ public /*final**/ class URL implements Serializable {
}
}
private void compatibleAppend(StringBuilder target, String parameterName) {
String parameterValue = this.getParameter(parameterName);
if (!isBlank(parameterValue)) {
target.append(':');
target.append(parameterValue);
}
}
/**
* The format of return value is '{group}/{interfaceName}:{version}'
*
@ -1376,6 +1397,10 @@ public /*final**/ class URL implements Serializable {
return buildString(true, false, true, true);
}
public String toServiceString(String... parameters) {
return buildString(true, true, true, true, parameters);
}
@Deprecated
public String getServiceName() {
return getServiceInterface();

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
@ -84,7 +85,8 @@ public final class Version {
}
private static void tryLoadVersionFromResource() throws IOException {
Enumeration<URL> configLoader = Version.class.getClassLoader().getResources("META-INF/versions/dubbo-common");
Enumeration<URL> configLoader =
Version.class.getClassLoader().getResources(CommonConstants.DUBBO_VERSIONS_KEY + "/dubbo-common");
if (configLoader.hasMoreElements()) {
URL url = configLoader.nextElement();
try (BufferedReader reader =
@ -312,7 +314,7 @@ public final class Version {
private static void checkArtifact(String artifactId) throws IOException {
Enumeration<URL> artifactEnumeration =
Version.class.getClassLoader().getResources("META-INF/versions/" + artifactId);
Version.class.getClassLoader().getResources(CommonConstants.DUBBO_VERSIONS_KEY + artifactId);
while (artifactEnumeration.hasMoreElements()) {
URL url = artifactEnumeration.nextElement();
try (BufferedReader reader =
@ -348,7 +350,7 @@ public final class Version {
private static Set<String> loadArtifactIds() throws IOException {
Enumeration<URL> artifactsEnumeration =
Version.class.getClassLoader().getResources("META-INF/versions/.artifacts");
Version.class.getClassLoader().getResources(CommonConstants.DUBBO_VERSIONS_KEY + "/.artifacts");
Set<String> artifactIds = new HashSet<>();
while (artifactsEnumeration.hasMoreElements()) {
URL url = artifactsEnumeration.nextElement();

View File

@ -31,10 +31,9 @@ import java.io.StringReader;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
@ -43,6 +42,7 @@ import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_SECONDS_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_PROPERTY_TYPE_MISMATCH;
/**
* Utilities for manipulating configurations from different sources
@ -57,18 +57,18 @@ public final class ConfigurationUtils {
}
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ConfigurationUtils.class);
private static final List<String> securityKey;
private static final Set<String> securityKey;
private static volatile long expectedShutdownTime = Long.MAX_VALUE;
static {
List<String> keys = new LinkedList<>();
Set<String> keys = new HashSet<>();
keys.add("accesslog");
keys.add("router");
keys.add("rule");
keys.add("runtime");
keys.add("type");
securityKey = Collections.unmodifiableList(keys);
securityKey = Collections.unmodifiableSet(keys);
}
/**
@ -213,11 +213,15 @@ public final class ConfigurationUtils {
properties.load(new StringReader(content));
properties.stringPropertyNames().forEach(k -> {
boolean deny = false;
for (String key : securityKey) {
if (k.contains(key)) {
deny = true;
break;
}
// check whether property name is safe or not based on the last fragment kebab-case comparison.
String[] fragments = k.split("\\.");
if (securityKey.contains(StringUtils.convertToSplitName(fragments[fragments.length - 1], "-"))) {
deny = true;
logger.warn(
COMMON_PROPERTY_TYPE_MISMATCH,
"security properties are not allowed to be set",
"",
String.format("'%s' is not allowed to be set as it is on the security key list.", k));
}
if (!deny) {
map.put(k, properties.getProperty(k));

View File

@ -24,6 +24,7 @@ import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
public interface CommonConstants {
String DUBBO = "dubbo";
String TRIPLE = "tri";
@ -267,12 +268,14 @@ public interface CommonConstants {
String $INVOKE = "$invoke";
String $INVOKE_ASYNC = "$invokeAsync";
String GENERIC_PARAMETER_DESC = "Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;";
/**
* echo call
*/
String $ECHO = "$echo";
/**
* package version in the manifest
*/
@ -283,12 +286,19 @@ public interface CommonConstants {
int MAX_PROXY_COUNT = 65535;
String MONITOR_KEY = "monitor";
String BACKGROUND_KEY = "background";
String CLUSTER_KEY = "cluster";
String USERNAME_KEY = "username";
String PASSWORD_KEY = "password";
String HOST_KEY = "host";
String PORT_KEY = "port";
String DUBBO_IP_TO_BIND = "DUBBO_IP_TO_BIND";
/**
@ -308,21 +318,29 @@ public interface CommonConstants {
String SHUTDOWN_WAIT_SECONDS_KEY = "dubbo.service.shutdown.wait.seconds";
String SHUTDOWN_WAIT_KEY = "dubbo.service.shutdown.wait";
String DUBBO_PROTOCOL = "dubbo";
String DUBBO_LABELS = "dubbo.labels";
String DUBBO_ENV_KEYS = "dubbo.env.keys";
String CONFIG_CONFIGFILE_KEY = "config-file";
String CONFIG_ENABLE_KEY = "highest-priority";
String CONFIG_NAMESPACE_KEY = "namespace";
String CHECK_KEY = "check";
String BACKLOG_KEY = "backlog";
String HEARTBEAT_EVENT = null;
String MOCK_HEARTBEAT_EVENT = "H";
String READONLY_EVENT = "R";
String WRITEABLE_EVENT = "W";
String REFERENCE_FILTER_KEY = "reference.filter";
@ -459,6 +477,7 @@ public interface CommonConstants {
String REGISTRY_DELAY_NOTIFICATION_KEY = "delay-notification";
String CACHE_CLEAR_TASK_INTERVAL = "dubbo.application.url.cache.task.interval";
String CACHE_CLEAR_WAITING_THRESHOLD = "dubbo.application.url.cache.clear.waiting";
String CLUSTER_INTERCEPTOR_COMPATIBLE_KEY = "dubbo.application.cluster.interceptor.compatible";
@ -615,17 +634,18 @@ public interface CommonConstants {
String SERVICE_EXECUTOR = "service-executor";
String EXECUTOR_MANAGEMENT_MODE = "executor-management-mode";
String EXECUTOR_MANAGEMENT_MODE_DEFAULT = "default";
String EXECUTOR_MANAGEMENT_MODE_ISOLATION = "isolation";
/**
*
* used in JVMUtil.java ,Control stack print lines, default is 32 lines
*
*/
String DUBBO_JSTACK_MAXLINE = "dubbo.jstack-dump.max-line";
String ENCODE_IN_IO_THREAD_KEY = "encode.in.io";
boolean DEFAULT_ENCODE_IN_IO_THREAD = false;
/**
@ -646,4 +666,8 @@ public interface CommonConstants {
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
String DUBBO2_COMPACT_ENABLE = "dubbo.compact.enable";
String ZOOKEEPER_ENSEMBLE_TRACKER_KEY = "zookeeper.ensemble.tracker";
String DUBBO_VERSIONS_KEY = "META-INF/dubbo-versions";
}

View File

@ -141,4 +141,11 @@ public interface RegistryConstants {
String ENABLE_EMPTY_PROTECTION_KEY = "enable-empty-protection";
boolean DEFAULT_ENABLE_EMPTY_PROTECTION = false;
String REGISTER_CONSUMER_URL_KEY = "register-consumer-url";
/**
* export noting suffix servicename
* by default, dubbo export servicename is "${interface}:${version}:", this servicename with ':' suffix
* for compatible, we should export noting suffix servicename, eg: ${interface}:${version}
*/
String NACOE_REGISTER_COMPATIBLE = "nacos.register-compatible";
}

View File

@ -23,6 +23,8 @@ import java.util.Map;
public interface JSON {
boolean isSupport();
boolean isJson(String json);
<T> T toJavaObject(String json, Type type);
<T> List<T> toJavaList(String json, Class<T> clazz);

View File

@ -19,9 +19,17 @@ package org.apache.dubbo.common.json.impl;
import java.lang.reflect.Type;
import java.util.List;
import com.alibaba.fastjson2.JSONValidator;
import com.alibaba.fastjson2.JSONWriter;
public class FastJson2Impl extends AbstractJSONImpl {
@Override
public boolean isJson(String json) {
JSONValidator validator = JSONValidator.from(json);
return validator.validate();
}
@Override
public <T> T toJavaObject(String json, Type type) {
return com.alibaba.fastjson2.JSON.parseObject(json, type);

View File

@ -23,6 +23,16 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
public class FastJsonImpl extends AbstractJSONImpl {
@Override
public boolean isJson(String json) {
try {
Object obj = com.alibaba.fastjson.JSON.parse(json);
return obj instanceof com.alibaba.fastjson.JSONObject || obj instanceof com.alibaba.fastjson.JSONArray;
} catch (com.alibaba.fastjson.JSONException e) {
return false;
}
}
@Override
public <T> T toJavaObject(String json, Type type) {
return com.alibaba.fastjson.JSON.parseObject(json, type);

View File

@ -20,12 +20,25 @@ import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
public class GsonImpl extends AbstractJSONImpl {
// weak reference of com.google.gson.Gson, prevent throw exception when init
private volatile Object gsonCache = null;
@Override
public boolean isJson(String json) {
try {
JsonElement jsonElement = JsonParser.parseString(json);
return jsonElement.isJsonObject() || jsonElement.isJsonArray();
} catch (JsonSyntaxException e) {
return false;
}
}
@Override
public <T> T toJavaObject(String json, Type type) {
return getGson().fromJson(json, type);

View File

@ -20,7 +20,9 @@ import java.lang.reflect.Type;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
@ -31,6 +33,16 @@ public class JacksonImpl extends AbstractJSONImpl {
private volatile Object jacksonCache = null;
@Override
public boolean isJson(String json) {
try {
JsonNode node = objectMapper.readTree(json);
return node.isObject() || node.isArray();
} catch (JsonProcessingException e) {
return false;
}
}
@Override
public <T> T toJavaObject(String json, Type type) {
try {

View File

@ -34,4 +34,6 @@ public interface DataStore {
void put(String componentName, String key, Object value);
void remove(String componentName, String key);
default void addListener(DataStoreUpdateListener dataStoreUpdateListener) {}
}

View File

@ -0,0 +1,21 @@
/*
* 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.common.store;
public interface DataStoreUpdateListener {
void onUpdate(String componentName, String key, Object value);
}

View File

@ -16,8 +16,13 @@
*/
package org.apache.dubbo.common.store.support;
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.store.DataStore;
import org.apache.dubbo.common.store.DataStoreUpdateListener;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import java.util.HashMap;
import java.util.Map;
@ -25,9 +30,11 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class SimpleDataStore implements DataStore {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SimpleDataStore.class);
// <component name or id, <data-name, data-value>>
private final ConcurrentMap<String, ConcurrentMap<String, Object>> data = new ConcurrentHashMap<>();
private final ConcurrentHashSet<DataStoreUpdateListener> listeners = new ConcurrentHashSet<>();
@Override
public Map<String, Object> get(String componentName) {
@ -52,6 +59,7 @@ public class SimpleDataStore implements DataStore {
Map<String, Object> componentData =
ConcurrentHashMapUtils.computeIfAbsent(data, componentName, k -> new ConcurrentHashMap<>());
componentData.put(key, value);
notifyListeners(componentName, key, value);
}
@Override
@ -60,5 +68,27 @@ public class SimpleDataStore implements DataStore {
return;
}
data.get(componentName).remove(key);
notifyListeners(componentName, key, null);
}
@Override
public void addListener(DataStoreUpdateListener dataStoreUpdateListener) {
listeners.add(dataStoreUpdateListener);
}
private void notifyListeners(String componentName, String key, Object value) {
for (DataStoreUpdateListener listener : listeners) {
try {
listener.onUpdate(componentName, key, value);
} catch (Throwable t) {
logger.warn(
LoggerCodeConstants.INTERNAL_ERROR,
"",
"",
"Failed to notify data store update listener. " + "ComponentName: " + componentName + " Key: "
+ key,
t);
}
}
}
}

View File

@ -146,4 +146,8 @@ public class JsonUtils {
public static List<String> checkStringList(List<?> rawList) {
return getJson().checkStringList(rawList);
}
public static boolean checkJson(String json) {
return getJson().isJson(json);
}
}

View File

@ -149,7 +149,11 @@ public interface Constants {
String SERVER_THREAD_POOL_NAME = "DubboServerHandler";
String SERVER_THREAD_POOL_PREFIX = SERVER_THREAD_POOL_NAME + "-";
String CLIENT_THREAD_POOL_NAME = "DubboClientHandler";
String CLIENT_THREAD_POOL_PREFIX = CLIENT_THREAD_POOL_NAME + "-";
String REST_PROTOCOL = "rest";
}

View File

@ -28,7 +28,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.EXTRA_KEYS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.ENABLE_EMPTY_PROTECTION_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
import static org.apache.dubbo.common.utils.PojoUtils.updatePropertyIfAbsent;
@ -221,7 +220,6 @@ public class RegistryConfig extends AbstractConfig {
}
@Override
@Parameter(key = REGISTRY_CLUSTER_KEY)
public String getId() {
return super.getId();
}

View File

@ -190,7 +190,6 @@ org.thymeleaf.
org.yaml.snakeyaml.tokens.
pstore.shaded.org.apache.commons.collections.
sun.print.
sun.rmi.server.
sun.rmi.transport.
sun.rmi.
weblogic.ejb20.internal.
weblogic.jms.common.

View File

@ -1132,4 +1132,22 @@ class URLTest {
assertEquals(20881, url.getPort());
assertEquals("apache", url.getParameter("name"));
}
@Test
void testToServiceString() {
URL url = URL.valueOf(
"zookeeper://10.20.130.230:4444/org.apache.dubbo.metadata.report.MetadataReport?version=1.0.0&application=vic&group=aaa");
assertEquals(
"zookeeper://10.20.130.230:4444/aaa/org.apache.dubbo.metadata.report.MetadataReport:1.0.0",
url.toServiceString());
}
@Test
void testToServiceStringWithParameters() {
URL url = URL.valueOf(
"zookeeper://10.20.130.230:4444/org.apache.dubbo.metadata.report.MetadataReport?version=1.0.0&application=vic&group=aaa&namespace=test");
assertEquals(
"zookeeper://10.20.130.230:4444/aaa/org.apache.dubbo.metadata.report.MetadataReport:1.0.0?namespace=test",
url.toServiceString("namespace"));
}
}

View File

@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import javassist.ClassPool;
@ -56,7 +57,8 @@ class ClassGeneratorTest {
ClassGenerator cg = ClassGenerator.newInstance();
// add className, interface, superClass
String className = BaseClass.class.getPackage().getName() + ".TestClass";
String className = BaseClass.class.getPackage().getName() + ".TestClass"
+ UUID.randomUUID().toString().replace("-", "");
cg.setClassName(className);
cg.addInterface(BaseInterface.class);
cg.setSuperClass(BaseClass.class);
@ -184,7 +186,7 @@ class ClassGeneratorTest {
fname.setAccessible(true);
ClassGenerator cg = ClassGenerator.newInstance();
cg.setClassName(Bean.class.getName() + "$Builder");
cg.setClassName(Bean.class.getName() + "$Builder" + UUID.randomUUID().toString());
cg.addInterface(Builder.class);
cg.addField("public static java.lang.reflect.Field FNAME;");
@ -211,7 +213,7 @@ class ClassGeneratorTest {
fname.setAccessible(true);
ClassGenerator cg = ClassGenerator.newInstance();
cg.setClassName(Bean.class.getName() + "$Builder2");
cg.setClassName(Bean.class.getName() + "$Builder2" + UUID.randomUUID().toString());
cg.addInterface(Builder.class);
cg.addField("FNAME", Modifier.PUBLIC | Modifier.STATIC, java.lang.reflect.Field.class);

View File

@ -45,8 +45,7 @@ class ExtensionDirectorTest {
// 2. Child ExtensionDirector can get extension instance from parent
// 3. Parent ExtensionDirector can't get extension instance from child
ExtensionDirector fwExtensionDirector =
new ExtensionDirector(null, ExtensionScope.FRAMEWORK, FrameworkModel.defaultModel());
ExtensionDirector fwExtensionDirector = FrameworkModel.defaultModel().getExtensionDirector();
ExtensionDirector appExtensionDirector =
new ExtensionDirector(fwExtensionDirector, ExtensionScope.APPLICATION, ApplicationModel.defaultModel());
ExtensionDirector moduleExtensionDirector = new ExtensionDirector(

View File

@ -36,7 +36,8 @@ class GsonUtilsTest {
Assertions.fail();
} catch (RuntimeException ex) {
Assertions.assertEquals(
"Generic serialization [gson] Json syntax exception thrown when parsing (message:{'name':'Tom','age':} type:class org.apache.dubbo.common.json.GsonUtilsTest$User) error:com.google.gson.stream.MalformedJsonException: Expected value at line 1 column 21 path $.age",
"Generic serialization [gson] Json syntax exception thrown when parsing (message:{'name':'Tom','age':} type:class org.apache.dubbo.common.json.GsonUtilsTest$User) error:com.google.gson.stream.MalformedJsonException: Expected value at line 1 column 21 path $.age\n"
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json",
ex.getMessage());
}
}

View File

@ -16,9 +16,13 @@
*/
package org.apache.dubbo.common.store.support;
import org.apache.dubbo.common.store.DataStoreUpdateListener;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@ -57,4 +61,30 @@ class SimpleDataStoreTest {
dataStore.remove("component", "key");
assertNotEquals(map, dataStore.get("component"));
}
@Test
void testNotify() {
DataStoreUpdateListener listener = Mockito.mock(DataStoreUpdateListener.class);
dataStore.addListener(listener);
ArgumentCaptor<String> componentNameCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Object> valueCaptor = ArgumentCaptor.forClass(Object.class);
dataStore.put("name", "key", "1");
Mockito.verify(listener).onUpdate(componentNameCaptor.capture(), keyCaptor.capture(), valueCaptor.capture());
assertEquals("name", componentNameCaptor.getValue());
assertEquals("key", keyCaptor.getValue());
assertEquals("1", valueCaptor.getValue());
dataStore.remove("name", "key");
Mockito.verify(listener, Mockito.times(2))
.onUpdate(componentNameCaptor.capture(), keyCaptor.capture(), valueCaptor.capture());
assertEquals("name", componentNameCaptor.getValue());
assertEquals("key", keyCaptor.getValue());
assertNull(valueCaptor.getValue());
dataStore.remove("name2", "key");
Mockito.verify(listener, Mockito.times(0)).onUpdate("name2", "key", null);
}
}

View File

@ -63,6 +63,49 @@ class JsonUtilsTest {
}
}
@Test
void testIsJson() {
JsonUtils.setJson(null);
// prefer use fastjson2
System.setProperty("dubbo.json-framework.prefer", "fastjson2");
Assertions.assertTrue(
JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}"));
Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string"));
Assertions.assertTrue(
JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]"));
System.clearProperty("dubbo.json-framework.prefer");
// prefer use fastjson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertTrue(
JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}"));
Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string"));
Assertions.assertTrue(
JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]"));
System.clearProperty("dubbo.json-framework.prefer");
// prefer use gson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "gson");
Assertions.assertTrue(
JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}"));
Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string"));
Assertions.assertTrue(
JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]"));
System.clearProperty("dubbo.json-framework.prefer");
// prefer use jackson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "jackson");
Assertions.assertTrue(
JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}"));
Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string"));
Assertions.assertTrue(
JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]"));
System.clearProperty("dubbo.json-framework.prefer");
}
@Test
void testGetJson1() {
Assertions.assertNotNull(JsonUtils.getJson());

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.version;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.constants.CommonConstants;
import java.io.FileInputStream;
import java.io.IOException;
@ -110,7 +111,7 @@ class VersionTest {
ClassLoader classLoader = new ClassLoader(originClassLoader) {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals("org.apache.dubbo.common.Version")) {
if ("org.apache.dubbo.common.Version".equals(name)) {
return findClass(name);
}
return super.loadClass(name);
@ -145,15 +146,13 @@ class VersionTest {
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (name.equals("META-INF/versions/dubbo-common")) {
if (name.equals(CommonConstants.DUBBO_VERSIONS_KEY + "/dubbo-common")) {
return super.getResources("META-INF/test-versions/dubbo-common");
}
return super.getResources(name);
}
};
Class<?> versionClass = classLoader.loadClass("org.apache.dubbo.common.Version");
return versionClass;
return classLoader.loadClass("org.apache.dubbo.common.Version");
}
@Test

View File

@ -54,6 +54,7 @@ public final class {{className}} {
private static final StubServiceDescriptor serviceDescriptor = new StubServiceDescriptor(SERVICE_NAME,{{interfaceClassName}}.class);
static {
org.apache.dubbo.rpc.protocol.tri.service.SchemaDescriptorRegistry.addSchemaDescriptor(SERVICE_NAME,{{outerClassName}}.getDescriptor());
StubSuppliers.addSupplier(SERVICE_NAME, {{className}}::newStub);
StubSuppliers.addSupplier({{interfaceClassName}}.JAVA_SERVICE_NAME, {{className}}::newStub);
StubSuppliers.addDescriptor(SERVICE_NAME, serviceDescriptor);

View File

@ -236,7 +236,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.19.7</version>
<version>1.19.8</version>
<scope>test</scope>
</dependency>

View File

@ -329,7 +329,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
}
}
metadataReportInstance.init(validMetadataReportConfigs);
if (!metadataReportInstance.inited()) {
if (!metadataReportInstance.isInitialized()) {
throw new IllegalStateException(String.format(
"%s MetadataConfigs found, but none of them is valid.", metadataReportConfigs.size()));
}
@ -382,6 +382,9 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
Optional<MetricsConfig> configOptional = configManager.getMetrics();
// If no specific metrics type is configured and there is no Prometheus dependency in the dependencies.
MetricsConfig metricsConfig = configOptional.orElse(new MetricsConfig(applicationModel));
if (PROTOCOL_PROMETHEUS.equals(metricsConfig.getProtocol()) && !isSupportPrometheus()) {
return;
}
if (StringUtils.isBlank(metricsConfig.getProtocol())) {
metricsConfig.setProtocol(isSupportPrometheus() ? PROTOCOL_PROMETHEUS : PROTOCOL_DEFAULT);
}

View File

@ -82,6 +82,7 @@ import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_MONITOR_ADDRESS;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
@ -108,6 +109,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGIST
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INTERFACE;
import static org.apache.dubbo.common.constants.RegistryConstants.DUBBO_REGISTER_MODE_DEFAULT_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
@ -217,6 +219,14 @@ public class ConfigValidationUtils {
if (!map.containsKey(PROTOCOL_KEY)) {
map.put(PROTOCOL_KEY, DUBBO_PROTOCOL);
}
String registryCluster = config.getId();
if (isEmpty(registryCluster)) {
registryCluster = DEFAULT_KEY;
}
if (map.containsKey(CONFIG_NAMESPACE_KEY)) {
registryCluster += ":" + map.get(CONFIG_NAMESPACE_KEY);
}
map.put(REGISTRY_CLUSTER_KEY, registryCluster);
List<URL> urls = UrlUtils.parseURLs(address, map);
for (URL url : urls) {

View File

@ -37,6 +37,8 @@ import org.apache.dubbo.config.metadata.ExporterDeployListener;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.monitor.MonitorService;
import org.apache.dubbo.registry.RegistryService;
import org.apache.dubbo.rpc.Exporter;
@ -50,10 +52,14 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import com.google.common.collect.Maps;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@ -61,10 +67,15 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_MONITOR_ADDRESS;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_SECONDS_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
import static org.apache.dubbo.metadata.MetadataConstants.REPORT_CONSUMER_URL_KEY;
import static org.hamcrest.CoreMatchers.anything;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;
@ -139,13 +150,29 @@ class DubboBootstrapTest {
@Test
void testLoadRegistries() {
SysProps.setProperty("dubbo.registry.address", "addr1");
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.setApplication(new ApplicationConfig("testLoadRegistries"));
String registryId = "nacosRegistry";
String namespace1 = "test";
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(registryId);
registryConfig.setAddress("nacos://addr1:8848");
Map<String, String> registryParamMap = Maps.newHashMap();
registryParamMap.put(CONFIG_NAMESPACE_KEY, namespace1);
registryConfig.setParameters(registryParamMap);
String namespace2 = "test2";
RegistryConfig registryConfig2 = new RegistryConfig();
registryConfig2.setAddress("polaris://addr1:9999");
Map<String, String> registryParamMap2 = Maps.newHashMap();
registryParamMap2.put(CONFIG_NAMESPACE_KEY, namespace2);
registryConfig2.setParameters(registryParamMap2);
serviceConfig.setRegistries(Arrays.asList(registryConfig, registryConfig2));
// load configs from props
DubboBootstrap.getInstance().initialize();
@ -154,16 +181,104 @@ class DubboBootstrapTest {
// ApplicationModel.defaultModel().getEnvironment().setDynamicConfiguration(new
// CompositeDynamicConfiguration());
List<URL> urls = ConfigValidationUtils.loadRegistries(serviceConfig, true);
Assertions.assertEquals(2, urls.size());
for (URL url : urls) {
Assertions.assertEquals(4, urls.size());
Map<String, List<URL>> urlsMap =
urls.stream().collect(Collectors.groupingBy(url -> url.getParameter(REGISTRY_KEY)));
Assertions.assertEquals(2, urlsMap.get("nacos").size());
for (URL url : urlsMap.get("nacos")) {
Assertions.assertTrue(url.getProtocol().contains("registry"));
Assertions.assertEquals("addr1:9090", url.getAddress());
Assertions.assertEquals("addr1:8848", url.getAddress());
Assertions.assertEquals(RegistryService.class.getName(), url.getPath());
Assertions.assertEquals(registryId + ":" + namespace1, url.getParameter(REGISTRY_CLUSTER_KEY));
Assertions.assertTrue(url.getParameters().containsKey("timestamp"));
Assertions.assertTrue(url.getParameters().containsKey("pid"));
Assertions.assertTrue(url.getParameters().containsKey("registry"));
Assertions.assertTrue(url.getParameters().containsKey("dubbo"));
}
Assertions.assertEquals(2, urlsMap.get("polaris").size());
for (URL url : urlsMap.get("polaris")) {
Assertions.assertTrue(url.getProtocol().contains("registry"));
Assertions.assertEquals("addr1:9999", url.getAddress());
Assertions.assertEquals(RegistryService.class.getName(), url.getPath());
Assertions.assertEquals(DEFAULT_KEY + ":" + namespace2, url.getParameter(REGISTRY_CLUSTER_KEY));
Assertions.assertTrue(url.getParameters().containsKey("timestamp"));
Assertions.assertTrue(url.getParameters().containsKey("pid"));
Assertions.assertTrue(url.getParameters().containsKey("registry"));
Assertions.assertTrue(url.getParameters().containsKey("dubbo"));
}
}
@Test
void testRegistryWithMetadataReport() {
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
List<RegistryConfig> registryConfigs = new ArrayList<>();
List<MetadataReportConfig> metadataReportConfigs = new ArrayList<>();
String registryId = "nacosRegistry";
String namespace1 = "test";
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(registryId);
registryConfig.setAddress(zkServerAddress);
Map<String, String> registryParamMap = Maps.newHashMap();
registryParamMap.put(CONFIG_NAMESPACE_KEY, namespace1);
registryConfig.setParameters(registryParamMap);
registryConfigs.add(registryConfig);
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
metadataReportConfig.setRegistry(registryId);
metadataReportConfig.setAddress(registryConfig.getAddress());
Map<String, String> metadataParamMap = Maps.newHashMap();
metadataParamMap.put(CONFIG_NAMESPACE_KEY, namespace1);
metadataParamMap.put(REPORT_CONSUMER_URL_KEY, Boolean.TRUE.toString());
metadataReportConfig.setParameters(metadataParamMap);
metadataReportConfig.setReportMetadata(true);
metadataReportConfigs.add(metadataReportConfig);
String namespace2 = "test2";
RegistryConfig registryConfig2 = new RegistryConfig();
registryConfig2.setAddress(zkServerAddress);
Map<String, String> registryParamMap2 = Maps.newHashMap();
registryParamMap2.put(CONFIG_NAMESPACE_KEY, namespace2);
registryConfig2.setParameters(registryParamMap2);
registryConfigs.add(registryConfig2);
MetadataReportConfig metadataReportConfig2 = new MetadataReportConfig();
metadataReportConfig2.setAddress(registryConfig2.getAddress());
Map<String, String> metadataParamMap2 = Maps.newHashMap();
metadataParamMap2.put(CONFIG_NAMESPACE_KEY, namespace2);
metadataParamMap2.put(REPORT_CONSUMER_URL_KEY, Boolean.TRUE.toString());
metadataReportConfig2.setParameters(metadataParamMap2);
metadataReportConfig2.setReportMetadata(true);
metadataReportConfigs.add(metadataReportConfig2);
serviceConfig.setRegistries(registryConfigs);
DubboBootstrap.getInstance()
.application(new ApplicationConfig("testRegistryWithMetadataReport"))
.registries(registryConfigs)
.metadataReports(metadataReportConfigs)
.service(serviceConfig)
.protocol(new ProtocolConfig(CommonConstants.DUBBO_PROTOCOL, -1))
.start();
ApplicationModel applicationModel = DubboBootstrap.getInstance().getApplicationModel();
MetadataReportInstance metadataReportInstance =
applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
Map<String, MetadataReport> metadataReports = metadataReportInstance.getMetadataReports(true);
Assertions.assertEquals(2, metadataReports.size());
List<URL> urls = ConfigValidationUtils.loadRegistries(serviceConfig, true);
Assertions.assertEquals(4, urls.size());
for (URL url : urls) {
Assertions.assertTrue(metadataReports.containsKey(url.getParameter(REGISTRY_CLUSTER_KEY)));
}
}
@Test

View File

@ -17,10 +17,13 @@
package org.apache.dubbo.config.deploy;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.constants.MetricsConstants.PROTOCOL_PROMETHEUS;
class DefaultApplicationDeployerTest {
@Test
@ -29,4 +32,13 @@ class DefaultApplicationDeployerTest {
new DefaultApplicationDeployer(ApplicationModel.defaultModel()).isSupportPrometheus();
Assert.assertTrue(supportPrometheus, "DefaultApplicationDeployer.isSupportPrometheus() should return true");
}
@Test
void isImportPrometheus() {
MetricsConfig metricsConfig = new MetricsConfig();
metricsConfig.setProtocol("prometheus");
boolean importPrometheus = PROTOCOL_PROMETHEUS.equals(metricsConfig.getProtocol())
&& !DefaultApplicationDeployer.isSupportPrometheus();
Assert.assertTrue(!importPrometheus, " should return false");
}
}

View File

@ -172,7 +172,6 @@ class MultipleRegistryCenterExportMetadataIntegrationTest implements Integration
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -239,7 +239,6 @@ class MultipleRegistryCenterExportProviderIntegrationTest implements Integration
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -185,7 +185,6 @@ class MultipleRegistryCenterInjvmIntegrationTest implements IntegrationTest {
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -201,7 +201,6 @@ class MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest implements I
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// TODO: we need to check whether this scenario is normal
// TODO: the Exporter and ServiceDiscoveryRegistry are same in multiple registry center

View File

@ -169,7 +169,6 @@ class SingleRegistryCenterExportMetadataIntegrationTest implements IntegrationTe
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -240,7 +240,6 @@ class SingleRegistryCenterExportProviderIntegrationTest implements IntegrationTe
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -185,7 +185,6 @@ class SingleRegistryCenterInjvmIntegrationTest implements IntegrationTest {
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
PROVIDER_APPLICATION_NAME = null;
serviceConfig = null;
// The exported service has been unexported
Assertions.assertTrue(serviceListener.getExportedServices().isEmpty());

View File

@ -35,6 +35,7 @@ class ReferenceCacheTest {
public void setUp() throws Exception {
DubboBootstrap.reset();
MockReferenceConfig.setCounter(0);
XxxMockReferenceConfig.setCounter(0);
SimpleReferenceCache.CACHE_HOLDER.clear();
}

View File

@ -74,7 +74,7 @@
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22</version>
<version>1.9.22.1</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -444,21 +444,11 @@ public abstract class AnnotationUtils {
(_k) -> ClassUtils.isPresent(ANNOTATED_ELEMENT_UTILS_CLASS_NAME, classLoader))) {
Class<?> annotatedElementUtilsClass = resolveClassName(ANNOTATED_ELEMENT_UTILS_CLASS_NAME, classLoader);
// getMergedAnnotation method appears in the Spring Framework 4.2
Method getMergedAnnotationMethod = findMethod(
annotatedElementUtilsClass,
"getMergedAnnotation",
AnnotatedElement.class,
Class.class,
boolean.class,
boolean.class);
Method getMergedAnnotationMethod =
findMethod(annotatedElementUtilsClass, "getMergedAnnotation", AnnotatedElement.class, Class.class);
if (getMergedAnnotationMethod != null) {
mergedAnnotation = (Annotation) invokeMethod(
getMergedAnnotationMethod,
null,
annotatedElement,
annotationType,
classValuesAsString,
nestedAnnotationsAsMap);
mergedAnnotation =
(Annotation) invokeMethod(getMergedAnnotationMethod, null, annotatedElement, annotationType);
}
}

View File

@ -184,7 +184,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.3</version>
<version>1.5.6</version>
<scope>compile</scope>
</dependency>
</dependencies>
@ -232,7 +232,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.10.1</version>
<version>0.10.2</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -181,7 +181,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.3</version>
<version>1.5.6</version>
<scope>compile</scope>
</dependency>
</dependencies>
@ -229,7 +229,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.10.1</version>
<version>0.10.2</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -37,7 +37,7 @@
<skip_maven_deploy>true</skip_maven_deploy>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-boot-maven-plugin.version>2.7.18</spring-boot-maven-plugin.version>
<micrometer-core.version>1.12.4</micrometer-core.version>
<micrometer-core.version>1.13.1</micrometer-core.version>
</properties>
<dependencyManagement>
<dependencies>

View File

@ -90,16 +90,16 @@
<properties>
<!-- Common libs -->
<!-- <spring_version>4.3.30.RELEASE</spring_version> -->
<spring_version>5.3.33</spring_version>
<spring_security_version>5.8.11</spring_security_version>
<spring_version>5.3.37</spring_version>
<spring_security_version>5.8.12</spring_security_version>
<javassist_version>3.30.2-GA</javassist_version>
<bytebuddy.version>1.14.13</bytebuddy.version>
<bytebuddy.version>1.14.17</bytebuddy.version>
<netty_version>3.2.10.Final</netty_version>
<netty4_version>4.1.108.Final</netty4_version>
<netty4_version>4.1.111.Final</netty4_version>
<httpclient_version>4.5.14</httpclient_version>
<httpcore_version>4.4.16</httpcore_version>
<fastjson_version>1.2.83</fastjson_version>
<fastjson2_version>2.0.48</fastjson2_version>
<fastjson2_version>2.0.51</fastjson2_version>
<zookeeper_version>3.7.0</zookeeper_version>
<curator_version>5.1.0</curator_version>
<curator_test_version>2.12.0</curator_test_version>
@ -109,7 +109,7 @@
<javax_annotation-api_version>1.3.2</javax_annotation-api_version>
<servlet_version>3.1.0</servlet_version>
<jetty_version>9.4.54.v20240208</jetty_version>
<validation_new_version>3.0.2</validation_new_version>
<validation_new_version>3.1.0</validation_new_version>
<validation_version>1.1.0.Final</validation_version>
<hibernate_validator_version>5.4.3.Final</hibernate_validator_version>
<hibernate_validator_new_version>7.0.5.Final</hibernate_validator_new_version>
@ -119,13 +119,13 @@
<snakeyaml_version>2.2</snakeyaml_version>
<commons_lang3_version>3.14.0</commons_lang3_version>
<envoy_api_version>0.1.35</envoy_api_version>
<micrometer.version>1.12.4</micrometer.version>
<micrometer.version>1.13.1</micrometer.version>
<micrometer-tracing.version>1.2.4</micrometer-tracing.version>
<micrometer-tracing.version>1.3.1</micrometer-tracing.version>
<t_digest.version>3.3</t_digest.version>
<prometheus_client.version>0.16.0</prometheus_client.version>
<reactive.version>1.0.4</reactive.version>
<reactor.version>3.6.4</reactor.version>
<reactor.version>3.6.7</reactor.version>
<rxjava.version>2.2.21</rxjava.version>
<okhttp_version>3.14.9</okhttp_version>
@ -134,43 +134,43 @@
<codehaus-jackson_version>1.9.13</codehaus-jackson_version>
<tomcat_embed_version>8.5.100</tomcat_embed_version>
<nacos_version>2.3.2</nacos_version>
<grpc.version>1.63.0</grpc.version>
<grpc.version>1.64.0</grpc.version>
<grpc_contrib_verdion>0.8.1</grpc_contrib_verdion>
<jprotoc_version>1.2.2</jprotoc_version>
<!-- Log libs -->
<slf4j_version>1.7.36</slf4j_version>
<jcl_version>1.3.1</jcl_version>
<jcl_version>1.3.2</jcl_version>
<log4j_version>1.2.17</log4j_version>
<logback_version>1.2.13</logback_version>
<!-- Fix the bug of log4j refer:https://github.com/apache/logging-log4j2/pull/608 -->
<log4j2_version>2.23.1</log4j2_version>
<commons_io_version>2.16.0</commons_io_version>
<commons_io_version>2.16.1</commons_io_version>
<embedded_redis_version>0.13.0</embedded_redis_version>
<embedded_redis_version>1.4.3</embedded_redis_version>
<!-- Alibaba -->
<alibaba_spring_context_support_version>1.0.11</alibaba_spring_context_support_version>
<jaxb_version>2.2.7</jaxb_version>
<activation_version>1.2.0</activation_version>
<test_container_version>1.19.7</test_container_version>
<test_container_version>1.19.8</test_container_version>
<hessian_lite_version>3.2.13</hessian_lite_version>
<swagger_version>1.6.14</swagger_version>
<snappy_java_version>1.1.10.5</snappy_java_version>
<bouncycastle-bcprov_version>1.70</bouncycastle-bcprov_version>
<metrics_version>2.0.6</metrics_version>
<gson_version>2.10.1</gson_version>
<jackson_version>2.17.0</jackson_version>
<gson_version>2.11.0</gson_version>
<jackson_version>2.17.1</jackson_version>
<mortbay_jetty_version>6.1.26</mortbay_jetty_version>
<portlet_version>2.0</portlet_version>
<maven_flatten_version>1.6.0</maven_flatten_version>
<commons_compress_version>1.26.1</commons_compress_version>
<commons_compress_version>1.26.2</commons_compress_version>
<spotless-maven-plugin.version>2.43.0</spotless-maven-plugin.version>
<spotless.action>check</spotless.action>
<dubbo-shared-resources.version>1.0.0</dubbo-shared-resources.version>
<palantirJavaFormat.version>2.38.0</palantirJavaFormat.version>
<revision>3.2.13-SNAPSHOT</revision>
<revision>3.2.15-SNAPSHOT</revision>
</properties>
<dependencyManagement>

View File

@ -31,7 +31,7 @@
<packaging>pom</packaging>
<properties>
<revision>3.2.13-SNAPSHOT</revision>
<revision>3.2.15-SNAPSHOT</revision>
<maven_flatten_version>1.6.0</maven_flatten_version>
<curator5_version>5.1.0</curator5_version>
<zookeeper_version>3.8.4</zookeeper_version>

View File

@ -31,7 +31,7 @@
<packaging>pom</packaging>
<properties>
<revision>3.2.13-SNAPSHOT</revision>
<revision>3.2.15-SNAPSHOT</revision>
<maven_flatten_version>1.6.0</maven_flatten_version>
<curator_version>4.3.0</curator_version>
<zookeeper_version>3.4.14</zookeeper_version>

View File

@ -33,27 +33,27 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.12.0</version>
<version>3.13.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-common-artifact-filters</artifactId>
<version>3.3.2</version>
<version>3.4.0</version>
</dependency>
<dependency>
@ -65,15 +65,19 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.0</version>
<version>2.16.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.10.2</version>
<version>3.13.1</version>
<configuration>
<goalPrefix>dubbo</goalPrefix>
</configuration>
<executions>
<execution>
<id>default-addPluginArtifactMetadata</id>

View File

@ -25,11 +25,12 @@ import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import org.apache.dubbo.rpc.service.Destroyable;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toSet;
import static java.util.stream.Stream.of;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
@ -88,7 +89,10 @@ public interface ServiceNameMapping extends Destroyable {
if (StringUtils.isBlank(content)) {
return emptySet();
}
return new TreeSet<>(Arrays.asList(content.split(COMMA_SEPARATOR)));
return new TreeSet<>(of(content.split(COMMA_SEPARATOR))
.map(String::trim)
.filter(StringUtils::isNotEmpty)
.collect(toSet()));
}
static Set<String> getMappingByUrl(URL consumerURL) {

View File

@ -54,7 +54,7 @@ import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT
*/
public class MetadataReportInstance implements Disposable {
private AtomicBoolean init = new AtomicBoolean(false);
private final AtomicBoolean initialized = new AtomicBoolean(false);
private String metadataType;
// mapping of registry id to metadata report instance, registry instances will use this mapping to find related
@ -69,7 +69,7 @@ public class MetadataReportInstance implements Disposable {
}
public void init(List<MetadataReportConfig> metadataReportConfigs) {
if (!init.compareAndSet(false, true)) {
if (!initialized.compareAndSet(false, true)) {
return;
}
@ -114,9 +114,10 @@ public class MetadataReportInstance implements Disposable {
}
private String getRelatedRegistryId(MetadataReportConfig config, URL url) {
String relatedRegistryId = isEmpty(config.getRegistry())
? (isEmpty(config.getId()) ? DEFAULT_KEY : config.getId())
: config.getRegistry();
String relatedRegistryId = config.getRegistry();
if (isEmpty(relatedRegistryId)) {
relatedRegistryId = DEFAULT_KEY;
}
String namespace = url.getParameter(NAMESPACE_KEY);
if (!StringUtils.isEmpty(namespace)) {
relatedRegistryId += ":" + namespace;
@ -144,15 +145,13 @@ public class MetadataReportInstance implements Disposable {
return metadataType;
}
public boolean inited() {
return init.get();
public boolean isInitialized() {
return initialized.get();
}
@Override
public void destroy() {
metadataReports.forEach((_k, reporter) -> {
reporter.destroy();
});
metadataReports.forEach((k, reporter) -> reporter.destroy());
metadataReports.clear();
}
}

View File

@ -29,6 +29,7 @@ import java.util.concurrent.locks.ReentrantLock;
import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_EXCEPTION;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROXY_FAILED_EXPORT_SERVICE;
import static org.apache.dubbo.metadata.MetadataConstants.NAMESPACE_KEY;
public abstract class AbstractMetadataReportFactory implements MetadataReportFactory {
@ -50,7 +51,7 @@ public abstract class AbstractMetadataReportFactory implements MetadataReportFac
@Override
public MetadataReport getMetadataReport(URL url) {
url = url.setPath(MetadataReport.class.getName()).removeParameters(EXPORT_KEY, REFER_KEY);
String key = toMetadataReportKey(url);
String key = url.toServiceString(NAMESPACE_KEY);
MetadataReport metadataReport = serviceStoreMap.get(key);
if (metadataReport != null) {
@ -88,10 +89,6 @@ public abstract class AbstractMetadataReportFactory implements MetadataReportFac
}
}
protected String toMetadataReportKey(URL url) {
return url.toServiceString();
}
@Override
public void destroy() {
lock.lock();

View File

@ -145,4 +145,26 @@ class AbstractMetadataReportFactoryTest {
MetadataReport metadataReport2 = metadataReportFactory.getMetadataReport(url2);
Assertions.assertNotEquals(metadataReport1, metadataReport2);
}
@Test
void testGetForSameNamespace() {
URL url1 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName()
+ ":4444/org.apache.dubbo.TestService1?version=1.0.0&application=vic&namespace=test");
URL url2 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName()
+ ":4444/org.apache.dubbo.TestService2?version=1.0.0&application=vic&namespace=test");
MetadataReport metadataReport1 = metadataReportFactory.getMetadataReport(url1);
MetadataReport metadataReport2 = metadataReportFactory.getMetadataReport(url2);
Assertions.assertEquals(metadataReport1, metadataReport2);
}
@Test
void testGetForDiffNamespace() {
URL url1 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName()
+ ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic&namespace=test");
URL url2 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName()
+ ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic&namespace=dev");
MetadataReport metadataReport1 = metadataReportFactory.getMetadataReport(url1);
MetadataReport metadataReport2 = metadataReportFactory.getMetadataReport(url2);
Assertions.assertNotEquals(metadataReport1, metadataReport2);
}
}

View File

@ -17,12 +17,9 @@
package org.apache.dubbo.metadata.store.nacos;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
import static org.apache.dubbo.metadata.MetadataConstants.NAMESPACE_KEY;
/**
* metadata report factory impl for nacos
*/
@ -31,15 +28,4 @@ public class NacosMetadataReportFactory extends AbstractMetadataReportFactory {
protected MetadataReport createMetadataReport(URL url) {
return new NacosMetadataReport(url);
}
@Override
protected String toMetadataReportKey(URL url) {
String namespace = url.getParameter(NAMESPACE_KEY);
if (!StringUtils.isEmpty(namespace)) {
return URL.valueOf(url.toServiceString())
.addParameter(NAMESPACE_KEY, namespace)
.toString();
}
return super.toMetadataReportKey(url);
}
}

View File

@ -30,12 +30,13 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException;
@ -46,6 +47,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.SYNC_REPORT_KEY;
import static redis.embedded.RedisServer.newRedisServer;
@DisabledOnOs(OS.WINDOWS)
class RedisMetadataReportTest {
private static final String REDIS_URL_TEMPLATE = "redis://%slocalhost:%d",
@ -69,7 +71,7 @@ class RedisMetadataReportTest {
redisServer = newRedisServer()
.port(redisPort)
// set maxheap to fix Windows error 0x70 while starting redis
.settingIf(SystemUtils.IS_OS_WINDOWS, "maxheap 128mb")
// .settingIf(SystemUtils.IS_OS_WINDOWS, "maxheap 128mb")
.settingIf(usesAuthentication, "requirepass " + REDIS_PASSWORD)
.build();
this.redisServer.start();
@ -250,7 +252,8 @@ class RedisMetadataReportTest {
if (e.getCause() instanceof JedisConnectionException
&& e.getCause().getCause() instanceof JedisDataException) {
Assertions.assertEquals(
"ERR invalid password", e.getCause().getCause().getMessage());
"WRONGPASS invalid username-password pair or user is disabled.",
e.getCause().getCause().getMessage());
} else {
Assertions.fail("no invalid password exception!");
}

View File

@ -18,8 +18,8 @@ package org.apache.dubbo.metrics.aggregate;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class TimeWindowAggregatorTest {
@Test

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.store.DataStore;
import org.apache.dubbo.common.store.DataStoreUpdateListener;
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
@ -42,11 +43,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION;
import static org.apache.dubbo.config.Constants.CLIENT_THREAD_POOL_NAME;
import static org.apache.dubbo.config.Constants.CLIENT_THREAD_POOL_PREFIX;
import static org.apache.dubbo.config.Constants.SERVER_THREAD_POOL_NAME;
import static org.apache.dubbo.config.Constants.SERVER_THREAD_POOL_PREFIX;
import static org.apache.dubbo.metrics.model.MetricsCategory.THREAD_POOL;
public class ThreadPoolMetricsSampler implements MetricsSampler {
public class ThreadPoolMetricsSampler implements MetricsSampler, DataStoreUpdateListener {
private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ThreadPoolMetricsSampler.class);
@ -61,14 +63,28 @@ public class ThreadPoolMetricsSampler implements MetricsSampler {
this.collector = collector;
}
@Override
public void onUpdate(String componentName, String key, Object value) {
if (EXECUTOR_SERVICE_COMPONENT_KEY.equals(componentName)) {
if (value instanceof ThreadPoolExecutor) {
addExecutors(SERVER_THREAD_POOL_PREFIX + key, (ThreadPoolExecutor) value);
}
} else if (CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY.equals(componentName)) {
if (value instanceof ThreadPoolExecutor) {
addExecutors(CLIENT_THREAD_POOL_PREFIX + key, (ThreadPoolExecutor) value);
}
}
}
public void addExecutors(String name, ExecutorService executorService) {
Optional.ofNullable(executorService)
.filter(Objects::nonNull)
.filter(e -> e instanceof ThreadPoolExecutor)
.map(e -> (ThreadPoolExecutor) e)
.ifPresent(threadPoolExecutor -> {
sampleThreadPoolExecutor.put(name, threadPoolExecutor);
samplesChanged.set(true);
if (sampleThreadPoolExecutor.put(name, threadPoolExecutor) == null) {
samplesChanged.set(true);
}
});
}
@ -152,18 +168,20 @@ public class ThreadPoolMetricsSampler implements MetricsSampler {
}
if (dataStore != null) {
dataStore.addListener(this);
Map<String, Object> executors = dataStore.get(EXECUTOR_SERVICE_COMPONENT_KEY);
for (Map.Entry<String, Object> entry : executors.entrySet()) {
ExecutorService executor = (ExecutorService) entry.getValue();
if (executor instanceof ThreadPoolExecutor) {
this.addExecutors(SERVER_THREAD_POOL_NAME + "-" + entry.getKey(), executor);
this.addExecutors(SERVER_THREAD_POOL_PREFIX + entry.getKey(), executor);
}
}
executors = dataStore.get(CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY);
for (Map.Entry<String, Object> entry : executors.entrySet()) {
ExecutorService executor = (ExecutorService) entry.getValue();
if (executor instanceof ThreadPoolExecutor) {
this.addExecutors(CLIENT_THREAD_POOL_NAME + "-" + entry.getKey(), executor);
this.addExecutors(CLIENT_THREAD_POOL_PREFIX + entry.getKey(), executor);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.collector.sample;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.store.DataStore;
import org.apache.dubbo.common.store.DataStoreUpdateListener;
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.model.ThreadPoolMetric;
@ -37,11 +38,13 @@ import java.util.concurrent.ThreadPoolExecutor;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SuppressWarnings("all")
@ -178,4 +181,32 @@ public class ThreadPoolMetricsSamplerTest {
serverExecutor.shutdown();
clientExecutor.shutdown();
}
@Test
void testDataSourceNotify() throws Exception {
ArgumentCaptor<DataStoreUpdateListener> captor = ArgumentCaptor.forClass(DataStoreUpdateListener.class);
when(scopeBeanFactory.getBean(FrameworkExecutorRepository.class)).thenReturn(frameworkExecutorRepository);
when(frameworkExecutorRepository.getSharedExecutor()).thenReturn(null);
sampler2.registryDefaultSampleThreadPoolExecutor();
Field f = ThreadPoolMetricsSampler.class.getDeclaredField("sampleThreadPoolExecutor");
f.setAccessible(true);
Map<String, ThreadPoolExecutor> executors = (Map<String, ThreadPoolExecutor>) f.get(sampler2);
Assertions.assertEquals(0, executors.size());
verify(dataStore).addListener(captor.capture());
Assertions.assertEquals(sampler2, captor.getValue());
ExecutorService executorService = Executors.newFixedThreadPool(5);
sampler2.onUpdate(EXECUTOR_SERVICE_COMPONENT_KEY, "20880", executorService);
executors = (Map<String, ThreadPoolExecutor>) f.get(sampler2);
Assertions.assertEquals(1, executors.size());
Assertions.assertTrue(executors.containsKey("DubboServerHandler-20880"));
sampler2.onUpdate(CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY, "client", executorService);
Assertions.assertEquals(2, executors.size());
Assertions.assertTrue(executors.containsKey("DubboClientHandler-client"));
}
}

View File

@ -43,7 +43,7 @@
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<artifactId>micrometer-registry-prometheus-simpleclient</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>

View File

@ -51,6 +51,7 @@ class PrometheusMetricsReporterTest {
private MetricsConfig metricsConfig;
private ApplicationModel applicationModel;
private FrameworkModel frameworkModel;
HttpServer prometheusExporterHttpServer;
@BeforeEach
public void setup() {
@ -64,6 +65,9 @@ class PrometheusMetricsReporterTest {
@AfterEach
public void teardown() {
applicationModel.destroy();
if (prometheusExporterHttpServer != null) {
prometheusExporterHttpServer.stop(0);
}
}
@Test
@ -146,7 +150,7 @@ class PrometheusMetricsReporterTest {
private void exportHttpServer(PrometheusMetricsReporter reporter, int port) {
try {
HttpServer prometheusExporterHttpServer = HttpServer.create(new InetSocketAddress(port), 0);
prometheusExporterHttpServer = HttpServer.create(new InetSocketAddress(port), 0);
prometheusExporterHttpServer.createContext("/metrics", httpExchange -> {
reporter.resetIfSamplesChanged();
String response = reporter.getPrometheusRegistry().scrape();

View File

@ -62,6 +62,8 @@ public class PrometheusMetricsThreadPoolTest {
DefaultMetricsCollector metricsCollector;
HttpServer prometheusExporterHttpServer;
@BeforeEach
public void setup() {
applicationModel = ApplicationModel.defaultModel();
@ -77,6 +79,9 @@ public class PrometheusMetricsThreadPoolTest {
@AfterEach
public void teardown() {
applicationModel.destroy();
if (prometheusExporterHttpServer != null) {
prometheusExporterHttpServer.stop(0);
}
}
@Test
@ -121,7 +126,7 @@ public class PrometheusMetricsThreadPoolTest {
private void exportHttpServer(PrometheusMetricsReporter reporter, int port) {
try {
HttpServer prometheusExporterHttpServer = HttpServer.create(new InetSocketAddress(port), 0);
prometheusExporterHttpServer = HttpServer.create(new InetSocketAddress(port), 0);
prometheusExporterHttpServer.createContext("/metrics", httpExchange -> {
reporter.resetIfSamplesChanged();
String response = reporter.getPrometheusRegistry().scrape();

View File

@ -30,6 +30,8 @@ import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@ -139,7 +141,13 @@ class DubboMonitorTest {
}
@Test
void testMonitorFactory() {
void testMonitorFactory() throws IOException {
int port;
try (ServerSocket socket = new ServerSocket(0)) {
port = socket.getLocalPort();
socket.close();
}
MockMonitorService monitorService = new MockMonitorService();
URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.10", 0)
.addParameter(APPLICATION_KEY, "morgan")
@ -163,12 +171,12 @@ class DubboMonitorTest {
Exporter<MonitorService> exporter = protocol.export(proxyFactory.getInvoker(
monitorService,
MonitorService.class,
URL.valueOf("dubbo://127.0.0.1:17979/" + MonitorService.class.getName())));
URL.valueOf("dubbo://127.0.0.1:" + port + "/" + MonitorService.class.getName())));
try {
Monitor monitor = null;
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 60000) {
monitor = monitorFactory.getMonitor(URL.valueOf("dubbo://127.0.0.1:17979?interval=10"));
monitor = monitorFactory.getMonitor(URL.valueOf("dubbo://127.0.0.1:" + port + "?interval=10"));
if (monitor == null) {
continue;
}

View File

@ -35,20 +35,20 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.12.0</version>
<version>3.13.1</version>
<scope>provided</scope>
</dependency>
@ -61,7 +61,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.0</version>
<version>2.16.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
@ -75,8 +75,12 @@
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.10.2</version>
<version>3.13.1</version>
<configuration>
<goalPrefix>dubbo</goalPrefix>
</configuration>
<executions>
<execution>
<id>default-addPluginArtifactMetadata</id>

View File

@ -35,6 +35,7 @@ class LiveTest {
@AfterEach
public void reset() {
frameworkModel.destroy();
MockLivenessProbe.setCheckReturnValue(false);
}
@Test

View File

@ -53,7 +53,7 @@ public abstract class AbstractTripleReactorSubscriber<T> implements Subscriber<T
if (downstream == null) {
throw new NullPointerException();
}
if (this.downstream == null && SUBSCRIBED.compareAndSet(false, true)) {
if (SUBSCRIBED.compareAndSet(false, true)) {
this.downstream = downstream;
subscription.request(1);
}

View File

@ -20,11 +20,31 @@ import org.apache.dubbo.rpc.CancellationContext;
import org.apache.dubbo.rpc.protocol.tri.CancelableStreamObserver;
import org.apache.dubbo.rpc.protocol.tri.observer.CallStreamObserver;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* The Subscriber in server to passing the data produced by user publisher to responseStream.
*/
public class ServerTripleReactorSubscriber<T> extends AbstractTripleReactorSubscriber<T> {
/**
* The execution future of the current task, in order to be returned to stubInvoker
*/
private final CompletableFuture<List<T>> executionFuture = new CompletableFuture<>();
/**
* The result elements collected by the current task.
* This class is a flux subscriber, which usually means there will be multiple elements, so it is declared as a list type.
*/
private final List<T> collectedData = new ArrayList<>();
public ServerTripleReactorSubscriber() {}
public ServerTripleReactorSubscriber(CallStreamObserver<T> streamObserver) {
this.downstream = streamObserver;
}
@Override
public void subscribe(CallStreamObserver<T> downstream) {
super.subscribe(downstream);
@ -40,4 +60,26 @@ public class ServerTripleReactorSubscriber<T> extends AbstractTripleReactorSubsc
context.addListener(ctx -> super.cancel());
}
}
@Override
public void onNext(T t) {
super.onNext(t);
collectedData.add(t);
}
@Override
public void onError(Throwable throwable) {
super.onError(throwable);
executionFuture.completeExceptionally(throwable);
}
@Override
public void onComplete() {
super.onComplete();
executionFuture.complete(this.collectedData);
}
public CompletableFuture<List<T>> getExecutionFuture() {
return executionFuture;
}
}

View File

@ -19,9 +19,12 @@ package org.apache.dubbo.reactive.calls;
import org.apache.dubbo.common.stream.StreamObserver;
import org.apache.dubbo.reactive.ServerTripleReactorPublisher;
import org.apache.dubbo.reactive.ServerTripleReactorSubscriber;
import org.apache.dubbo.rpc.StatusRpcException;
import org.apache.dubbo.rpc.TriRpcStatus;
import org.apache.dubbo.rpc.protocol.tri.observer.CallStreamObserver;
import org.apache.dubbo.rpc.protocol.tri.observer.ServerCallToObserverAdapter;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
@ -43,16 +46,16 @@ public final class ReactorServerCalls {
* @param func service implementation
*/
public static <T, R> void oneToOne(T request, StreamObserver<R> responseObserver, Function<Mono<T>, Mono<R>> func) {
func.apply(Mono.just(request)).subscribe(res -> {
CompletableFuture.completedFuture(res).whenComplete((r, t) -> {
if (t != null) {
responseObserver.onError(t);
} else {
responseObserver.onNext(r);
responseObserver.onCompleted();
}
});
});
try {
func.apply(Mono.just(request))
.switchIfEmpty(Mono.error(TriRpcStatus.NOT_FOUND.asException()))
.subscribe(
responseObserver::onNext,
throwable -> doOnResponseHasException(throwable, responseObserver),
responseObserver::onCompleted);
} catch (Throwable throwable) {
doOnResponseHasException(throwable, responseObserver);
}
}
/**
@ -62,14 +65,21 @@ public final class ReactorServerCalls {
* @param responseObserver response StreamObserver
* @param func service implementation
*/
public static <T, R> void oneToMany(
public static <T, R> CompletableFuture<List<R>> oneToMany(
T request, StreamObserver<R> responseObserver, Function<Mono<T>, Flux<R>> func) {
try {
ServerCallToObserverAdapter<R> serverCallToObserverAdapter =
(ServerCallToObserverAdapter<R>) responseObserver;
Flux<R> response = func.apply(Mono.just(request));
ServerTripleReactorSubscriber<R> subscriber = response.subscribeWith(new ServerTripleReactorSubscriber<>());
subscriber.subscribe((ServerCallToObserverAdapter<R>) responseObserver);
ServerTripleReactorSubscriber<R> reactorSubscriber =
new ServerTripleReactorSubscriber<>(serverCallToObserverAdapter);
response.subscribeWith(reactorSubscriber).subscribe(serverCallToObserverAdapter);
return reactorSubscriber.getExecutionFuture();
} catch (Throwable throwable) {
responseObserver.onError(throwable);
doOnResponseHasException(throwable, responseObserver);
CompletableFuture<List<R>> future = new CompletableFuture<>();
future.completeExceptionally(throwable);
return future;
}
}
@ -131,4 +141,10 @@ public final class ReactorServerCalls {
return serverPublisher;
}
private static void doOnResponseHasException(Throwable throwable, StreamObserver<?> responseObserver) {
StatusRpcException statusRpcException =
TriRpcStatus.getStatus(throwable).asException();
responseObserver.onError(statusRpcException);
}
}

View File

@ -42,7 +42,6 @@ public class OneToManyMethodHandler<T, R> implements StubMethodHandler<T, R> {
public CompletableFuture<?> invoke(Object[] arguments) {
T request = (T) arguments[0];
StreamObserver<R> responseObserver = (StreamObserver<R>) arguments[1];
ReactorServerCalls.oneToMany(request, responseObserver, func);
return CompletableFuture.completedFuture(null);
return ReactorServerCalls.oneToMany(request, responseObserver, func);
}
}

View File

@ -84,7 +84,7 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
this(applicationModel, applicationModel.getApplicationName(), registryURL);
MetadataReportInstance metadataReportInstance =
applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
metadataType = metadataReportInstance.getMetadataType();
this.metadataType = metadataReportInstance.getMetadataType();
this.metadataReport = metadataReportInstance.getMetadataReport(registryURL.getParameter(REGISTRY_CLUSTER_KEY));
}

View File

@ -109,7 +109,7 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
String[] oldAppNames = oldConfigContent.split(",");
if (oldAppNames.length > 0) {
for (String oldAppName : oldAppNames) {
if (oldAppName.equals(appName)) {
if (StringUtils.trim(oldAppName).equals(appName)) {
succeeded = true;
break;
}

View File

@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@ -71,6 +72,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGO
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_ENABLE_EMPTY_PROTECTION;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.ENABLE_EMPTY_PROTECTION_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.NACOE_REGISTER_COMPATIBLE;
import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_CONSUMER_URL_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY;
@ -107,9 +109,8 @@ public class NacosRegistry extends FailbackRegistry {
private static final String UP = "UP";
/**
* The separator for service name
* Change a constant to be configurable, it's designed for Windows file name that is compatible with old
* Nacos binary release(< 0.6.1)
* The separator for service name Change a constant to be configurable, it's designed for Windows file name that is
* compatible with old Nacos binary release(< 0.6.1)
*/
private static final String SERVICE_NAME_SEPARATOR = System.getProperty("nacos.service.name.separator", ":");
@ -174,18 +175,33 @@ public class NacosRegistry extends FailbackRegistry {
public void doRegister(URL url) {
try {
if (PROVIDER_SIDE.equals(url.getSide()) || getUrl().getParameter(REGISTER_CONSUMER_URL_KEY, false)) {
String serviceName = getServiceName(url);
Instance instance = createInstance(url);
Set<String> serviceNames = new HashSet<>();
// by default servicename is "org.apache.dubbo.xxService:1.0.0:"
String serviceName = getServiceName(url, false);
serviceNames.add(serviceName);
// in https://github.com/apache/dubbo/issues/14075
if (getUrl().getParameter(NACOE_REGISTER_COMPATIBLE, false)) {
// servicename is "org.apache.dubbo.xxService:1.0.0"
String compatibleServiceName = getServiceName(url, true);
serviceNames.add(compatibleServiceName);
}
/**
* namingService.registerInstance with {@link org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
* namingService.registerInstance with
* {@link org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
* default {@link DEFAULT_GROUP}
*
* in https://github.com/apache/dubbo/issues/5978
*/
namingService.registerInstance(serviceName, getUrl().getGroup(Constants.DEFAULT_GROUP), instance);
for (String service : serviceNames) {
namingService.registerInstance(service, getUrl().getGroup(Constants.DEFAULT_GROUP), instance);
}
} else {
logger.info(
"Please set 'dubbo.registry.parameters.register-consumer-url=true' to turn on consumer url registration.");
logger.info("Please set 'dubbo.registry.parameters.register-consumer-url=true' to turn on consumer "
+ "url registration.");
}
} catch (SkipFailbackWrapperException exception) {
throw exception;
@ -198,10 +214,24 @@ public class NacosRegistry extends FailbackRegistry {
@Override
public void doUnregister(final URL url) {
try {
String serviceName = getServiceName(url);
Instance instance = createInstance(url);
namingService.deregisterInstance(
serviceName, getUrl().getGroup(Constants.DEFAULT_GROUP), instance.getIp(), instance.getPort());
Set<String> serviceNames = new HashSet<>();
// by default servicename is "org.apache.dubbo.xxService:1.0.0:"
String serviceName = getServiceName(url, false);
serviceNames.add(serviceName);
// in https://github.com/apache/dubbo/issues/14075
if (getUrl().getParameter(NACOE_REGISTER_COMPATIBLE, false)) {
// servicename is "org.apache.dubbo.xxService:1.0.0"
String serviceName1 = getServiceName(url, true);
serviceNames.add(serviceName1);
}
for (String service : serviceNames) {
namingService.deregisterInstance(
service, getUrl().getGroup(Constants.DEFAULT_GROUP), instance.getIp(), instance.getPort());
}
} catch (SkipFailbackWrapperException exception) {
throw exception;
} catch (Exception cause) {
@ -230,7 +260,8 @@ public class NacosRegistry extends FailbackRegistry {
* Get all instances with serviceNames to avoid instance overwrite and but with empty instance mentioned
* in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899
*
* namingService.getAllInstances with {@link org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
* namingService.getAllInstances with
* {@link org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
* default {@link DEFAULT_GROUP}
*
* in https://github.com/apache/dubbo/issues/5978
@ -268,8 +299,8 @@ public class NacosRegistry extends FailbackRegistry {
}
/**
* Since 2.7.6 the legacy service name will be added to serviceNames
* to fix bug with https://github.com/apache/dubbo/issues/5442
* Since 2.7.6 the legacy service name will be added to serviceNames to fix bug with
* https://github.com/apache/dubbo/issues/5442
*
* @param url
* @return
@ -290,7 +321,8 @@ public class NacosRegistry extends FailbackRegistry {
"",
"",
String.format(
"No aggregate listener found for url %s, this service might have already been unsubscribed.",
"No aggregate listener found for url %s, "
+ "this service might have already been unsubscribed.",
url));
return;
}
@ -581,7 +613,8 @@ public class NacosRegistry extends FailbackRegistry {
REGISTRY_NACOS_EXCEPTION,
"",
"",
"Received empty url address list and empty protection is disabled, will clear current available addresses");
"Received empty url address list and empty protection is "
+ "disabled, will clear current available addresses");
URL empty = URLBuilder.from(consumerURL)
.setProtocol(EMPTY_PROTOCOL)
.addParameter(CATEGORY_KEY, DEFAULT_CATEGORY)
@ -697,7 +730,10 @@ public class NacosRegistry extends FailbackRegistry {
return valueOf(url);
}
private String getServiceName(URL url) {
private String getServiceName(URL url, boolean needCompatible) {
if (needCompatible) {
return getCompatibleServiceName(url, url.getCategory(DEFAULT_CATEGORY));
}
return getServiceName(url, url.getCategory(DEFAULT_CATEGORY));
}
@ -705,6 +741,10 @@ public class NacosRegistry extends FailbackRegistry {
return category + SERVICE_NAME_SEPARATOR + url.getColonSeparatedKey();
}
private String getCompatibleServiceName(URL url, String category) {
return category + SERVICE_NAME_SEPARATOR + url.getCompatibleColonSeparatedKey();
}
private void filterEnabledInstances(Collection<Instance> instances) {
filterData(instances, Instance::isEnabled);
}

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.JsonUtils;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.support.CacheableFailbackRegistry;
@ -46,6 +47,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_DESERIALIZE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_ZOOKEEPER_EXCEPTION;
import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY;
@ -201,7 +203,15 @@ public class ZookeeperRegistry extends CacheableFailbackRegistry {
ChildListener zkListener = ConcurrentHashMapUtils.computeIfAbsent(
listeners, listener, k -> (parentPath, currentChildren) -> {
for (String child : currentChildren) {
child = URL.decode(child);
try {
child = URL.decode(child);
if (!(JsonUtils.checkJson(child))) {
throw new Exception("dubbo-admin subscribe " + child + " failed,beacause "
+ child + "is root path in " + url);
}
} catch (Exception e) {
logger.warn(PROTOCOL_ERROR_DESERIALIZE, "", "", e.getMessage());
}
if (!anyServices.contains(child)) {
anyServices.add(child);
subscribe(

View File

@ -43,6 +43,7 @@ import org.apache.zookeeper.data.ACL;
import static org.apache.curator.x.discovery.ServiceInstance.builder;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.ZOOKEEPER_ENSEMBLE_TRACKER_KEY;
import static org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery.DEFAULT_GROUP;
import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkParams.BASE_SLEEP_TIME;
import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkParams.BLOCK_UNTIL_CONNECTED_UNIT;
@ -69,8 +70,10 @@ public abstract class CuratorFrameworkUtils {
public static CuratorFramework buildCuratorFramework(URL connectionURL, ZookeeperServiceDiscovery serviceDiscovery)
throws Exception {
boolean ensembleTracker = connectionURL.getParameter(ZOOKEEPER_ENSEMBLE_TRACKER_KEY, true);
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(connectionURL.getBackupAddress())
.ensembleTracker(ensembleTracker)
.retryPolicy(buildRetryPolicy(connectionURL));
String userInformation = connectionURL.getUserInformation();
if (StringUtils.isNotEmpty(userInformation)) {

View File

@ -40,6 +40,7 @@ public abstract class AbstractZookeeperClient<TargetDataListener, TargetChildLis
// may hang up to wait name resolution up to 10s
protected int DEFAULT_CONNECTION_TIMEOUT_MS = 30 * 1000;
protected int DEFAULT_SESSION_TIMEOUT_MS = 60 * 1000;
protected boolean DEFAULT_ENSEMBLE_TRACKER = true;
private final URL url;

View File

@ -24,12 +24,18 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
class ChannelHandlerDispatcherTest {
@AfterEach
public void tearDown() {
MockChannelHandler.reset();
}
@Test
void test() {
ChannelHandlerDispatcher channelHandlerDispatcher = new ChannelHandlerDispatcher();
@ -138,4 +144,12 @@ class MockChannelHandler extends ChannelHandlerAdapter {
public static int getCaughtCount() {
return caughtCount;
}
public static void reset() {
sentCount = 0;
connectedCount = 0;
disconnectedCount = 0;
receivedCount = 0;
caughtCount = 0;
}
}

View File

@ -22,6 +22,10 @@ public class HttpClientConfig {
private int connectTimeout = 6 * 1000;
private int chunkLength = 8196;
private int maxIdleConnections = 20;
private int keepAliveDuration = 30 * 1000;
private int HTTP_CLIENT_CONNECTION_MANAGER_MAX_PER_ROUTE = 20;
private int HTTP_CLIENT_CONNECTION_MANAGER_MAX_TOTAL = 20;
private int HTTPCLIENT_KEEP_ALIVE_DURATION = 30 * 1000;
@ -57,4 +61,24 @@ public class HttpClientConfig {
public int getChunkLength() {
return chunkLength;
}
public int getMaxIdleConnections() {
return maxIdleConnections;
}
public void setMaxIdleConnections(int maxIdleConnections) {
this.maxIdleConnections = maxIdleConnections;
}
public int getKeepAliveDuration() {
return keepAliveDuration;
}
public void setKeepAliveDuration(int keepAliveDuration) {
this.keepAliveDuration = keepAliveDuration;
}
}

View File

@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
@ -140,11 +141,15 @@ public class OKHttpRestClient implements RestClient {
}
public OkHttpClient createHttpClient(HttpClientConfig httpClientConfig) {
OkHttpClient client = new OkHttpClient.Builder()
return new OkHttpClient.Builder()
.readTimeout(httpClientConfig.getReadTimeout(), TimeUnit.SECONDS)
.writeTimeout(httpClientConfig.getWriteTimeout(), TimeUnit.SECONDS)
.connectTimeout(httpClientConfig.getConnectTimeout(), TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(
httpClientConfig.getMaxIdleConnections(),
httpClientConfig.getKeepAliveDuration(),
TimeUnit.SECONDS))
.build();
return client;
}
}

View File

@ -236,6 +236,13 @@ public class NettyConnectionClient extends AbstractConnectionClient {
}
return;
}
// Close the existing channel before setting a new channel
final io.netty.channel.Channel current = getNettyChannel();
if (current != null) {
current.close();
}
this.channel.set(nettyChannel);
// This indicates that the connection is available.
if (this.connectingPromise.get() != null) {
@ -254,6 +261,10 @@ public class NettyConnectionClient extends AbstractConnectionClient {
}
io.netty.channel.Channel nettyChannel = (io.netty.channel.Channel) channel;
if (this.channel.compareAndSet(nettyChannel, null)) {
// Ensure the channel is closed
if (nettyChannel.isOpen()) {
nettyChannel.close();
}
NettyChannel.removeChannelIfDisconnected(nettyChannel);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("%s goaway", this));

View File

@ -55,6 +55,7 @@ import org.apache.zookeeper.data.Stat;
import static org.apache.dubbo.common.constants.CommonConstants.SESSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ZOOKEEPER_ENSEMBLE_TRACKER_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_CONNECT_REGISTRY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_ZOOKEEPER_EXCEPTION;
@ -74,10 +75,12 @@ public class Curator5ZookeeperClient
try {
int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS);
int sessionExpireMs = url.getParameter(SESSION_KEY, DEFAULT_SESSION_TIMEOUT_MS);
boolean ensembleTracker = url.getParameter(ZOOKEEPER_ENSEMBLE_TRACKER_KEY, DEFAULT_ENSEMBLE_TRACKER);
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(url.getBackupAddress())
.retryPolicy(new RetryNTimes(1, 1000))
.connectionTimeoutMs(timeout)
.ensembleTracker(ensembleTracker)
.sessionTimeoutMs(sessionExpireMs);
String userInformation = url.getUserInformation();
if (userInformation != null && userInformation.length() > 0) {

View File

@ -108,7 +108,7 @@ public class AccessLogFilter implements Filter {
public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
String accessLogKey = invoker.getUrl().getParameter(Constants.ACCESS_LOG_KEY);
boolean isFixedPath = invoker.getUrl().getParameter(ACCESS_LOG_FIXED_PATH_KEY, true);
if (StringUtils.isEmpty(accessLogKey)) {
if (StringUtils.isEmpty(accessLogKey) || "false".equalsIgnoreCase(accessLogKey)) {
// Notice that disable accesslog of one service may cause the whole application to stop collecting
// accesslog.
// It's recommended to use application level configuration to enable or disable accesslog if dynamically

View File

@ -317,7 +317,7 @@ public class RpcUtils {
timeout = Long.parseLong((String) obj);
} else if (obj instanceof Number) {
timeout = ((Number) obj).longValue();
} else {
} else if (obj != null) {
timeout = Long.parseLong(obj.toString());
}
} catch (Exception e) {

View File

@ -39,6 +39,10 @@ class RpcStatusTest {
URL url = new ServiceConfigURL("dubbo", "127.0.0.1", 91031, DemoService.class.getName());
String methodName = "testBeginCountEndCount";
int max = 2;
RpcStatus.removeStatus(url);
RpcStatus.removeStatus(url, methodName);
boolean flag = RpcStatus.beginCount(url, methodName, max);
RpcStatus urlRpcStatus = RpcStatus.getStatus(url);
RpcStatus methodRpcStatus = RpcStatus.getStatus(url, methodName);
@ -65,6 +69,10 @@ class RpcStatusTest {
void testBeginCountEndCountInMultiThread() throws Exception {
URL url = new ServiceConfigURL("dubbo", "127.0.0.1", 91032, DemoService.class.getName());
String methodName = "testBeginCountEndCountInMultiThread";
RpcStatus.removeStatus(url);
RpcStatus.removeStatus(url, methodName);
int max = 50;
int threadNum = 10;
AtomicInteger successCount = new AtomicInteger();
@ -99,6 +107,10 @@ class RpcStatusTest {
URL url = new ServiceConfigURL("dubbo", "127.0.0.1", 91033, DemoService.class.getName());
String methodName = "testStatistics";
int max = 0;
RpcStatus.removeStatus(url);
RpcStatus.removeStatus(url, methodName);
RpcStatus.beginCount(url, methodName, max);
RpcStatus.beginCount(url, methodName, max);
RpcStatus.beginCount(url, methodName, max);

View File

@ -36,6 +36,7 @@ import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.rpc.model.MethodDescriptor;
import org.apache.dubbo.rpc.model.ServiceModel;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
@ -317,11 +318,18 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
}
Object value = originValue;
ClassLoader cl = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
ServiceModel consumerServiceModel = getUrl().getServiceModel();
if (consumerServiceModel != null) {
Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader());
// 1. By default, the classloader of the current Thread is the consumer class loader.
ClassLoader consumerClassLoader = contextClassLoader;
ServiceModel serviceModel = getUrl().getServiceModel();
// 2. If there is a ConsumerModel in the url, the classloader of the ConsumerModel is consumerLoader
if (Objects.nonNull(serviceModel) && serviceModel instanceof ConsumerModel) {
consumerClassLoader = serviceModel.getClassLoader();
}
// 3. request result copy
if (Objects.nonNull(consumerClassLoader)) {
Thread.currentThread().setContextClassLoader(consumerClassLoader);
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
if (returnTypes == null) {
return originValue;
@ -334,7 +342,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
}
return value;
} finally {
Thread.currentThread().setContextClassLoader(cl);
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}

View File

@ -57,7 +57,6 @@ public class ProviderParseContext extends BaseParseContext {
public String getPathVariable(int urlSplitIndex) {
String[] split = getRequestFacade().getRequestURI().split("/");
return split[urlSplitIndex];
return split[urlSplitIndex].split("\\?")[0];
}
}

View File

@ -51,7 +51,7 @@ import static org.springframework.beans.factory.config.ConfigurableBeanFactory.S
* @see DubboRelaxedBindingAutoConfiguration
* @since 2.7.0
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
@AutoConfigureBefore(DubboRelaxedBindingAutoConfiguration.class)

View File

@ -62,7 +62,7 @@ public class DubboAutoConfiguration {
@ConditionalOnProperty(prefix = DUBBO_SCAN_PREFIX, name = BASE_PACKAGES_PROPERTY_NAME)
@ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME)
@Bean
public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(
public static ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(
@Qualifier(BASE_PACKAGES_BEAN_NAME) Set<String> packagesToScan) {
return new ServiceAnnotationPostProcessor(packagesToScan);
}

View File

@ -42,7 +42,7 @@
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<artifactId>micrometer-registry-prometheus-simpleclient</artifactId>
</dependency>
<dependency>
<groupId>com.tdunning</groupId>

View File

@ -25,11 +25,11 @@ import java.util.zip.GZIPOutputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.util.unit.DataSize;
import zipkin2.Call;
import zipkin2.CheckResult;
import zipkin2.codec.Encoding;
import zipkin2.reporter.BytesMessageEncoder;
import zipkin2.reporter.Call;
import zipkin2.reporter.CheckResult;
import zipkin2.reporter.ClosedSenderException;
import zipkin2.reporter.Encoding;
import zipkin2.reporter.Sender;
/**

View File

@ -134,7 +134,7 @@ class ZipkinConfigurations {
@ConditionalOnMissingBean
@ConditionalOnBean(Sender.class)
AsyncReporter<Span> spanReporter(Sender sender, BytesEncoder<Span> encoder) {
return AsyncReporter.builder(sender).build(encoder);
return AsyncReporter.builder(sender).build((zipkin2.reporter.BytesEncoder<Span>) encoder);
}
}

View File

@ -19,8 +19,8 @@ package org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;
import zipkin2.Call;
import zipkin2.Callback;
import zipkin2.reporter.Call;
import zipkin2.reporter.Callback;
class ZipkinRestTemplateSender extends HttpSender {
private final String endpoint;

View File

@ -20,8 +20,8 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import zipkin2.Call;
import zipkin2.Callback;
import zipkin2.reporter.Call;
import zipkin2.reporter.Callback;
class ZipkinWebClientSender extends HttpSender {
private final String endpoint;

View File

@ -36,10 +36,10 @@
</modules>
<properties>
<micrometer.version>1.12.4</micrometer.version>
<micrometer-tracing.version>1.2.4</micrometer-tracing.version>
<opentelemetry.version>1.34.1</opentelemetry.version>
<zipkin-reporter.version>2.17.2</zipkin-reporter.version>
<micrometer.version>1.13.1</micrometer.version>
<micrometer-tracing.version>1.3.1</micrometer-tracing.version>
<opentelemetry.version>1.39.0</opentelemetry.version>
<zipkin-reporter.version>3.4.0</zipkin-reporter.version>
<prometheus-client.version>0.16.0</prometheus-client.version>
</properties>

View File

@ -43,7 +43,7 @@
<!-- Fix the bug of log4j refer:https://github.com/apache/logging-log4j2/pull/608 -->
<log4j2_version>2.23.1</log4j2_version>
<!-- Spring boot buddy is lower than the delivery dependency package version and can only show the defined dependency version -->
<byte-buddy.version>1.14.13</byte-buddy.version>
<byte-buddy.version>1.14.17</byte-buddy.version>
</properties>
<dependencyManagement>

View File

@ -33,7 +33,7 @@
<curator.test.version>4.2.0</curator.test.version>
<zookeeper.version>3.7.2</zookeeper.version>
<curator5.version>4.2.0</curator5.version>
<commons.compress.version>1.26.1</commons.compress.version>
<commons.compress.version>1.26.2</commons.compress.version>
<junit.platform.launcher.version>1.9.3</junit.platform.launcher.version>
<commons.exec.version>1.4.0</commons.exec.version>
<async.http.client.version>2.12.3</async.http.client.version>

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.dependency;
import org.apache.dubbo.common.constants.CommonConstants;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@ -133,7 +135,7 @@ class FileTest {
List<String> artifactIdsInRoot = IOUtils.readLines(
this.getClass()
.getClassLoader()
.getResource("META-INF/versions/.artifacts")
.getResource(CommonConstants.DUBBO_VERSIONS_KEY + "/.artifacts")
.openStream(),
StandardCharsets.UTF_8);
artifactIdsInRoot.removeIf(s -> s.startsWith("#"));

View File

@ -29,7 +29,7 @@
<properties>
<skip_maven_deploy>true</skip_maven_deploy>
<slf4j-log4j12.version>1.7.33</slf4j-log4j12.version>
<spring_version>5.3.33</spring_version>
<spring_version>5.3.37</spring_version>
<!--<spring_version>4.0.9.RELEASE</spring_version>-->
<!--<spring_version>4.1.9.RELEASE</spring_version>-->
<!--<spring_version>4.2.4.RELEASE</spring_version>-->

View File

@ -28,7 +28,7 @@
<properties>
<skip_maven_deploy>true</skip_maven_deploy>
<spring_version>5.3.33</spring_version>
<spring_version>5.3.37</spring_version>
</properties>
<dependencyManagement>

View File

@ -28,7 +28,7 @@
<properties>
<skip_maven_deploy>true</skip_maven_deploy>
<spring_version>5.3.33</spring_version>
<spring_version>5.3.37</spring_version>
</properties>
<dependencyManagement>

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