Merge branch 'apache-3.2' into apache-3.3

# Conflicts:
#	dubbo-dependencies-bom/pom.xml
#	dubbo-spring-boot/pom.xml
This commit is contained in:
Albumen Kevin 2024-03-05 09:47:49 +08:00
commit 76390eed4e
38 changed files with 628 additions and 230 deletions

126
.github/ISSUE_TEMPLATE/1-bug.yml vendored Normal file
View File

@ -0,0 +1,126 @@
#
# 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.
#
name: Bug Report
description: File a bug report
title: "[Bug] "
labels: ["status/need-triage"]
projects: ["apache/337"]
body:
- type: markdown
attributes:
value: |
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
Thank you for finding the time to report the problem! We really appreciate the community efforts to improve Dubbo.
Please make sure what you are reporting is indeed a bug with reproducible steps, if you want to ask questions
or share ideas, please [subscribe to our mailing list](mailto:dev-subscribe@dubbo.apache.org) and sent
emails to [our mailing list](mailto:dev@dubbo.apache.org), you can also head to our
[Discussion](https://github.com/apache/dubbo/discussions) tab.
If you need to report a security issue, please visit [our security policy](https://github.com/apache/dubbo/security/policy).
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
Remember that non-English issues is quite not friendly for everyone, and might unable to get the response!
- type: checkboxes
attributes:
label: Pre-check
options:
- label: >
I am sure that all the content I provide is in English.
required: true
- type: checkboxes
attributes:
label: Search before asking
description: >
Please make sure to search in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) first to see
whether the same issue was reported already.
options:
- label: >
I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar
issues.
required: true
- type: input
attributes:
label: Dubbo Version
description: "Which Dubbo version, JDK version and operating system did you use?"
placeholder: "Example: Dubbo Java 3.2.12, OpenJDK 1.8, Ubuntu 20.04"
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce this issue
description: >
Describe how to reproduce this issue.If you are not able to provide a reproducible case,
please open a [Discussion](https://github.com/apache/dubbo/discussions) instead.
placeholder: >
Please provide the context in which the problem occurred and explain what happened.
A [GitHub address] would be helpful for maintainers to reproduce the problem.
validations:
required: true
- type: textarea
attributes:
label: What you expected to happen
description: What do you think went wrong?
placeholder: >
Please explain why you think the behaviour is erroneous. It is extremely helpful if you copy and paste
the fragment of logs showing the exact error messages or wrong behaviour and screenshots for
UI problems. You can include files by dragging and dropping them here.
**NOTE**: please copy and paste texts instead of taking screenshots of them for easy future search.
validations:
required: true
- type: textarea
attributes:
label: Anything else
description: Anything else we need to know?
placeholder: >
How often does this problem occur? (Once? Every time? Only when certain conditions are met?)
Any relevant logs to include? Put them here inside fenced
``` ``` blocks or inside a collapsable details tag if it's too long:
<details><summary>x.log</summary> lots of stuff </details>
- type: checkboxes
attributes:
label: Are you willing to submit a pull request to fix on your own?
description: >
This is absolutely not required, but we are happy to guide you in the contribution process
especially if you already have a good understanding of how to implement the fix.
Dubbo is a totally community-driven project and we love to bring new contributors in.
options:
- label: Yes I am willing to submit a pull request on my own!
- type: checkboxes
attributes:
label: Code of Conduct
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
options:
- label: >
I agree to follow this project's
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
required: true
- type: markdown
attributes:
value: "Thanks for completing our form!"

90
.github/ISSUE_TEMPLATE/2-feature.yml vendored Normal file
View File

@ -0,0 +1,90 @@
#
# 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.
#
name: Feature Request
description: Create a Feature Request for Dubbo
title: "[Feature] "
labels: ["status/need-triage"]
projects: ["apache/337"]
body:
- type: markdown
attributes:
value: |
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
Thank you for finding the time to propose new feature!
We really appreciate the community efforts to improve Dubbo.
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
Remember that non-English issues is quite not friendly for everyone, and might unable to get the response!
- type: checkboxes
attributes:
label: Pre-check
options:
- label: >
I am sure that all the content I provide is in English.
required: true
- type: checkboxes
attributes:
label: Search before asking
description: >
Please make sure to search in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) first to see
whether the same feature was requested already.
options:
- label: >
I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar
feature requirement.
required: true
- type: textarea
attributes:
label: Descriptions
description: A short description of your feature
validations:
required: true
- type: textarea
attributes:
label: Related issues
description: Is there currently another issue associated with this?
- type: checkboxes
attributes:
label: Are you willing to submit a pull request to fix on your own?
description: >
This is absolutely not required, but we are happy to guide you in the contribution process
especially if you already have a good understanding of how to implement the feature.
Dubbo is a totally community-driven project and we love to bring new contributors in.
options:
- label: Yes I am willing to submit a pull request on my own!
- type: checkboxes
attributes:
label: Code of Conduct
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
options:
- label: >
I agree to follow this project's
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
required: true
- type: markdown
attributes:
value: "Thanks for completing our form!"

View File

@ -1,39 +0,0 @@
---
name: Bug Report
about: Report a bug in Dubbo
title: ''
labels: status/need-triage
assignees: ''
---
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
### Environment
* Dubbo version: xxx
* Operating System version: xxx
* Java version: xxx
### Steps to reproduce this issue
1. xxx
2. xxx
3. xxx
Pls. provide [GitHub address] to reproduce this issue.
### Expected Behavior
<!-- What do you expect from the above steps-->
### Actual Behavior
<!-- What actually happens? -->
If there is an exception, please attach the exception trace:
```
Just put your stack trace here!
```

View File

@ -1,8 +1,22 @@
blank_issues_enabled: true
#
# 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.
#
blank_issues_enabled: false
contact_links:
- name: Dubbo Community Repo
url: https://github.com/apache/dubbo-website
about: Please see our community docs here.
- name: Report a security issue
url: https://github.com/apache/dubbo/security/policy
about: Please report security vulnerabilities using these instructions.
- name: Question & FAQ & Proposal
url: https://github.com/apache/dubbo/discussions/
about: Ask a question, request support or submit a proposal for Apache Dubbo.

View File

@ -1,11 +0,0 @@
---
name: Discussion
about: Start a discussion for Dubbo
title: ''
labels: type/discussion
assignees: ''
---
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
<!-- For all design discussions please continue. -->

View File

@ -1,16 +0,0 @@
---
name: Feature Request
about: Create a Feature Request for Dubbo
title: ''
labels: type/feature
assignees: ''
---
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
- [ ] I have searched the [release notes](https://github.com/apache/dubbo/releases) of this repository and believe that this is not a duplicate.
## Describe the feature
<!-- Please also discuss possible business value -->

View File

@ -1,15 +0,0 @@
---
name: Proposal
about: Create a technical proposal for Dubbo
title: ''
labels: type/proposal
assignees: ''
---
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
## Describe the proposal
<!-- Please use this for a concrete design proposal for functionality. -->
<!-- If you just want to request a new feature and discuss the possible business value, create a Feature Request. -->

View File

@ -1,13 +0,0 @@
---
name: Question
about: Ask a question about Dubbo
title: ''
labels: type/question
assignees: ''
---
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
## Ask your question here

View File

@ -25,6 +25,7 @@ import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.LockUtils;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metrics.event.MetricsEventBus;
@ -56,6 +57,8 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
@ -122,6 +125,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
private volatile ScheduledFuture<?> connectivityCheckFuture;
private final ReentrantLock invokerRefreshLock = new ReentrantLock();
/**
* The max count of invokers for each reconnect task select to try to reconnect.
*/
@ -293,17 +298,19 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
@Override
public void addInvalidateInvoker(Invoker<T> invoker) {
// 1. remove this invoker from validInvokers list, this invoker will not be listed in the next time
if (removeValidInvoker(invoker)) {
// 2. add this invoker to reconnect list
invokersToReconnect.add(invoker);
// 3. try start check connectivity task
checkConnectivity();
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
// 1. remove this invoker from validInvokers list, this invoker will not be listed in the next time
if (removeValidInvoker(invoker)) {
// 2. add this invoker to reconnect list
invokersToReconnect.add(invoker);
// 3. try start check connectivity task
checkConnectivity();
logger.info("The invoker " + invoker.getUrl()
+ " has been added to invalidate list due to connectivity problem. "
+ "Will trying to reconnect to it in the background.");
}
logger.info("The invoker " + invoker.getUrl()
+ " has been added to invalidate list due to connectivity problem. "
+ "Will trying to reconnect to it in the background.");
}
});
}
public void checkConnectivity() {
@ -322,23 +329,30 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
// 1. pick invokers from invokersToReconnect
// limit max reconnectTaskTryCount, prevent this task hang up all the connectivityExecutor
// for long time
if (invokersToReconnect.size() < reconnectTaskTryCount) {
invokersToTry.addAll(invokersToReconnect);
} else {
for (int i = 0; i < reconnectTaskTryCount; i++) {
Invoker<T> tInvoker = invokersToReconnect.get(
ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
if (!invokersToTry.contains(tInvoker)) {
// ignore if is selected, invokersToTry's size is always smaller than
// reconnectTaskTryCount + 1
invokersToTry.add(tInvoker);
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
if (invokersToReconnect.size() < reconnectTaskTryCount) {
invokersToTry.addAll(invokersToReconnect);
} else {
for (int i = 0; i < reconnectTaskTryCount; i++) {
Invoker<T> tInvoker = invokersToReconnect.get(
ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
if (!invokersToTry.contains(tInvoker)) {
// ignore if is selected, invokersToTry's size is always smaller than
// reconnectTaskTryCount + 1
invokersToTry.add(tInvoker);
}
}
}
}
});
// 2. try to check the invoker's status
for (Invoker<T> invoker : invokersToTry) {
if (invokers.contains(invoker)) {
AtomicBoolean invokerExist = new AtomicBoolean(false);
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
invokerExist.set(invokers.contains(invoker));
});
// Should not lock here, `invoker.isAvailable` may need some time to check
if (invokerExist.get()) {
if (invoker.isAvailable()) {
needDeleteList.add(invoker);
}
@ -348,22 +362,37 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
// 3. recover valid invoker
for (Invoker<T> tInvoker : needDeleteList) {
if (invokers.contains(tInvoker)) {
addValidInvoker(tInvoker);
logger.info(
"Recover service address: " + tInvoker.getUrl() + " from invalid list.");
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
for (Invoker<T> tInvoker : needDeleteList) {
if (invokers.contains(tInvoker)) {
addValidInvoker(tInvoker);
logger.info("Recover service address: " + tInvoker.getUrl()
+ " from invalid list.");
} else {
logger.info(
"The invoker " + tInvoker.getUrl()
+ " has been removed from invokers list. Will remove it in reconnect list.");
}
invokersToReconnect.remove(tInvoker);
}
invokersToReconnect.remove(tInvoker);
}
});
} catch (Throwable t) {
logger.error(
LoggerCodeConstants.INTERNAL_ERROR,
"",
"",
"Error occurred when check connectivity. ",
t);
} finally {
checkConnectivityPermit.release();
}
// 4. submit new task if it has more to recover
if (!invokersToReconnect.isEmpty()) {
checkConnectivity();
}
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
if (!invokersToReconnect.isEmpty()) {
checkConnectivity();
}
});
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(
applicationModel, getSummary(), getDirectoryMeta()));
},
@ -382,9 +411,11 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
* 4. all the invokers disappeared from total invokers should be removed in the disabled invokers list
*/
public void refreshInvoker() {
if (invokersInitialized) {
refreshInvokerInternal();
}
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
if (invokersInitialized) {
refreshInvokerInternal();
}
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
@ -393,7 +424,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
return Collections.emptyMap();
}
private synchronized void refreshInvokerInternal() {
private void refreshInvokerInternal() {
BitList<Invoker<T>> copiedInvokers = invokers.clone();
refreshInvokers(copiedInvokers, invokersToReconnect);
refreshInvokers(copiedInvokers, disabledInvokers);
@ -414,25 +445,29 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
@Override
public void addDisabledInvoker(Invoker<T> invoker) {
if (invokers.contains(invoker)) {
disabledInvokers.add(invoker);
removeValidInvoker(invoker);
logger.info("Disable service address: " + invoker.getUrl() + ".");
}
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
if (invokers.contains(invoker)) {
disabledInvokers.add(invoker);
removeValidInvoker(invoker);
logger.info("Disable service address: " + invoker.getUrl() + ".");
}
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
@Override
public void recoverDisabledInvoker(Invoker<T> invoker) {
if (disabledInvokers.remove(invoker)) {
try {
addValidInvoker(invoker);
logger.info("Recover service address: " + invoker.getUrl() + " from disabled list.");
} catch (Throwable ignore) {
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
if (disabledInvokers.remove(invoker)) {
try {
addValidInvoker(invoker);
logger.info("Recover service address: " + invoker.getUrl() + " from disabled list.");
} catch (Throwable ignore) {
}
}
}
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
@ -491,9 +526,11 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
protected void setInvokers(BitList<Invoker<T>> invokers) {
this.invokers = invokers;
refreshInvokerInternal();
this.invokersInitialized = true;
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
this.invokers = invokers;
refreshInvokerInternal();
this.invokersInitialized = true;
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
@ -501,29 +538,31 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
protected void destroyInvokers() {
// set empty instead of clearing to support concurrent access.
this.invokers = BitList.emptyList();
this.validInvokers = BitList.emptyList();
this.invokersInitialized = false;
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
this.invokers = BitList.emptyList();
this.validInvokers = BitList.emptyList();
this.invokersInitialized = false;
});
}
private boolean addValidInvoker(Invoker<T> invoker) {
boolean result;
synchronized (this.validInvokers) {
result = this.validInvokers.add(invoker);
}
AtomicBoolean result = new AtomicBoolean(false);
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
result.set(this.validInvokers.add(invoker));
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
return result.get();
}
private boolean removeValidInvoker(Invoker<T> invoker) {
boolean result;
synchronized (this.validInvokers) {
result = this.validInvokers.remove(invoker);
}
AtomicBoolean result = new AtomicBoolean(false);
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
result.set(this.validInvokers.remove(invoker));
});
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
return result.get();
}
protected abstract List<Invoker<T>> doList(

View File

@ -235,7 +235,7 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,
"condition state router thenCondition is empty",
"",
"The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost()
"The current consumer in the service blocklist. consumer: " + NetUtils.getLocalHost()
+ ", service: " + url.getServiceKey());
if (needToPrintMessage) {
messageHolder.set("Empty return. Reason: ThenCondition is empty.");

View File

@ -339,7 +339,7 @@ public /*final**/ class URL implements Serializable {
}
static String appendDefaultPort(String address, int defaultPort) {
if (address != null && address.length() > 0 && defaultPort > 0) {
if (StringUtils.isNotEmpty(address) && defaultPort > 0) {
int i = address.indexOf(':');
if (i < 0) {
return address + ":" + defaultPort;
@ -525,7 +525,7 @@ public /*final**/ class URL implements Serializable {
List<URL> urls = new ArrayList<>();
urls.add(this);
String[] backups = getParameter(RemotingConstants.BACKUP_KEY, new String[0]);
if (backups != null && backups.length > 0) {
if (ArrayUtils.isNotEmpty(backups)) {
for (String backup : backups) {
urls.add(this.setAddress(backup));
}
@ -805,7 +805,7 @@ public /*final**/ class URL implements Serializable {
public boolean hasParameter(String key) {
String value = getParameter(key);
return value != null && value.length() > 0;
return StringUtils.isNotEmpty(value);
}
public String getMethodParameterAndDecoded(String method, String key) {
@ -1061,7 +1061,7 @@ public /*final**/ class URL implements Serializable {
}
public URL addParameters(String... pairs) {
if (pairs == null || pairs.length == 0) {
if (ArrayUtils.isEmpty(pairs)) {
return this;
}
if (pairs.length % 2 != 0) {
@ -1589,9 +1589,9 @@ public /*final**/ class URL implements Serializable {
return attributes == null ? Collections.emptyMap() : attributes;
}
public URL addAttributes(Map<String, Object> attributes) {
if (attributes != null) {
attributes.putAll(attributes);
public URL addAttributes(Map<String, Object> attributeMap) {
if (attributeMap != null) {
attributes.putAll(attributeMap);
}
return this;
}
@ -1718,7 +1718,7 @@ public /*final**/ class URL implements Serializable {
public boolean hasServiceParameter(String service, String key) {
String value = getServiceParameter(service, key);
return value != null && value.length() > 0;
return StringUtils.isNotEmpty(value);
}
public float getPositiveServiceParameter(String service, String key, float defaultValue) {

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ScopeModel;
@ -376,7 +377,7 @@ public final class URLBuilder extends ServiceConfigURL {
@Override
public URLBuilder addParameters(String... pairs) {
if (pairs == null || pairs.length == 0) {
if (ArrayUtils.isEmpty(pairs)) {
return this;
}
if (pairs.length % 2 != 0) {
@ -416,7 +417,7 @@ public final class URLBuilder extends ServiceConfigURL {
@Override
public URLBuilder removeParameters(String... keys) {
if (keys == null || keys.length == 0) {
if (ArrayUtils.isEmpty(keys)) {
return this;
}
for (String key : keys) {
@ -458,7 +459,7 @@ public final class URLBuilder extends ServiceConfigURL {
return false;
}
String value = getMethodParameter(method, key);
return value != null && value.length() > 0;
return StringUtils.isNotEmpty(value);
}
@Override

View File

@ -29,8 +29,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_EXCEPTION;
public class ModuleEnvironment extends Environment implements ModuleExt {
// delegate
@ -94,19 +92,13 @@ public class ModuleEnvironment extends Environment implements ModuleExt {
@Override
public Configuration getDynamicGlobalConfiguration() {
if (dynamicConfiguration == null) {
return applicationDelegate.getDynamicGlobalConfiguration();
CompositeConfiguration configuration = new CompositeConfiguration();
configuration.addConfiguration(applicationDelegate.getDynamicGlobalConfiguration());
configuration.addConfiguration(orderedPropertiesConfiguration);
return configuration;
}
if (dynamicGlobalConfiguration == null) {
if (dynamicConfiguration == null) {
if (logger.isWarnEnabled()) {
logger.warn(
COMMON_UNEXPECTED_EXCEPTION,
"",
"",
"dynamicConfiguration is null , return globalConfiguration.");
}
return getConfiguration();
}
dynamicGlobalConfiguration = new CompositeConfiguration();
dynamicGlobalConfiguration.addConfiguration(dynamicConfiguration);
dynamicGlobalConfiguration.addConfiguration(getConfiguration());

View File

@ -113,12 +113,12 @@ public class ServiceConfigURL extends URL {
}
@Override
public URL addAttributes(Map<String, Object> attributes) {
public URL addAttributes(Map<String, Object> attributeMap) {
Map<String, Object> newAttributes = new HashMap<>();
if (this.attributes != null) {
newAttributes.putAll(this.attributes);
}
newAttributes.putAll(attributes);
newAttributes.putAll(attributeMap);
return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes);
}

View File

@ -0,0 +1,54 @@
/*
* 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.utils;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
public class LockUtils {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(LockUtils.class);
public static final int DEFAULT_TIMEOUT = 60_000;
public static void safeLock(Lock lock, int timeout, Runnable runnable) {
try {
if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) {
logger.error(
LoggerCodeConstants.INTERNAL_ERROR,
"",
"",
"Try to lock failed, timeout: " + timeout,
new TimeoutException());
}
runnable.run();
} catch (InterruptedException e) {
logger.warn(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Try to lock failed", e);
Thread.currentThread().interrupt();
} finally {
try {
lock.unlock();
} catch (Exception e) {
// ignore
}
}
}
}

View File

@ -17,6 +17,8 @@
package org.apache.dubbo.common.config;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -32,4 +34,18 @@ class OrderedPropertiesConfigurationTest {
ApplicationModel.defaultModel().getDefaultModule());
Assertions.assertEquals("999", configuration.getInternalProperty("testKey"));
}
@Test
void testGetPropertyFromOrderedPropertiesConfiguration() {
FrameworkModel frameworkModel = new FrameworkModel();
ApplicationModel applicationModel = frameworkModel.newApplication();
ModuleModel moduleModel = applicationModel.newModule();
ModuleEnvironment moduleEnvironment = moduleModel.modelEnvironment();
Configuration configuration = moduleEnvironment.getDynamicGlobalConfiguration();
// MockOrderedPropertiesProvider2 initProperties
Assertions.assertEquals("999", configuration.getString("testKey"));
}
}

View File

@ -0,0 +1,144 @@
/*
* 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.utils;
import java.lang.Thread.State;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.RepeatedTest;
import static org.awaitility.Awaitility.await;
public class LockUtilsTest {
@RepeatedTest(5)
void testLockFailed() {
ReentrantLock reentrantLock = new ReentrantLock();
AtomicBoolean releaseLock = new AtomicBoolean(false);
new Thread(() -> {
reentrantLock.lock();
while (!releaseLock.get()) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
reentrantLock.unlock();
})
.start();
await().until(reentrantLock::isLocked);
AtomicLong lockTime = new AtomicLong(0);
long startTime = System.currentTimeMillis();
LockUtils.safeLock(reentrantLock, 1000, () -> {
lockTime.set(System.currentTimeMillis());
});
Assertions.assertTrue(lockTime.get() - startTime >= 1000);
releaseLock.set(true);
while (reentrantLock.isLocked()) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
lockTime.set(0);
startTime = System.currentTimeMillis();
LockUtils.safeLock(reentrantLock, 1000, () -> {
lockTime.set(System.currentTimeMillis());
});
Assertions.assertTrue(lockTime.get() - startTime < 1000);
}
@RepeatedTest(5)
void testReentrant() {
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
AtomicLong lockTime = new AtomicLong(0);
long startTime = System.currentTimeMillis();
LockUtils.safeLock(reentrantLock, 1000, () -> {
lockTime.set(System.currentTimeMillis());
});
Assertions.assertTrue(lockTime.get() - startTime < 1000);
reentrantLock.lock();
lockTime.set(0);
startTime = System.currentTimeMillis();
LockUtils.safeLock(reentrantLock, 1000, () -> {
lockTime.set(System.currentTimeMillis());
});
Assertions.assertTrue(lockTime.get() - startTime < 1000);
Assertions.assertTrue(reentrantLock.isLocked());
reentrantLock.unlock();
Assertions.assertTrue(reentrantLock.isLocked());
reentrantLock.unlock();
Assertions.assertFalse(reentrantLock.isLocked());
}
@RepeatedTest(5)
void testInterrupt() {
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
AtomicBoolean locked = new AtomicBoolean(false);
Thread thread = new Thread(() -> {
LockUtils.safeLock(reentrantLock, 10000, () -> {
locked.set(true);
});
});
thread.start();
await().until(() -> thread.getState() == State.TIMED_WAITING);
thread.interrupt();
await().until(() -> thread.getState() == State.TERMINATED);
Assertions.assertFalse(locked.get());
reentrantLock.unlock();
}
@RepeatedTest(5)
void testHoldLock() throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
AtomicLong lockTime = new AtomicLong(0);
long startTime = System.currentTimeMillis();
Thread thread = new Thread(() -> {
LockUtils.safeLock(reentrantLock, 10000, () -> {
lockTime.set(System.currentTimeMillis());
});
});
thread.start();
await().until(() -> thread.getState() == State.TIMED_WAITING);
Thread.sleep(1000);
reentrantLock.unlock();
await().until(() -> thread.getState() == State.TERMINATED);
Assertions.assertTrue(lockTime.get() - startTime > 1000);
Assertions.assertTrue(lockTime.get() - startTime < 10000);
}
}

View File

@ -854,8 +854,8 @@ public class DelegateURL extends com.alibaba.dubbo.common.URL {
}
@Override
public org.apache.dubbo.common.URL addAttributes(Map<String, Object> attributes) {
return apacheUrl.addAttributes(attributes);
public org.apache.dubbo.common.URL addAttributes(Map<String, Object> attributeMap) {
return apacheUrl.addAttributes(attributeMap);
}
@Override

View File

@ -242,7 +242,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.19.5</version>
<version>1.19.6</version>
<scope>test</scope>
</dependency>

View File

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

View File

@ -534,6 +534,9 @@ public class ServiceAnnotationPostProcessor
addPropertyReference(builder, "executor", executorBeanName);
}
// service bean definition should not be lazy
builder.setLazyInit(false);
return builder.getBeanDefinition();
}

View File

@ -65,7 +65,7 @@ public interface RestDemoService {
Boolean testBody2(Boolean b);
@POST
@Path("/testBody3")
@Path("/testBody4")
@Consumes({MediaType.TEXT_PLAIN})
TestPO testBody2(TestPO b);

View File

@ -157,7 +157,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.14</version>
<version>1.5.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@ -204,7 +204,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -157,7 +157,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.14</version>
<version>1.5.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@ -204,7 +204,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>

View File

@ -35,7 +35,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.2</micrometer-core.version>
<micrometer-core.version>1.12.3</micrometer-core.version>
</properties>
<dependencyManagement>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>27</version>
<version>31</version>
<relativePath />
</parent>
@ -91,24 +91,24 @@
<!-- Common libs -->
<!-- <spring_version>4.3.30.RELEASE</spring_version> -->
<spring_version>5.3.25</spring_version>
<spring_security_version>5.8.9</spring_security_version>
<spring_security_version>5.8.10</spring_security_version>
<javassist_version>3.30.2-GA</javassist_version>
<byte-buddy_version>1.14.11</byte-buddy_version>
<byte-buddy_version>1.14.12</byte-buddy_version>
<netty_version>3.2.10.Final</netty_version>
<netty4_version>4.1.106.Final</netty4_version>
<netty4_version>4.1.107.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.46</fastjson2_version>
<fastjson2_version>2.0.47</fastjson2_version>
<zookeeper_version>3.7.2</zookeeper_version>
<curator_version>5.1.0</curator_version>
<curator_test_version>2.12.0</curator_test_version>
<jedis_version>3.10.0</jedis_version>
<hessian_version>4.0.66</hessian_version>
<protobuf-java_version>3.25.2</protobuf-java_version>
<protobuf-java_version>3.25.3</protobuf-java_version>
<javax_annotation-api_version>1.3.2</javax_annotation-api_version>
<servlet_version>3.1.0</servlet_version>
<jetty_version>9.4.53.v20231009</jetty_version>
<jetty_version>9.4.54.v20240208</jetty_version>
<validation_new_version>3.0.2</validation_new_version>
<validation_version>1.1.0.Final</validation_version>
<hibernate_validator_version>5.4.3.Final</hibernate_validator_version>
@ -119,10 +119,10 @@
<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.2</micrometer.version>
<micrometer.version>1.12.3</micrometer.version>
<opentelemetry.version>1.26.0</opentelemetry.version>
<zipkin-reporter.version>2.16.4</zipkin-reporter.version>
<micrometer-tracing.version>1.2.2</micrometer-tracing.version>
<micrometer-tracing.version>1.2.3</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>
@ -133,7 +133,7 @@
<rs_api_version>2.1.1</rs_api_version>
<resteasy_version>3.15.6.Final</resteasy_version>
<codehaus-jackson_version>1.9.13</codehaus-jackson_version>
<tomcat_embed_version>8.5.98</tomcat_embed_version>
<tomcat_embed_version>8.5.99</tomcat_embed_version>
<nacos_version>2.2.4</nacos_version>
<sentinel.version>1.8.6</sentinel.version>
<seata.version>1.6.1</seata.version>
@ -147,7 +147,7 @@
<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.22.1</log4j2_version>
<log4j2_version>2.23.0</log4j2_version>
<commons_io_version>2.15.1</commons_io_version>
<commons-codec_version>1.16.0</commons-codec_version>
@ -166,7 +166,7 @@
<jaxb_version>2.2.7</jaxb_version>
<activation_version>1.2.0</activation_version>
<test_container_version>1.19.5</test_container_version>
<test_container_version>1.19.6</test_container_version>
<hessian_lite_version>3.2.13</hessian_lite_version>
<swagger_version>1.6.13</swagger_version>
@ -179,7 +179,7 @@
<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.25.0</commons_compress_version>
<commons_compress_version>1.26.0</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>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>27</version>
<version>31</version>
<relativePath />
</parent>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>27</version>
<version>31</version>
<relativePath />
</parent>

View File

@ -202,7 +202,7 @@ public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implement
+ " for service " + getConsumerUrl().getServiceKey() + " on consumer "
+ NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ ", please check status of providers(disabled, not registered or in blacklist).");
+ ", please check status of providers(disabled, not registered or in blocklist).");
}
if (multiGroup) {

View File

@ -169,10 +169,13 @@ public interface ResteasyContext {
for (Map.Entry<String, List<Object>> entry : headers.entrySet()) {
String key = entry.getKey();
if (entry.getValue() == null) {
List<Object> value = entry.getValue();
if (value == null || value.isEmpty()) {
continue;
}
response.addOutputHeaders(key, entry.getValue().toString());
for (Object tmp : value) {
response.addOutputHeaders(key, tmp.toString());
}
}
}

View File

@ -42,7 +42,14 @@ public class ResteasyNettyHttpResponse implements HttpResponse {
for (Map.Entry<String, List<String>> headers : outputHeaders.entrySet()) {
String key = headers.getKey();
List<String> value = headers.getValue();
multivaluedMap.add(key, value);
if (value == null || value.isEmpty()) {
continue;
}
for (String val : value) {
multivaluedMap.add(key, val);
}
}
}

View File

@ -33,13 +33,12 @@ import java.util.Set;
/**
* body is json
*/
@Activate("json")
@Activate(value = "json", order = 100)
public class JsonCodec implements HttpMessageCodec<byte[], OutputStream> {
private static final Set<Class> unSupportClasses = new HashSet<>();
static {
unSupportClasses.add(byte[].class);
unSupportClasses.add(String.class);
}
@Override

View File

@ -28,7 +28,7 @@ import java.nio.charset.StandardCharsets;
/**
* body is string
*/
@Activate("string")
@Activate(value = "string", order = 200)
public class StringCodec implements HttpMessageCodec<byte[], OutputStream> {
@Override

View File

@ -190,6 +190,10 @@ public class NettyHttpResponse implements HttpResponse {
outputHeaders.put(name, values);
}
if (values.contains(value)) {
return;
}
values.add(value);
}

View File

@ -36,8 +36,8 @@
</modules>
<properties>
<micrometer.version>1.12.2</micrometer.version>
<micrometer-tracing.version>1.2.2</micrometer-tracing.version>
<micrometer.version>1.12.3</micrometer.version>
<micrometer-tracing.version>1.2.3</micrometer-tracing.version>
<opentelemetry.version>1.34.1</opentelemetry.version>
<zipkin-reporter.version>2.17.2</zipkin-reporter.version>
<prometheus-client.version>0.16.0</prometheus-client.version>

View File

@ -41,7 +41,7 @@
<properties>
<spring-boot.version>2.7.18</spring-boot.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.11</byte-buddy.version>
<byte-buddy.version>1.14.12</byte-buddy.version>
<mockito_version>4.11.0</mockito_version>
</properties>

View File

@ -31,7 +31,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.25.0</commons.compress.version>
<commons.compress.version>1.26.0</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

@ -22,7 +22,7 @@
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>23</version>
<version>31</version>
</parent>
<groupId>org.apache.dubbo</groupId>
@ -136,7 +136,7 @@
<maven_compiler_version>3.12.1</maven_compiler_version>
<maven_source_version>3.3.0</maven_source_version>
<maven_javadoc_version>3.6.3</maven_javadoc_version>
<maven_jetty_version>9.4.53.v20231009</maven_jetty_version>
<maven_jetty_version>9.4.54.v20240208</maven_jetty_version>
<maven_checkstyle_version>3.3.1</maven_checkstyle_version>
<maven_jacoco_version>0.8.11</maven_jacoco_version>
<maven_flatten_version>1.6.0</maven_flatten_version>
@ -280,7 +280,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>