Merge branch 'apache-3.1' into apache-3.2

# Conflicts:
#	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
This commit is contained in:
Albumen Kevin 2022-12-12 16:24:01 +08:00
commit ab10b8a189
20 changed files with 230 additions and 111 deletions

View File

@ -33,12 +33,15 @@ import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.TimeoutCountDown;
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_TIMEOUT_COUNTDOWN_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHMENT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;
/**
@ -95,13 +98,21 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
}
// pass default timeout set by end user (ReferenceConfig)
Object countDown = context.getObjectAttachment(TIME_COUNTDOWN_KEY);
Object countDown = RpcContext.getServerAttachment().getObjectAttachment(TIME_COUNTDOWN_KEY);
if (countDown != null) {
TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown;
if (timeoutCountDown.isExpired()) {
return AsyncRpcResult.newDefaultAsyncResult(new RpcException(RpcException.TIMEOUT_TERMINATE,
"No time left for making the following call: " + invocation.getServiceName() + "."
+ invocation.getMethodName() + ", terminate directly."), invocation);
String methodName = RpcUtils.getMethodName(invocation);
// When the client has enabled the timeout-countdown function,
// the subsequent calls launched by the Server side will be enabled by default,
// and support to turn off the function on a node to get rid of the timeout control.
if (invoker.getUrl().getMethodParameter(methodName, ENABLE_TIMEOUT_COUNTDOWN_KEY, true)) {
context.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, countDown);
TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown;
if (timeoutCountDown.isExpired()) {
return AsyncRpcResult.newDefaultAsyncResult(new RpcException(RpcException.TIMEOUT_TERMINATE,
"No time left for making the following call: " + invocation.getServiceName() + "."
+ invocation.getMethodName() + ", terminate directly."), invocation);
}
}
}
RpcContext.removeClientResponseContext();

View File

@ -120,7 +120,8 @@ public class JdkCompiler extends AbstractCompiler {
Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
null, Collections.singletonList(javaFileObject)).call();
if (result == null || !result) {
throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: "
+ diagnosticCollector.getDiagnostics());
}
return classLoader.loadClass(name);
}

View File

@ -81,7 +81,7 @@ public class Environment extends LifecycleAdapter implements ApplicationExt {
public void initialize() throws IllegalStateException {
if (initialized.compareAndSet(false, true)) {
this.propertiesConfiguration = new PropertiesConfiguration(scopeModel);
this.systemConfiguration = new SystemConfiguration();
this.systemConfiguration = new SystemConfiguration(scopeModel);
this.environmentConfiguration = new EnvironmentConfiguration();
this.externalConfiguration = new InmemoryConfiguration("ExternalConfig");
this.appExternalConfiguration = new InmemoryConfiguration("AppExternalConfig");

View File

@ -17,8 +17,18 @@
package org.apache.dubbo.common.config;
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.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* FIXME: is this really necessary? PropertiesConfiguration should have already covered this:
@ -28,8 +38,23 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class SystemConfiguration implements Configuration {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SystemConfiguration.class);
private final Map<String, Object> cache = new ConcurrentHashMap<>();
private final ScheduledExecutorService sharedScheduledExecutor;
public SystemConfiguration(ScopeModel scopeModel) {
sharedScheduledExecutor = ScopeModelUtil.getFrameworkModel(scopeModel).getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getSharedScheduledExecutor();
sharedScheduledExecutor.scheduleWithFixedDelay(() -> {
if (!cache.isEmpty()) {
Set<String> keys = cache.keySet();
keys.forEach((key) -> overwriteCache(key, System.getProperty(key)));
}
}, 60000, 60000, TimeUnit.MILLISECONDS);
}
@Override
public Object getInternalProperty(String key) {
if (cache.containsKey(key)) {
@ -72,8 +97,14 @@ public class SystemConfiguration implements Configuration {
}
public Map<String, String> getProperties() {
return (Map) System.getProperties();
Properties properties = System.getProperties();
Map<String, String> res = new ConcurrentHashMap<>(properties.size());
try {
res.putAll((Map) properties);
} catch (Exception e) {
logger.warn("System property get failed", e);
}
return res;
}
}

View File

@ -664,47 +664,7 @@ public abstract class AbstractConfig implements Serializable {
try {
// check and init before do refresh
preProcessRefresh();
Environment environment = getScopeModel().getModelEnvironment();
List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
// Search props starts with PREFIX in order
String preferredPrefix = null;
List<String> prefixes = getPrefixes();
for (String prefix : prefixes) {
if (ConfigurationUtils.hasSubProperties(configurationMaps, prefix)) {
preferredPrefix = prefix;
break;
}
}
if (preferredPrefix == null) {
preferredPrefix = prefixes.get(0);
}
// Extract sub props (which key was starts with preferredPrefix)
Collection<Map<String, String>> instanceConfigMaps = environment.getConfigurationMaps(this, preferredPrefix);
Map<String, String> subProperties = ConfigurationUtils.getSubProperties(instanceConfigMaps, preferredPrefix);
InmemoryConfiguration subPropsConfiguration = new InmemoryConfiguration(subProperties);
if (logger.isDebugEnabled()) {
String idOrName = "";
if (StringUtils.hasText(this.getId())) {
idOrName = "[id=" + this.getId() + "]";
} else {
String name = ReflectUtils.getProperty(this, "getName");
if (StringUtils.hasText(name)) {
idOrName = "[name=" + name + "]";
}
}
logger.debug("Refreshing " + this.getClass().getSimpleName() + idOrName +
" with prefix [" + preferredPrefix +
"], extracted props: " + subProperties);
}
assignProperties(this, environment, subProperties, subPropsConfiguration);
// process extra refresh of subclass, e.g. refresh method configs
processExtraRefresh(preferredPrefix, subPropsConfiguration);
refreshWithPrefixes(getPrefixes(), getConfigMode());
} catch (Exception e) {
logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e);
throw new IllegalStateException("Failed to override field value of config bean: " + this, e);
@ -714,12 +674,53 @@ public abstract class AbstractConfig implements Serializable {
refreshed.set(true);
}
private void assignProperties(Object obj, Environment environment, Map<String, String> properties, InmemoryConfiguration configuration) {
protected void refreshWithPrefixes(List<String> prefixes, ConfigMode configMode) {
Environment environment = getScopeModel().getModelEnvironment();
List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
// Search props starts with PREFIX in order
String preferredPrefix = null;
for (String prefix : prefixes) {
if (ConfigurationUtils.hasSubProperties(configurationMaps, prefix)) {
preferredPrefix = prefix;
break;
}
}
if (preferredPrefix == null) {
preferredPrefix = prefixes.get(0);
}
// Extract sub props (which key was starts with preferredPrefix)
Collection<Map<String, String>> instanceConfigMaps = environment.getConfigurationMaps(this, preferredPrefix);
Map<String, String> subProperties = ConfigurationUtils.getSubProperties(instanceConfigMaps, preferredPrefix);
InmemoryConfiguration subPropsConfiguration = new InmemoryConfiguration(subProperties);
if (logger.isDebugEnabled()) {
String idOrName = "";
if (StringUtils.hasText(this.getId())) {
idOrName = "[id=" + this.getId() + "]";
} else {
String name = ReflectUtils.getProperty(this, "getName");
if (StringUtils.hasText(name)) {
idOrName = "[name=" + name + "]";
}
}
logger.debug("Refreshing " + this.getClass().getSimpleName() + idOrName +
" with prefix [" + preferredPrefix +
"], extracted props: " + subProperties);
}
assignProperties(this, environment, subProperties, subPropsConfiguration, configMode);
// process extra refresh of subclass, e.g. refresh method configs
processExtraRefresh(preferredPrefix, subPropsConfiguration);
}
private void assignProperties(Object obj, Environment environment, Map<String, String> properties, InmemoryConfiguration configuration, ConfigMode configMode) {
// if old one (this) contains non-null value, do not override
boolean overrideIfAbsent = getConfigMode() == ConfigMode.OVERRIDE_IF_ABSENT;
boolean overrideIfAbsent = configMode == ConfigMode.OVERRIDE_IF_ABSENT;
// even if old one (this) contains non-null value, do override
boolean overrideAll = getConfigMode() == ConfigMode.OVERRIDE_ALL;
boolean overrideAll = configMode == ConfigMode.OVERRIDE_ALL;
// loop methods, get override value and set the new value back to method
List<Method> methods = MethodUtils.getMethods(obj.getClass(), method -> method.getDeclaringClass() != Object.class);
@ -807,7 +808,7 @@ public abstract class AbstractConfig implements Serializable {
String fieldName = MethodUtils.extractFieldName(method);
Map<String, String> subProperties = ConfigurationUtils.getSubProperties(properties, fieldName);
InmemoryConfiguration subPropsConfiguration = new InmemoryConfiguration(subProperties);
assignProperties(inner, environment, subProperties, subPropsConfiguration);
assignProperties(inner, environment, subProperties, subPropsConfiguration, configMode);
method.invoke(obj, inner);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Cannot assign nested class when refreshing config: " + obj.getClass().getName(), e);

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.RegexProperties;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.context.ConfigMode;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
@ -134,6 +135,8 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
.getDefaultConsumer()
.orElseThrow(() -> new IllegalStateException("Default consumer is not initialized"));
}
// try set properties from `dubbo.reference` if not set in current config
refreshWithPrefixes(super.getPrefixes(), ConfigMode.OVERRIDE_IF_ABSENT);
}
@Override

View File

@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.context.ConfigMode;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
@ -174,6 +175,8 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
.getDefaultProvider()
.orElseThrow(() -> new IllegalStateException("Default provider is not initialized"));
}
// try set properties from `dubbo.service` if not set in current config
refreshWithPrefixes(super.getPrefixes(), ConfigMode.OVERRIDE_IF_ABSENT);
}
@Override

View File

@ -272,7 +272,6 @@ public class ConfigManager extends AbstractConfigManager implements ApplicationE
ApplicationConfig.class,
ProtocolConfig.class,
RegistryConfig.class,
MetadataReportConfig.class,
MonitorConfig.class,
MetricsConfig.class,
SslConfig.class);

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.config;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -44,7 +45,7 @@ class SystemConfigurationTest {
@BeforeEach
public void init() {
sysConfig = new SystemConfiguration();
sysConfig = new SystemConfiguration(ApplicationModel.defaultModel().getDefaultModule());
}
/**
@ -114,4 +115,4 @@ class SystemConfigurationTest {
MockTwo
}
}
}

View File

@ -393,22 +393,33 @@ class ConfigManagerTest {
@Test
void testLoadConfigsOfTypeFromProps() {
try {
System.setProperty("dubbo.protocols.dubbo1.port", "20880");
System.setProperty("dubbo.protocols.dubbo2.port", "20881");
System.setProperty("dubbo.protocols.rest1.port", "8080");
System.setProperty("dubbo.protocols.rest2.port", "8081");
ApplicationModel.defaultModel().destroy();
ApplicationModel applicationModel = ApplicationModel.defaultModel();
configManager = applicationModel.getApplicationConfigManager();
moduleConfigManager = applicationModel.getDefaultModule().getConfigManager();
// dubbo.application.enable-file-cache = false
configManager.loadConfigsOfTypeFromProps(ApplicationConfig.class);
Optional<ApplicationConfig> application = configManager.getApplication();
Assertions.assertTrue(application.isPresent());
configManager.removeConfig(application.get());
System.setProperty("dubbo.protocols.dubbo1.port", "20880");
System.setProperty("dubbo.protocols.dubbo2.port", "20881");
System.setProperty("dubbo.protocols.rest1.port", "8080");
System.setProperty("dubbo.protocols.rest2.port", "8081");
configManager.loadConfigsOfTypeFromProps(ProtocolConfig.class);
Collection<ProtocolConfig> protocols = configManager.getProtocols();
Assertions.assertEquals(protocols.size(), 4);
System.setProperty("dubbo.applications.app1.name", "app-demo1");
System.setProperty("dubbo.applications.app2.name", "app-demo2");
ApplicationModel.defaultModel().destroy();
applicationModel = ApplicationModel.defaultModel();
configManager = applicationModel.getApplicationConfigManager();
moduleConfigManager = applicationModel.getDefaultModule().getConfigManager();
try {
configManager.loadConfigsOfTypeFromProps(ApplicationConfig.class);
Assertions.fail();
@ -456,4 +467,4 @@ class ConfigManagerTest {
Assertions.assertFalse(moduleConfigManager.getConsumers().isEmpty());
}
}
}

View File

@ -65,6 +65,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@ -73,16 +75,17 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static java.lang.String.format;
import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REFRESH_INSTANCE_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REGISTER_INSTANCE_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_START_MODEL;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_EXECUTE_DESTORY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_INIT_CONFIG_CENTER;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_START_MODEL;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REFRESH_INSTANCE_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REGISTER_INSTANCE_ERROR;
import static org.apache.dubbo.common.constants.MetricsConstants.PROTOCOL_PROMETHEUS;
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
@ -302,8 +305,10 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
MetadataReportInstance metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
List<MetadataReportConfig> validMetadataReportConfigs = new ArrayList<>(metadataReportConfigs.size());
for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
validMetadataReportConfigs.add(metadataReportConfig);
if (ConfigValidationUtils.isValidMetadataConfig(metadataReportConfig)) {
ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
validMetadataReportConfigs.add(metadataReportConfig);
}
}
metadataReportInstance.init(validMetadataReportConfigs);
if (!metadataReportInstance.inited()) {
@ -405,41 +410,57 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
private void useRegistryAsMetadataCenterIfNecessary() {
Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isNotEmpty(metadataConfigs)) {
Collection<MetadataReportConfig> originMetadataConfigs = configManager.getMetadataConfigs();
if (originMetadataConfigs.stream().anyMatch(m -> Objects.nonNull(m.getAddress()))) {
return;
}
Collection<MetadataReportConfig> metadataConfigsToOverride = originMetadataConfigs
.stream()
.filter(m -> Objects.isNull(m.getAddress()))
.collect(Collectors.toList());
if (metadataConfigsToOverride.size() > 1) {
return;
}
MetadataReportConfig metadataConfigToOverride = metadataConfigsToOverride.stream().findFirst().orElse(null);
List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
if (defaultRegistries.size() > 0) {
if (!defaultRegistries.isEmpty()) {
defaultRegistries
.stream()
.filter(this::isUsedRegistryAsMetadataCenter)
.map(this::registryAsMetadataCenter)
.map(registryConfig -> registryAsMetadataCenter(registryConfig, metadataConfigToOverride))
.forEach(metadataReportConfig -> {
if (metadataReportConfig.getId() == null) {
Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
for (MetadataReportConfig existedConfig : metadataReportConfigs) {
if (existedConfig.getId() == null && existedConfig.getAddress().equals(metadataReportConfig.getAddress())) {
return;
}
}
}
configManager.addMetadataReport(metadataReportConfig);
} else {
Optional<MetadataReportConfig> configOptional = configManager.getConfig(MetadataReportConfig.class, metadataReportConfig.getId());
if (configOptional.isPresent()) {
return;
}
configManager.addMetadataReport(metadataReportConfig);
}
logger.info("use registry as metadata-center: " + metadataReportConfig);
overrideMetadataReportConfig(metadataConfigToOverride, metadataReportConfig);
});
}
}
private void overrideMetadataReportConfig(MetadataReportConfig metadataConfigToOverride, MetadataReportConfig metadataReportConfig) {
if (metadataReportConfig.getId() == null) {
Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
for (MetadataReportConfig existedConfig : metadataReportConfigs) {
if (existedConfig.getId() == null && existedConfig.getAddress().equals(metadataReportConfig.getAddress())) {
return;
}
}
}
configManager.removeConfig(metadataConfigToOverride);
configManager.addMetadataReport(metadataReportConfig);
} else {
Optional<MetadataReportConfig> configOptional = configManager.getConfig(MetadataReportConfig.class, metadataReportConfig.getId());
if (configOptional.isPresent()) {
return;
}
configManager.removeConfig(metadataConfigToOverride);
configManager.addMetadataReport(metadataReportConfig);
}
logger.info("use registry as metadata-center: " + metadataReportConfig);
}
private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsMetadataCenter, "metadata",
MetadataReportFactory.class);
@ -495,24 +516,37 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
return false;
}
private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) {
String protocol = registryConfig.getProtocol();
URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel());
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
metadataReportConfig.setId(registryConfig.getId());
private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig, MetadataReportConfig originMetadataReportConfig) {
MetadataReportConfig metadataReportConfig = originMetadataReportConfig == null ?
new MetadataReportConfig(registryConfig.getApplicationModel()) : originMetadataReportConfig;
if (metadataReportConfig.getId() == null) {
metadataReportConfig.setId(registryConfig.getId());
}
metadataReportConfig.setScopeModel(applicationModel);
if (metadataReportConfig.getParameters() == null) {
metadataReportConfig.setParameters(new HashMap<>());
}
if (CollectionUtils.isNotEmptyMap(registryConfig.getParameters())) {
metadataReportConfig.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
for (Map.Entry<String, String> entry : registryConfig.getParameters().entrySet()) {
metadataReportConfig.getParameters().putIfAbsent(entry.getKey(), entry.getValue()); // copy the parameters
}
}
metadataReportConfig.getParameters().put(CLIENT_KEY, registryConfig.getClient());
metadataReportConfig.setGroup(registryConfig.getGroup());
metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig));
metadataReportConfig.setUsername(registryConfig.getUsername());
metadataReportConfig.setPassword(registryConfig.getPassword());
metadataReportConfig.setTimeout(registryConfig.getTimeout());
if (metadataReportConfig.getGroup() == null) {
metadataReportConfig.setGroup(registryConfig.getGroup());
}
if (metadataReportConfig.getAddress() == null) {
metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig));
}
if (metadataReportConfig.getUsername() == null) {
metadataReportConfig.setUsername(registryConfig.getUsername());
}
if (metadataReportConfig.getPassword() == null) {
metadataReportConfig.setPassword(registryConfig.getPassword());
}
if (metadataReportConfig.getTimeout() == null) {
metadataReportConfig.setTimeout(registryConfig.getTimeout());
}
return metadataReportConfig;
}

View File

@ -512,8 +512,21 @@ public class ConfigValidationUtils {
}
}
public static void validateMetadataConfig(MetadataReportConfig metadataReportConfig) {
public static boolean isValidMetadataConfig(MetadataReportConfig metadataReportConfig) {
if (metadataReportConfig == null) {
return false;
}
if (Boolean.FALSE.equals(metadataReportConfig.getReportMetadata()) &&
Boolean.FALSE.equals(metadataReportConfig.getReportDefinition())) {
return false;
}
return !isEmpty(metadataReportConfig.getAddress());
}
public static void validateMetadataConfig(MetadataReportConfig metadataReportConfig) {
if (!isValidMetadataConfig(metadataReportConfig)) {
return;
}

View File

@ -375,7 +375,7 @@ class MultiInstanceTest {
// stop provider app 2 and check threads
providerBootstrap2.stop();
// shutdown register center after dubbo application to avoid unregister services blocking
checkUnclosedThreadsOfApp(stackTraces2, "Found unclosed threads of app 2: ", null);
checkUnclosedThreadsOfApp(stackTraces2, "Found unclosed threads of app 2: ", new String[]{"Dubbo-framework-shared-scheduler"});
} finally {
if (providerBootstrap1 != null) {

View File

@ -29,10 +29,11 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_DIRECTORY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
@ -86,6 +87,7 @@ public class MetadataReportInstance implements Disposable {
String protocol = url.getParameter(METADATA_REPORT_KEY, DEFAULT_DIRECTORY);
url = URLBuilder.from(url)
.setProtocol(protocol)
.setPort(url.getParameter(PORT_KEY, url.getPort()))
.setScopeModel(config.getScopeModel())
.removeParameter(METADATA_REPORT_KEY)
.build();

View File

@ -112,7 +112,7 @@ public class RpcInvocation implements Invocation, Serializable {
* Deep clone of an invocation & put some service params into attachment from invoker (will not change the invoker in invocation)
*
* @param invocation original invocation
* @param invoker target invoker
* @param invoker target invoker
*/
public RpcInvocation(Invocation invocation, Invoker<?> invoker) {
this(invocation.getTargetServiceUniqueName(), invocation.getServiceModel(), invocation.getMethodName(), invocation.getServiceName(),
@ -384,6 +384,9 @@ public class RpcInvocation implements Invocation, Serializable {
public Map<String, Object> getObjectAttachments() {
try {
attachmentLock.lock();
if (attachments == null) {
attachments = new HashMap<>();
}
return attachments;
} finally {
attachmentLock.unlock();

View File

@ -121,7 +121,7 @@ public class ContextFilter implements Filter, Filter.Listener {
long timeout = RpcUtils.getTimeout(invocation, -1);
if (timeout != -1) {
// pass to next hop
RpcContext.getClientAttachment().setObjectAttachment(TIME_COUNTDOWN_KEY, TimeoutCountDown.newCountDown(timeout, TimeUnit.MILLISECONDS));
RpcContext.getServerAttachment().setObjectAttachment(TIME_COUNTDOWN_KEY, TimeoutCountDown.newCountDown(timeout, TimeUnit.MILLISECONDS));
}
// merged from dubbox

View File

@ -47,7 +47,7 @@ public class TimeoutFilter implements Filter, Filter.Listener {
@Override
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
Object obj = RpcContext.getClientAttachment().getObjectAttachment(TIME_COUNTDOWN_KEY);
Object obj = RpcContext.getServerAttachment().getObjectAttachment(TIME_COUNTDOWN_KEY);
if (obj != null) {
TimeoutCountDown countDown = (TimeoutCountDown) obj;
if (countDown.isExpired()) {

View File

@ -179,7 +179,7 @@ public class DubboInvoker<T> extends AbstractInvoker<T> {
int timeout;
if (countdown == null) {
timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getClientAttachment(), invocation, DEFAULT_TIMEOUT);
if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
if (getUrl().getMethodParameter(methodName, ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout); // pass timeout to remote server
}
} else {
@ -187,6 +187,8 @@ public class DubboInvoker<T> extends AbstractInvoker<T> {
timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS);
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout);// pass timeout to remote server
}
invocation.getObjectAttachments().remove(TIME_COUNTDOWN_KEY);
return timeout;
}
}

View File

@ -286,7 +286,7 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
int timeout;
if (countdown == null) {
timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getClientAttachment(), invocation, DEFAULT_TIMEOUT);
if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
if (getUrl().getMethodParameter(methodName, ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout); // pass timeout to remote server
}
} else {
@ -294,6 +294,8 @@ public class InjvmInvoker<T> extends AbstractInvoker<T> {
timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS);
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout);// pass timeout to remote server
}
invocation.getObjectAttachments().remove(TIME_COUNTDOWN_KEY);
return timeout;
}

View File

@ -307,7 +307,7 @@ public class TripleInvoker<T> extends AbstractInvoker<T> {
if (countdown == null) {
timeout = (int) RpcUtils.getTimeout(getUrl(), methodName,
RpcContext.getClientAttachment(), invocation, 3000);
if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
if (getUrl().getMethodParameter(methodName, ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY,
timeout); // pass timeout to remote server
}
@ -317,6 +317,8 @@ public class TripleInvoker<T> extends AbstractInvoker<T> {
invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY,
timeout);// pass timeout to remote server
}
invocation.getObjectAttachments().remove(TIME_COUNTDOWN_KEY);
return timeout;
}
}