Dubbo cloud native (#4666)

This commit is contained in:
Mercy Ma 2019-07-26 10:14:12 +08:00 committed by cvictory
parent fe562c3fee
commit 2691784703
37 changed files with 1730 additions and 1760 deletions

View File

@ -90,6 +90,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,127 +0,0 @@
/*
* 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.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.builders.ApplicationBuilder;
import java.util.Map;
/**
* {@link ApplicationConfig Application} settings
*
* @since 2.7.4
*/
public class ApplicationSettings extends AbstractSettings {
private final ApplicationBuilder builder;
public ApplicationSettings(ApplicationBuilder builder, DubboBootstrap dubboBootstrap) {
super(dubboBootstrap);
this.builder = builder;
}
public ApplicationSettings version(String version) {
builder.version(version);
return this;
}
public ApplicationSettings owner(String owner) {
builder.owner(owner);
return this;
}
public ApplicationSettings organization(String organization) {
builder.organization(organization);
return this;
}
public ApplicationSettings architecture(String architecture) {
builder.architecture(architecture);
return this;
}
public ApplicationSettings environment(String environment) {
builder.environment(environment);
return this;
}
public ApplicationSettings compiler(String compiler) {
builder.compiler(compiler);
return this;
}
public ApplicationSettings logger(String logger) {
builder.logger(logger);
return this;
}
public ApplicationSettings monitor(MonitorConfig monitor) {
builder.monitor(monitor);
return this;
}
public ApplicationSettings monitor(String monitor) {
builder.monitor(monitor);
return this;
}
public ApplicationSettings isDefault(Boolean isDefault) {
builder.isDefault(isDefault);
return this;
}
public ApplicationSettings dumpDirectory(String dumpDirectory) {
builder.dumpDirectory(dumpDirectory);
return this;
}
public ApplicationSettings qosEnable(Boolean qosEnable) {
builder.qosEnable(qosEnable);
return this;
}
public ApplicationSettings qosPort(Integer qosPort) {
builder.qosPort(qosPort);
return this;
}
public ApplicationSettings qosAcceptForeignIp(Boolean qosAcceptForeignIp) {
builder.qosAcceptForeignIp(qosAcceptForeignIp);
return this;
}
public ApplicationSettings shutwait(String shutwait) {
builder.shutwait(shutwait);
return this;
}
public ApplicationSettings appendParameter(String key, String value) {
builder.appendParameter(key, value);
return this;
}
public ApplicationSettings appendParameters(Map<String, String> appendParameters) {
builder.appendParameters(appendParameters);
return this;
}
ApplicationConfig build() {
return builder.build();
}
}

View File

@ -19,14 +19,11 @@ package org.apache.dubbo.bootstrap;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
@ -59,7 +56,7 @@ import org.apache.dubbo.registry.support.ServiceOrientedRegistry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -71,9 +68,13 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.config.context.ConfigManager.getInstance;
import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries;
/**
@ -91,6 +92,10 @@ public class DubboBootstrap {
public static final String DEFAULT_REFERENCE_ID = "REFERENCE#DEFAULT";
public static final String DEFAULT_PROVIDER_ID = "PROVIDER#DEFAULT";
public static final String DEFAULT_CONSUMER_ID = "CONSUMER#DEFAULT";
private static final String NAME = DubboBootstrap.class.getSimpleName();
private final Logger logger = LoggerFactory.getLogger(getClass());
@ -105,6 +110,8 @@ public class DubboBootstrap {
private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
private final ConfigManager configManager = getInstance();
/**
* Is provider or not
*/
@ -121,20 +128,6 @@ public class DubboBootstrap {
private ServiceInstance serviceInstance;
private ApplicationBuilder applicationBuilder;
private ConsumerBuilder consumerBuilder;
private ProviderBuilder providerBuilder;
private Map<String, RegistryBuilder> registryBuilders = new HashMap<>();
private Map<String, ProtocolBuilder> protocolBuilders = new HashMap<>();
private Map<String, ServiceBuilder<?>> serviceBuilders = new HashMap<>();
private Map<String, ReferenceBuilder<?>> referenceBuilders = new HashMap<>();
public DubboBootstrap() {
DubboShutdownHook.getDubboShutdownHook().register();
}
@ -150,96 +143,205 @@ public class DubboBootstrap {
return this;
}
/* accept Config instance */
public DubboBootstrap application(ApplicationConfig applicationConfig) {
ConfigManager.getInstance().setApplication(applicationConfig);
return this;
}
public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
ConfigManager.getInstance().addConfigCenter(configCenterConfig);
return this;
}
public DubboBootstrap configCenter(List<ConfigCenterConfig> configCenterConfigs) {
ConfigManager.getInstance().addConfigCenter(configCenterConfigs);
return this;
}
public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
ConfigManager.getInstance().addMetadataReport(metadataReportConfig);
configManager.addMetadataReport(metadataReportConfig);
return this;
}
public DubboBootstrap metadataReport(List<MetadataReportConfig> metadataReportConfigs) {
ConfigManager.getInstance().addMetadataReport(metadataReportConfigs);
configManager.addMetadataReports(metadataReportConfigs);
return this;
}
// {@link ApplicationConfig} correlative methods
/**
* Set the name of application
*
* @param name the name of application
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap application(String name) {
return application(name, builder -> {
// DO NOTHING
});
}
/**
* Set the name of application and it's future build
*
* @param name the name of application
* @param consumerBuilder {@link ApplicationBuilder}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap application(String name, Consumer<ApplicationBuilder> consumerBuilder) {
ApplicationBuilder builder = createApplicationBuilder(name);
consumerBuilder.accept(builder);
return application(builder.build());
}
/**
* Set the {@link ApplicationConfig}
*
* @param applicationConfig the {@link ApplicationConfig}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap application(ApplicationConfig applicationConfig) {
configManager.setApplication(applicationConfig);
return this;
}
// {@link RegistryConfig} correlative methods
/**
* Add an instance of {@link RegistryConfig} with {@link #DEFAULT_REGISTRY_ID default ID}
*
* @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap registry(Consumer<RegistryBuilder> consumerBuilder) {
return registry(DEFAULT_REGISTRY_ID, consumerBuilder);
}
/**
* Add an instance of {@link RegistryConfig} with the specified ID
*
* @param id the {@link RegistryConfig#getId() id} of {@link RegistryConfig}
* @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap registry(String id, Consumer<RegistryBuilder> consumerBuilder) {
RegistryBuilder builder = createRegistryBuilder(id);
consumerBuilder.accept(builder);
return registry(builder.build());
}
/**
* Add an instance of {@link RegistryConfig}
*
* @param registryConfig an instance of {@link RegistryConfig}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap registry(RegistryConfig registryConfig) {
ConfigManager.getInstance().addRegistry(registryConfig, true);
configManager.addRegistry(registryConfig);
return this;
}
public DubboBootstrap registry(List<RegistryConfig> registryConfigs) {
ConfigManager.getInstance().addRegistries(registryConfigs, true);
/**
* Add an instance of {@link RegistryConfig}
*
* @param registryConfigs the multiple instances of {@link RegistryConfig}
* @return current {@link DubboBootstrap} instance
*/
public DubboBootstrap registries(Iterable<RegistryConfig> registryConfigs) {
registryConfigs.forEach(this::registry);
return this;
}
// {@link ProtocolConfig} correlative methods
public DubboBootstrap protocol(Consumer<ProtocolBuilder> consumerBuilder) {
return protocol(DEFAULT_PROTOCOL_ID, consumerBuilder);
}
public DubboBootstrap protocol(String id, Consumer<ProtocolBuilder> consumerBuilder) {
ProtocolBuilder builder = createProtocolBuilder(id);
consumerBuilder.accept(builder);
return protocol(builder.build());
}
public DubboBootstrap protocol(ProtocolConfig protocolConfig) {
ConfigManager.getInstance().addProtocol(protocolConfig, true);
return this;
return protocols(asList(protocolConfig));
}
public DubboBootstrap protocols(List<ProtocolConfig> protocolConfigs) {
ConfigManager.getInstance().addProtocols(protocolConfigs, true);
configManager.addProtocols(protocolConfigs, true);
return this;
}
public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
ConfigManager.getInstance().addConsumer(consumerConfig);
return this;
// {@link ServiceConfig} correlative methods
public <S> DubboBootstrap service(Consumer<ServiceBuilder<S>> consumerBuilder) {
return service(DEFAULT_SERVICE_ID, consumerBuilder);
}
public DubboBootstrap provider(ProviderConfig providerConfig) {
ConfigManager.getInstance().addProvider(providerConfig);
return this;
public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
ServiceBuilder builder = createServiceBuilder(id);
consumerBuilder.accept(builder);
return service(builder.build());
}
public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
ConfigManager.getInstance().addService(serviceConfig);
configManager.addService(serviceConfig);
return this;
}
// {@link Reference} correlative methods
public <S> DubboBootstrap reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
}
public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
ReferenceBuilder builder = createReferenceBuilder(id);
consumerBuilder.accept(builder);
return reference(builder.build());
}
public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
ConfigManager.getInstance().addReference(referenceConfig);
configManager.addReference(referenceConfig);
return this;
}
/* accept builder functional interface */
public DubboBootstrap application(String name, Consumer<ApplicationBuilder> builder) {
initApplicationBuilder(name);
builder.accept(applicationBuilder);
// {@link ProviderConfig} correlative methods
public DubboBootstrap provider(Consumer<ProviderBuilder> builderConsumer) {
return provider(DEFAULT_PROVIDER_ID, builderConsumer);
}
public DubboBootstrap provider(String id, Consumer<ProviderBuilder> builderConsumer) {
ProviderBuilder builder = createProviderBuilder(id);
builderConsumer.accept(builder);
return provider(builder.build());
}
public DubboBootstrap provider(ProviderConfig providerConfig) {
return providers(asList(providerConfig));
}
public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
providerConfigs.forEach(configManager::addProvider);
return this;
}
public DubboBootstrap registry(String id, Consumer<RegistryBuilder> builder) {
builder.accept(initRegistryBuilder(id));
// {@link ConsumerConfig} correlative methods
public DubboBootstrap consumer(Consumer<ConsumerBuilder> builderConsumer) {
return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
}
public DubboBootstrap consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
ConsumerBuilder builder = createConsumerBuilder(id);
builderConsumer.accept(builder);
return consumer(builder.build());
}
public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
return consumers(asList(consumerConfig));
}
public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
consumerConfigs.forEach(configManager::addConsumer);
return this;
}
public DubboBootstrap protocol(String id, Consumer<ProtocolBuilder> builder) {
builder.accept(initProtocolBuilder(id));
return this;
// {@link ConfigCenterConfig} correlative methods
public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
return configCenter(asList(configCenterConfig));
}
public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> builder) {
builder.accept(initServiceBuilder(id));
return this;
}
public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> builder) {
builder.accept(initReferenceBuilder(id));
public DubboBootstrap configCenter(List<ConfigCenterConfig> configCenterConfigs) {
configManager.addConfigCenters(configCenterConfigs);
return this;
}
@ -252,30 +354,13 @@ public class DubboBootstrap {
return;
}
buildApplicationConfig();
buildRegistryConfigs();
buildProtocolConfigs();
buildServiceConfigs();
buildReferenceConfigs();
clearBuilders();
startConfigCenter();
startMetadataReport();
loadRemoteConfigs();
useRegistryAsConfigCenterIfNecessary();
// checkApplication();
// checkProvider();
// chcckConsumer();
// checkRegistry();
// checkProtocol();
// checkMonitor();
useRegistryAsConfigCenterIfNecessary();
initialized = true;
@ -285,8 +370,6 @@ public class DubboBootstrap {
}
private void loadRemoteConfigs() {
ConfigManager configManager = ConfigManager.getInstance();
// registry ids to registry configs
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Set<String> registryIds = configManager.getRegistryIds();
@ -301,7 +384,7 @@ public class DubboBootstrap {
}
});
configManager.addRegistries(tmpRegistries, true);
configManager.addRegistries(tmpRegistries);
// protocol ids to protocol configs
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
@ -325,26 +408,26 @@ public class DubboBootstrap {
* there's no config center specified explicitly.
*/
private void useRegistryAsConfigCenterIfNecessary() {
ConfigManager configManager = ConfigManager.getInstance();
configManager.getDefaultRegistries().ifPresent(registryConfigs -> {
for (RegistryConfig registryConfig : registryConfigs) {
if (registryConfig != null && registryConfig.isZookeeperProtocol()) {
// we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
Environment.getInstance().getDynamicConfiguration().orElseGet(() -> {
Set<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
if (CollectionUtils.isEmpty(configCenters)) {
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setProtocol(registryConfig.getProtocol());
cc.setAddress(registryConfig.getAddress());
cc.setHighestPriority(false);
configManager.addConfigCenter(cc);
}
return null;
});
}
}
startConfigCenter();
// we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
if (Environment.getInstance().getDynamicConfiguration().isPresent()) {
return;
}
if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
return;
}
configManager.getRegistries().forEach(registryConfig -> {
String protocol = registryConfig.getProtocol();
String id = "config-center-" + protocol + "-" + registryConfig.getPort();
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setId(id);
cc.setProtocol(protocol);
cc.setAddress(registryConfig.getAddress());
cc.setHighestPriority(false);
configManager.addConfigCenter(cc);
});
startConfigCenter();
}
private List<ServiceDiscovery> getServiceDiscoveries() {
@ -369,16 +452,15 @@ public class DubboBootstrap {
exportServices();
// Not only provider register and some services are exported
if (!onlyRegisterProvider && !ConfigManager.getInstance().getServiceConfigs().isEmpty()) {
if (!onlyRegisterProvider && !configManager.getServiceConfigs().isEmpty()) {
/**
* export {@link MetadataService}
*/
ConfigManager configManager = ConfigManager.getInstance();
// TODO, only export to default registry?
List<URL> exportedURLs = exportMetadataService (
List<URL> exportedURLs = exportMetadataService(
configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")),
configManager.getDefaultRegistries().orElseThrow(() -> new IllegalStateException("No default RegistryConfig")),
configManager.getDefaultProtocols().orElseThrow(() -> new IllegalStateException("No default ProtocolConfig"))
configManager.getRegistries(),
configManager.getProtocols()
);
/**
@ -450,10 +532,10 @@ public class DubboBootstrap {
return started;
}
/* serve for builder apis, begin */
private ApplicationBuilder initApplicationBuilder(String name) {
applicationBuilder = new ApplicationBuilder().name(name);
return applicationBuilder;
private ApplicationBuilder createApplicationBuilder(String name) {
return new ApplicationBuilder().name(name);
}
private RegistryBuilder createRegistryBuilder(String id) {
@ -472,29 +554,21 @@ public class DubboBootstrap {
return new ReferenceBuilder().id(id);
}
private RegistryBuilder initRegistryBuilder(String id) {
return registryBuilders.computeIfAbsent(id, this::createRegistryBuilder);
private ProviderBuilder createProviderBuilder(String id) {
return new ProviderBuilder().id(id);
}
private ProtocolBuilder initProtocolBuilder(String id) {
return protocolBuilders.computeIfAbsent(id, this::createProtocolBuilder);
}
private ServiceBuilder initServiceBuilder(String id) {
return serviceBuilders.computeIfAbsent(id, this::createServiceBuilder);
}
private ReferenceBuilder initReferenceBuilder(String id) {
return referenceBuilders.computeIfAbsent(id, this::createReferenceBuilder);
private ConsumerBuilder createConsumerBuilder(String id) {
return new ConsumerBuilder().id(id);
}
/* serve for builder apis, end */
private void startMetadataReport() {
ApplicationConfig applicationConfig = ConfigManager.getInstance().getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
// FIXME, multiple metadata config support.
Set<MetadataReportConfig> metadataReportConfigs = ConfigManager.getInstance().getMetadataConfigs();
Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isEmpty(metadataReportConfigs)) {
if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
@ -512,7 +586,7 @@ public class DubboBootstrap {
}
private void startConfigCenter() {
Set<ConfigCenterConfig> configCenters = ConfigManager.getInstance().getConfigCenters();
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
if (CollectionUtils.isNotEmpty(configCenters)) {
CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
@ -522,7 +596,7 @@ public class DubboBootstrap {
}
Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration);
}
ConfigManager.getInstance().refreshAll();
configManager.refreshAll();
}
private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
@ -533,11 +607,11 @@ public class DubboBootstrap {
DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
String configContent = dynamicConfiguration.getConfigs(configCenter.getConfigFile(), configCenter.getGroup());
String appGroup = ConfigManager.getInstance().getApplication().orElse(new ApplicationConfig()).getName();
String appGroup = configManager.getApplication().orElse(new ApplicationConfig()).getName();
String appConfigContent = null;
if (StringUtils.isNotEmpty(appGroup)) {
if (isNotEmpty(appGroup)) {
appConfigContent = dynamicConfiguration.getConfigs
(StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
(isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
appGroup
);
}
@ -553,13 +627,6 @@ public class DubboBootstrap {
return null;
}
private DynamicConfiguration getDynamicConfiguration(URL url) {
DynamicConfigurationFactory factory = ExtensionLoader
.getExtensionLoader(DynamicConfigurationFactory.class)
.getExtension(url.getProtocol());
return factory.getDynamicConfiguration(url);
}
/**
* Add an instance of {@link EventListener}
*
@ -572,8 +639,8 @@ public class DubboBootstrap {
}
private List<URL> exportMetadataService(ApplicationConfig applicationConfig,
List<RegistryConfig> globalRegistryConfigs,
List<ProtocolConfig> globalProtocolConfigs) {
Collection<RegistryConfig> globalRegistryConfigs,
Collection<ProtocolConfig> globalProtocolConfigs) {
ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
exporter.setApplicationConfig(applicationConfig);
exporter.setRegistries(globalRegistryConfigs);
@ -581,36 +648,8 @@ public class DubboBootstrap {
return exporter.export();
}
private void buildApplicationConfig() {
ApplicationConfig applicationConfig = null;
if (applicationBuilder != null) {
applicationConfig = applicationBuilder.build();
}
ConfigManager.getInstance().setApplication(applicationConfig);
}
private void buildProtocolConfigs() {
List<ProtocolConfig> protocolConfigs = buildConfigs(protocolBuilders);
ConfigManager.getInstance().addProtocols(protocolConfigs, true);
}
private void buildRegistryConfigs() {
List<RegistryConfig> registryConfigs = buildConfigs(registryBuilders);
ConfigManager.getInstance().addRegistries(registryConfigs, true);
}
private void buildServiceConfigs() {
List<ServiceConfig<?>> serviceConfigs = buildConfigs(serviceBuilders);
serviceConfigs.forEach(ConfigManager.getInstance()::addService);
}
private void buildReferenceConfigs() {
List<ReferenceConfig<?>> referenceConfigs = buildConfigs(referenceBuilders);
referenceConfigs.forEach(ConfigManager.getInstance()::addReference);
}
private void exportServices() {
ConfigManager.getInstance().getServiceConfigs().forEach(this::exportServiceConfig);
configManager.getServiceConfigs().forEach(this::exportServiceConfig);
}
public void exportServiceConfig(ServiceConfig<?> serviceConfig) {
@ -658,46 +697,30 @@ public class DubboBootstrap {
}
private void destroyProtocolConfigs() {
ConfigManager.getInstance().getProtocols().values().forEach(ProtocolConfig::destroy);
configManager.getProtocols().forEach(ProtocolConfig::destroy);
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s all ProtocolConfigs have been destroyed.");
}
}
private void destroyReferenceConfigs() {
ConfigManager.getInstance().getReferenceConfigs().forEach(ReferenceConfig::destroy);
configManager.getReferenceConfigs().forEach(ReferenceConfig::destroy);
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s all ReferenceConfigs have been destroyed.");
}
}
private void clear() {
clearBuilders();
clearConfigs();
ConfigManager.getInstance().clear();
}
private void clearConfigs() {
ConfigManager.getInstance().clear();
configManager.clear();
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s configs have been clear.");
}
}
private void clearBuilders() {
this.applicationBuilder = null;
this.registryBuilders.clear();
this.protocolBuilders.clear();
this.serviceBuilders.clear();
this.referenceBuilders.clear();
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s builders have been clear.");
}
}
private void release() {
executeMutually(() -> {
while (awaited.compareAndSet(false, true)) {
@ -725,7 +748,8 @@ public class DubboBootstrap {
}
}
private static <C extends AbstractConfig, B extends AbstractBuilder> List<C> buildConfigs(Map<String, B> map) {
private static <C extends AbstractConfig, B extends
AbstractBuilder> List<C> buildConfigs(Map<String, B> map) {
List<C> configs = new ArrayList<>();
map.entrySet().forEach(entry -> {
configs.add((C) entry.getValue().build());

View File

@ -1,215 +0,0 @@
/*
* 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.bootstrap;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.builders.ProtocolBuilder;
import java.util.Map;
/**
* The settings of {@link ProtocolConfig protcol}
*
* @see ProtocolBuilder
* @since 2.7.4
*/
public class ProtocolSettings extends AbstractSettings {
private final ProtocolBuilder builder;
public ProtocolSettings(ProtocolBuilder builder, DubboBootstrap dubboBootstrap) {
super(dubboBootstrap);
this.builder = builder;
}
public ProtocolSettings name(String name) {
builder.name(name);
return this;
}
public ProtocolSettings host(String host) {
builder.host(host);
return this;
}
public ProtocolSettings port(Integer port) {
builder.port(port);
return this;
}
public ProtocolSettings contextpath(String contextpath) {
builder.contextpath(contextpath);
return this;
}
@Deprecated
public ProtocolSettings path(String path) {
builder.path(path);
return this;
}
public ProtocolSettings threadpool(String threadpool) {
builder.threadpool(threadpool);
return this;
}
public ProtocolSettings corethreads(Integer corethreads) {
builder.corethreads(corethreads);
return this;
}
public ProtocolSettings threads(Integer threads) {
builder.threads(threads);
return this;
}
public ProtocolSettings iothreads(Integer iothreads) {
builder.iothreads(iothreads);
return this;
}
public ProtocolSettings queues(Integer queues) {
builder.queues(queues);
return this;
}
public ProtocolSettings accepts(Integer accepts) {
builder.accepts(accepts);
return this;
}
public ProtocolSettings codec(String codec) {
builder.codec(codec);
return this;
}
public ProtocolSettings serialization(String serialization) {
builder.serialization(serialization);
return this;
}
public ProtocolSettings charset(String charset) {
builder.charset(charset);
return this;
}
public ProtocolSettings payload(Integer payload) {
builder.payload(payload);
return this;
}
public ProtocolSettings buffer(Integer buffer) {
builder.buffer(buffer);
return this;
}
public ProtocolSettings heartbeat(Integer heartbeat) {
builder.heartbeat(heartbeat);
return this;
}
public ProtocolSettings accesslog(String accesslog) {
builder.accesslog(accesslog);
return this;
}
public ProtocolSettings transporter(String transporter) {
builder.transporter(transporter);
return this;
}
public ProtocolSettings exchanger(String exchanger) {
builder.exchanger(exchanger);
return this;
}
public ProtocolSettings dispatcher(String dispatcher) {
builder.dispatcher(dispatcher);
return this;
}
@Deprecated
public ProtocolSettings dispather(String dispather) {
builder.dispather(dispather);
return this;
}
public ProtocolSettings networker(String networker) {
builder.networker(networker);
return this;
}
public ProtocolSettings server(String server) {
builder.server(server);
return this;
}
public ProtocolSettings client(String client) {
builder.client(client);
return this;
}
public ProtocolSettings telnet(String telnet) {
builder.telnet(telnet);
return this;
}
public ProtocolSettings prompt(String prompt) {
builder.prompt(prompt);
return this;
}
public ProtocolSettings status(String status) {
builder.status(status);
return this;
}
public ProtocolSettings register(Boolean register) {
builder.register(register);
return this;
}
public ProtocolSettings keepAlive(Boolean keepAlive) {
builder.keepAlive(keepAlive);
return this;
}
public ProtocolSettings optimizer(String optimizer) {
builder.optimizer(optimizer);
return this;
}
public ProtocolSettings extension(String extension) {
builder.extension(extension);
return this;
}
public ProtocolSettings appendParameter(String key, String value) {
builder.appendParameter(key, value);
return this;
}
public ProtocolSettings appendParameters(Map<String, String> appendParameters) {
builder.appendParameters(appendParameters);
return this;
}
public ProtocolSettings isDefault(Boolean isDefault) {
builder.isDefault(isDefault);
return this;
}
}

View File

@ -1,334 +0,0 @@
/*
* 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.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.builders.ReferenceBuilder;
import java.util.List;
import java.util.Map;
/**
* The settings of {@link ReferenceConfig}
*
* @since 2.7.4
*/
public class ReferenceSettings<S> extends AbstractSettings {
private final ReferenceBuilder<S> builder;
public ReferenceSettings(ReferenceBuilder<S> builder, DubboBootstrap dubboBootstrap) {
super(dubboBootstrap);
this.builder = builder;
}
public ReferenceSettings<S> interfaceName(String interfaceName) {
builder.interfaceName(interfaceName);
return this;
}
public ReferenceSettings<S> interfaceClass(Class<?> interfaceClass) {
builder.interfaceClass(interfaceClass);
return this;
}
public ReferenceSettings<S> client(String client) {
builder.client(client);
return this;
}
public ReferenceSettings<S> url(String url) {
builder.url(url);
return this;
}
public ReferenceSettings<S> addMethods(List<MethodConfig> methods) {
builder.addMethods(methods);
return this;
}
public ReferenceSettings<S> addMethod(MethodConfig method) {
builder.addMethod(method);
return this;
}
public ReferenceSettings<S> consumer(ConsumerConfig consumer) {
builder.consumer(consumer);
return this;
}
public ReferenceSettings<S> protocol(String protocol) {
builder.protocol(protocol);
return this;
}
public ReferenceSettings<S> check(Boolean check) {
builder.check(check);
return this;
}
public ReferenceSettings<S> init(Boolean init) {
builder.init(init);
return this;
}
public ReferenceSettings<S> generic(String generic) {
builder.generic(generic);
return this;
}
public ReferenceSettings<S> generic(Boolean generic) {
builder.generic(generic);
return this;
}
@Deprecated
public ReferenceSettings<S> injvm(Boolean injvm) {
builder.injvm(injvm);
return this;
}
public ReferenceSettings<S> lazy(Boolean lazy) {
builder.lazy(lazy);
return this;
}
public ReferenceSettings<S> reconnect(String reconnect) {
builder.reconnect(reconnect);
return this;
}
public ReferenceSettings<S> sticky(Boolean sticky) {
builder.sticky(sticky);
return this;
}
public ReferenceSettings<S> version(String version) {
builder.version(version);
return this;
}
public ReferenceSettings<S> group(String group) {
builder.group(group);
return this;
}
@Deprecated
public ReferenceSettings<S> local(String local) {
builder.local(local);
return this;
}
@Deprecated
public ReferenceSettings<S> local(Boolean local) {
builder.local(local);
return this;
}
public ReferenceSettings<S> stub(String stub) {
builder.stub(stub);
return this;
}
public ReferenceSettings<S> stub(Boolean stub) {
builder.stub(stub);
return this;
}
public ReferenceSettings<S> monitor(MonitorConfig monitor) {
builder.monitor(monitor);
return this;
}
public ReferenceSettings<S> monitor(String monitor) {
builder.monitor(monitor);
return this;
}
public ReferenceSettings<S> proxy(String proxy) {
builder.proxy(proxy);
return this;
}
public ReferenceSettings<S> cluster(String cluster) {
builder.cluster(cluster);
return this;
}
public ReferenceSettings<S> filter(String filter) {
builder.filter(filter);
return this;
}
public ReferenceSettings<S> listener(String listener) {
builder.listener(listener);
return this;
}
public ReferenceSettings<S> owner(String owner) {
builder.owner(owner);
return this;
}
public ReferenceSettings<S> connections(Integer connections) {
builder.connections(connections);
return this;
}
public ReferenceSettings<S> layer(String layer) {
builder.layer(layer);
return this;
}
public ReferenceSettings<S> application(ApplicationConfig application) {
builder.application(application);
return this;
}
public ReferenceSettings<S> module(ModuleConfig module) {
builder.module(module);
return this;
}
public ReferenceSettings<S> addRegistries(List<RegistryConfig> registries) {
builder.addRegistries(registries);
return this;
}
public ReferenceSettings<S> addRegistry(RegistryConfig registry) {
builder.addRegistry(registry);
return this;
}
public ReferenceSettings<S> registryIds(String registryIds) {
builder.registryIds(registryIds);
return this;
}
public ReferenceSettings<S> onconnect(String onconnect) {
builder.onconnect(onconnect);
return this;
}
public ReferenceSettings<S> ondisconnect(String ondisconnect) {
builder.ondisconnect(ondisconnect);
return this;
}
public ReferenceSettings<S> metadataReportConfig(MetadataReportConfig metadataReportConfig) {
builder.metadataReportConfig(metadataReportConfig);
return this;
}
public ReferenceSettings<S> configCenter(ConfigCenterConfig configCenter) {
builder.configCenter(configCenter);
return this;
}
public ReferenceSettings<S> callbacks(Integer callbacks) {
builder.callbacks(callbacks);
return this;
}
public ReferenceSettings<S> scope(String scope) {
builder.scope(scope);
return this;
}
public ReferenceSettings<S> tag(String tag) {
builder.tag(tag);
return this;
}
public ReferenceSettings<S> timeout(Integer timeout) {
builder.timeout(timeout);
return this;
}
public ReferenceSettings<S> retries(Integer retries) {
builder.retries(retries);
return this;
}
public ReferenceSettings<S> actives(Integer actives) {
builder.actives(actives);
return this;
}
public ReferenceSettings<S> loadbalance(String loadbalance) {
builder.loadbalance(loadbalance);
return this;
}
public ReferenceSettings<S> async(Boolean async) {
builder.async(async);
return this;
}
public ReferenceSettings<S> sent(Boolean sent) {
builder.sent(sent);
return this;
}
public ReferenceSettings<S> mock(String mock) {
builder.mock(mock);
return this;
}
public ReferenceSettings<S> mock(Boolean mock) {
builder.mock(mock);
return this;
}
public ReferenceSettings<S> merger(String merger) {
builder.merger(merger);
return this;
}
public ReferenceSettings<S> cache(String cache) {
builder.cache(cache);
return this;
}
public ReferenceSettings<S> validation(String validation) {
builder.validation(validation);
return this;
}
public ReferenceSettings<S> appendParameters(Map<String, String> appendParameters) {
builder.appendParameters(appendParameters);
return this;
}
public ReferenceSettings<S> appendParameter(String key, String value) {
builder.appendParameter(key, value);
return this;
}
public ReferenceSettings<S> forks(Integer forks) {
builder.forks(forks);
return this;
}
}

View File

@ -1,164 +0,0 @@
/*
* 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.bootstrap;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.builders.RegistryBuilder;
import java.util.Map;
/**
* The settings of {@link RegistryConfig}
*
* @since 2.7.4
*/
public class RegistrySettings extends AbstractSettings {
private final RegistryBuilder builder;
public RegistrySettings(RegistryBuilder builder, DubboBootstrap dubboBootstrap) {
super(dubboBootstrap);
this.builder = builder;
}
public RegistrySettings address(String address) {
builder.address(address);
return this;
}
public RegistrySettings username(String username) {
builder.username(username);
return this;
}
public RegistrySettings password(String password) {
builder.password(password);
return this;
}
public RegistrySettings port(Integer port) {
builder.port(port);
return this;
}
public RegistrySettings protocol(String protocol) {
builder.protocol(protocol);
return this;
}
public RegistrySettings transporter(String transporter) {
builder.transporter(transporter);
return this;
}
@Deprecated
public RegistrySettings transport(String transport) {
builder.transport(transport);
return this;
}
public RegistrySettings server(String server) {
builder.server(server);
return this;
}
public RegistrySettings client(String client) {
builder.client(client);
return this;
}
public RegistrySettings cluster(String cluster) {
builder.cluster(cluster);
return this;
}
public RegistrySettings group(String group) {
builder.group(group);
return this;
}
public RegistrySettings version(String version) {
builder.version(version);
return this;
}
public RegistrySettings timeout(Integer timeout) {
builder.timeout(timeout);
return this;
}
public RegistrySettings session(Integer session) {
builder.session(session);
return this;
}
public RegistrySettings file(String file) {
builder.file(file);
return this;
}
@Deprecated
public RegistrySettings wait(Integer wait) {
builder.wait(wait);
return this;
}
public RegistrySettings isCheck(Boolean check) {
builder.isCheck(check);
return this;
}
public RegistrySettings isDynamic(Boolean dynamic) {
builder.isDynamic(dynamic);
return this;
}
public RegistrySettings register(Boolean register) {
builder.register(register);
return this;
}
public RegistrySettings subscribe(Boolean subscribe) {
builder.subscribe(subscribe);
return this;
}
public RegistrySettings appendParameter(String key, String value) {
builder.appendParameter(key, value);
return this;
}
public RegistrySettings appendParameters(Map<String, String> appendParameters) {
builder.appendParameters(appendParameters);
return this;
}
public RegistrySettings isDefault(Boolean isDefault) {
builder.isDefault(isDefault);
return this;
}
public RegistrySettings simplified(Boolean simplified) {
builder.simplified(simplified);
return this;
}
public RegistrySettings extraKeys(String extraKeys) {
builder.extraKeys(extraKeys);
return this;
}
}

View File

@ -1,384 +0,0 @@
/*
* 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.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.builders.ServiceBuilder;
import java.util.List;
import java.util.Map;
/**
* The settings of {@link ServiceConfig Dubbo service}
*
* @since 2.7.4
*/
public class ServiceSettings<S> extends AbstractSettings {
private final ServiceBuilder<S> builder;
public ServiceSettings(ServiceBuilder<S> builder, DubboBootstrap dubboBootstrap) {
super(dubboBootstrap);
this.builder = builder;
}
public ServiceSettings<S> interfaceName(String interfaceName) {
builder.interfaceName(interfaceName);
return this;
}
public ServiceSettings<S> interfaceClass(Class<?> interfaceClass) {
builder.interfaceClass(interfaceClass);
return this;
}
public ServiceSettings<S> ref(S ref) {
builder.ref(ref);
return this;
}
public ServiceSettings<S> path(String path) {
builder.path(path);
return this;
}
public ServiceSettings<S> addMethod(MethodConfig method) {
builder.addMethod(method);
return this;
}
public ServiceSettings<S> addMethods(List<? extends MethodConfig> methods) {
builder.addMethods(methods);
return this;
}
public ServiceSettings<S> provider(ProviderConfig provider) {
builder.provider(provider);
return this;
}
public ServiceSettings<S> providerIds(String providerIds) {
builder.providerIds(providerIds);
return this;
}
public ServiceSettings<S> generic(String generic) {
builder.generic(generic);
return this;
}
public ServiceSettings<S> mock(String mock) {
builder.mock(mock);
return this;
}
public ServiceSettings<S> mock(Boolean mock) {
builder.mock(mock);
return this;
}
public ServiceSettings<S> version(String version) {
builder.version(version);
return this;
}
public ServiceSettings<S> group(String group) {
builder.group(group);
return this;
}
public ServiceSettings<S> deprecated(Boolean deprecated) {
builder.deprecated(deprecated);
return this;
}
public ServiceSettings<S> delay(Integer delay) {
builder.delay(delay);
return this;
}
public ServiceSettings<S> export(Boolean export) {
builder.export(export);
return this;
}
public ServiceSettings<S> weight(Integer weight) {
builder.weight(weight);
return this;
}
public ServiceSettings<S> document(String document) {
builder.document(document);
return this;
}
public ServiceSettings<S> dynamic(Boolean dynamic) {
builder.dynamic(dynamic);
return this;
}
public ServiceSettings<S> token(String token) {
builder.token(token);
return this;
}
public ServiceSettings<S> token(Boolean token) {
builder.token(token);
return this;
}
public ServiceSettings<S> accesslog(String accesslog) {
builder.accesslog(accesslog);
return this;
}
public ServiceSettings<S> accesslog(Boolean accesslog) {
builder.accesslog(accesslog);
return this;
}
public ServiceSettings<S> addProtocols(List<ProtocolConfig> protocols) {
builder.addProtocols(protocols);
return this;
}
public ServiceSettings<S> addProtocol(ProtocolConfig protocol) {
builder.addProtocol(protocol);
return this;
}
public ServiceSettings<S> protocolIds(String protocolIds) {
builder.protocolIds(protocolIds);
return this;
}
public ServiceSettings<S> executes(Integer executes) {
builder.executes(executes);
return this;
}
public ServiceSettings<S> register(Boolean register) {
builder.register(register);
return this;
}
public ServiceSettings<S> warmup(Integer warmup) {
builder.warmup(warmup);
return this;
}
public ServiceSettings<S> serialization(String serialization) {
builder.serialization(serialization);
return this;
}
@Deprecated
public ServiceSettings<S> local(String local) {
builder.local(local);
return this;
}
@Deprecated
public ServiceSettings<S> local(Boolean local) {
builder.local(local);
return this;
}
public ServiceSettings<S> stub(String stub) {
builder.stub(stub);
return this;
}
public ServiceSettings<S> stub(Boolean stub) {
builder.stub(stub);
return this;
}
public ServiceSettings<S> monitor(MonitorConfig monitor) {
builder.monitor(monitor);
return this;
}
public ServiceSettings<S> monitor(String monitor) {
builder.monitor(monitor);
return this;
}
public ServiceSettings<S> proxy(String proxy) {
builder.proxy(proxy);
return this;
}
public ServiceSettings<S> cluster(String cluster) {
builder.cluster(cluster);
return this;
}
public ServiceSettings<S> filter(String filter) {
builder.filter(filter);
return this;
}
public ServiceSettings<S> listener(String listener) {
builder.listener(listener);
return this;
}
public ServiceSettings<S> owner(String owner) {
builder.owner(owner);
return this;
}
public ServiceSettings<S> connections(Integer connections) {
builder.connections(connections);
return this;
}
public ServiceSettings<S> layer(String layer) {
builder.layer(layer);
return this;
}
public ServiceSettings<S> application(ApplicationConfig application) {
builder.application(application);
return this;
}
public ServiceSettings<S> module(ModuleConfig module) {
builder.module(module);
return this;
}
public ServiceSettings<S> addRegistries(List<RegistryConfig> registries) {
builder.addRegistries(registries);
return this;
}
public ServiceSettings<S> addRegistry(RegistryConfig registry) {
builder.addRegistry(registry);
return this;
}
public ServiceSettings<S> registryIds(String registryIds) {
builder.registryIds(registryIds);
return this;
}
public ServiceSettings<S> onconnect(String onconnect) {
builder.onconnect(onconnect);
return this;
}
public ServiceSettings<S> ondisconnect(String ondisconnect) {
builder.ondisconnect(ondisconnect);
return this;
}
public ServiceSettings<S> metadataReportConfig(MetadataReportConfig metadataReportConfig) {
builder.metadataReportConfig(metadataReportConfig);
return this;
}
public ServiceSettings<S> configCenter(ConfigCenterConfig configCenter) {
builder.configCenter(configCenter);
return this;
}
public ServiceSettings<S> callbacks(Integer callbacks) {
builder.callbacks(callbacks);
return this;
}
public ServiceSettings<S> scope(String scope) {
builder.scope(scope);
return this;
}
public ServiceSettings<S> tag(String tag) {
builder.tag(tag);
return this;
}
public ServiceSettings<S> timeout(Integer timeout) {
builder.timeout(timeout);
return this;
}
public ServiceSettings<S> retries(Integer retries) {
builder.retries(retries);
return this;
}
public ServiceSettings<S> actives(Integer actives) {
builder.actives(actives);
return this;
}
public ServiceSettings<S> loadbalance(String loadbalance) {
builder.loadbalance(loadbalance);
return this;
}
public ServiceSettings<S> async(Boolean async) {
builder.async(async);
return this;
}
public ServiceSettings<S> sent(Boolean sent) {
builder.sent(sent);
return this;
}
public ServiceSettings<S> merger(String merger) {
builder.merger(merger);
return this;
}
public ServiceSettings<S> cache(String cache) {
builder.cache(cache);
return this;
}
public ServiceSettings<S> validation(String validation) {
builder.validation(validation);
return this;
}
public ServiceSettings<S> appendParameters(Map<String, String> appendParameters) {
builder.appendParameters(appendParameters);
return this;
}
public ServiceSettings<S> appendParameter(String key, String value) {
builder.appendParameter(key, value);
return this;
}
public ServiceSettings<S> forks(Integer forks) {
builder.forks(forks);
return this;
}
}

View File

@ -16,11 +16,6 @@
*/
package org.apache.dubbo.bootstrap;
import org.apache.dubbo.config.builders.ApplicationBuilder;
import org.apache.dubbo.config.builders.ProtocolBuilder;
import org.apache.dubbo.config.builders.RegistryBuilder;
import org.apache.dubbo.config.builders.ServiceBuilder;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@ -35,14 +30,5 @@ public class DubboBootstrapTest {
@Test
public void test() throws IOException {
new DubboBootstrap()
.application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
.registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&metadata=remote").build())
.protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
.service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
.start()
.await();
System.in.read();
}
}

View File

@ -16,9 +16,8 @@
*/
package org.apache.dubbo.bootstrap;
import org.apache.dubbo.config.builders.ApplicationBuilder;
import org.apache.dubbo.config.builders.ReferenceBuilder;
import org.apache.dubbo.config.builders.RegistryBuilder;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.context.ConfigManager;
/**
* Dubbo Provider Bootstrap
@ -29,23 +28,27 @@ public class DubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
DubboBootstrap bootstrap = new DubboBootstrap()
.application(ApplicationBuilder.newBuilder().name("dubbo-consumer-demo").build())
.registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo&metadata=remote").build())
.reference(ReferenceBuilder.newBuilder().id("ref").interfaceClass(EchoService.class).build())
new DubboBootstrap()
.application("dubbo-consumer-demo")
// Zookeeper
.registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo"))
// Nacos
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo"))
.reference("ref", builder -> builder.interfaceClass(EchoService.class))
.onlyRegisterProvider(true)
.start()
.await();
// TODO,
// ReferenceConfig<EchoService> referenceConfig = ReferenceConfigCache.getCache().get(EchoService.class.getName(), EchoService.class);
//
// EchoService echoService = referenceConfig.get();
//
// for (int i = 0; i < 500; i++) {
// Thread.sleep(2000L);
// System.out.println(echoService.echo("Hello,World"));
// }
ConfigManager configManager = ConfigManager.getInstance();
ReferenceConfig<EchoService> referenceConfig = configManager.getReferenceConfig("ref");
EchoService echoService = referenceConfig.get();
for (int i = 0; i < 500; i++) {
Thread.sleep(2000L);
System.out.println(echoService.echo("Hello,World"));
}
}
}

View File

@ -16,14 +16,6 @@
*/
package org.apache.dubbo.bootstrap;
import org.apache.dubbo.config.builders.ApplicationBuilder;
import org.apache.dubbo.config.builders.MetadataReportBuilder;
import org.apache.dubbo.config.builders.ProtocolBuilder;
import org.apache.dubbo.config.builders.RegistryBuilder;
import org.apache.dubbo.config.builders.ServiceBuilder;
import java.io.IOException;
/**
* Dubbo Provider Bootstrap
*
@ -31,15 +23,15 @@ import java.io.IOException;
*/
public class DubboServiceProviderBootstrap {
public static void main(String[] args) throws IOException {
public static void main(String[] args) {
new DubboBootstrap()
.application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").metadata("remote").build())
.metadataReport(MetadataReportBuilder.newBuilder().address("zookeeper://127.0.0.1:2181").build())
// .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
.registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service").build())
.protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
.service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
.application("dubbo-provider-demo")
// Zookeeper in service registry type
.registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
// Nacos
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service"))
.protocol(builder -> builder.port(-1).name("dubbo"))
.service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()))
.start()
.await();
}

View File

@ -77,5 +77,9 @@
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -16,15 +16,18 @@
*/
package org.apache.dubbo.common.config.configcenter;
import java.util.EventObject;
/**
* Config change event, immutable.
*
* @see ConfigChangeType
*/
public class ConfigChangeEvent {
public class ConfigChangeEvent extends EventObject {
private final String key;
private final String value;
private final ConfigChangeType changeType;
public ConfigChangeEvent(String key, String value) {
@ -32,6 +35,7 @@ public class ConfigChangeEvent {
}
public ConfigChangeEvent(String key, String value, ConfigChangeType changeType) {
super(key + "=" + value);
this.key = key;
this.value = value;
this.changeType = changeType;

View File

@ -16,10 +16,12 @@
*/
package org.apache.dubbo.common.config.configcenter;
import java.util.EventListener;
/**
* Config listener, will get notified when the config it listens on changes.
*/
public interface ConfigurationListener {
public interface ConfigurationListener extends EventListener {
/**
* Listener call back method. Listener gets notified by this method once there's any change happens on the config

View File

@ -16,16 +16,17 @@
*/
package org.apache.dubbo.common.config.configcenter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.Environment;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import static org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory.getDynamicConfigurationFactory;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
@ -38,7 +39,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
* <li>3. addListener/removeListener, add or remove listeners for governance rules or config items that need to watch.</li>
* </ul>
*/
public interface DynamicConfiguration extends Configuration {
public interface DynamicConfiguration extends Configuration, AutoCloseable {
String DEFAULT_GROUP = "dubbo";
@ -133,6 +134,20 @@ public interface DynamicConfiguration extends Configuration {
*/
String getConfigs(String key, String group, long timeout) throws IllegalStateException;
/**
* Publish Config mapped to the given key under the {@link #DEFAULT_GROUP default group}
*
* @param key the key to represent a configuration
* @param content the content of configuration
* @return <code>true</code> if success, or <code>false</code>
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default boolean publishConfig(String key, String content) throws UnsupportedOperationException {
return publishConfig(key, DEFAULT_GROUP, content);
}
/**
* Publish Config mapped to the given key and the given group.
*
@ -148,45 +163,92 @@ public interface DynamicConfiguration extends Configuration {
}
/**
* Get the config keys by the specified group
* Remove Config mapped to the given key under the {@link #DEFAULT_GROUP default group}
*
* @param group the specified group
* @return the read-only non-null sorted {@link Set set} of config keys
* @param key the key to represent a configuration
* @return the content of configuration was removed
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
default String removeConfig(String key) throws UnsupportedOperationException {
return removeConfig(key, DEFAULT_GROUP);
}
/**
* Remove Config mapped to the given key and the given group.
*
* @param key the key to represent a configuration
* @param group the group where the key belongs to
* @return the content of configuration was removed
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default String removeConfig(String key, String group) throws UnsupportedOperationException {
throw new UnsupportedOperationException("No support");
}
/**
* Get the {@link SortedMap} with with config keys and contents value by the specified group
* Get all groups
*
* @param group the specified group
* @return the read-only non-null sorted {@link SortedMap map}
* @return the read-only non-null {@link Set set} of config keys
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default SortedMap<String, String> getConfigs(String group) throws UnsupportedOperationException {
default Set<String> getConfigGroups() throws UnsupportedOperationException {
throw new UnsupportedOperationException("No support");
}
/**
* Get the config keys by the specified group
*
* @param group the specified group
* @return the read-only non-null {@link Set set} of config keys
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default Set<String> getConfigKeys(String group) throws UnsupportedOperationException {
throw new UnsupportedOperationException("No support");
}
/**
* Get the {@link Map} with with config keys and contents value by the specified group
*
* @param group the specified group
* @return the read-only non-null {@link Map map}
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
default Map<String, String> getConfigs(String group) throws UnsupportedOperationException {
return getConfigs(group, -1);
}
/**
* Get the {@link SortedMap} with with config keys and content value by the specified group
* Get the {@link Map} with with config keys and content value by the specified group
*
* @param group the specified group
* @param timeout the millisecond for timeout
* @return the read-only non-null sorted {@link SortedMap map}
* @return the read-only non-null {@link Map map}
* @throws UnsupportedOperationException If the under layer does not support
* @throws IllegalStateException If timeout exceeds
* @since 2.7.4
*/
default SortedMap<String, String> getConfigs(String group, long timeout) throws UnsupportedOperationException,
default Map<String, String> getConfigs(String group, long timeout) throws UnsupportedOperationException,
IllegalStateException {
SortedMap<String, String> configs = new TreeMap<>();
SortedSet<String> configKeys = getConfigKeys(group);
Map<String, String> configs = new LinkedHashMap<>();
Set<String> configKeys = getConfigKeys(group);
configKeys.forEach(key -> configs.put(key, getConfig(key, group, timeout)));
return Collections.unmodifiableSortedMap(configs);
return Collections.unmodifiableMap(configs);
}
/**
* Close the configuration
*
* @throws Exception
* @since 2.7.4
*/
@Override
default void close() throws Exception {
throw new UnsupportedOperationException();
}
/**
@ -200,4 +262,17 @@ public interface DynamicConfiguration extends Configuration {
.getDefaultExtension()
.getDynamicConfiguration(null));
}
/**
* Get the instance of {@link DynamicConfiguration} by the specified connection {@link URL}
*
* @param connectionURL
* @return non-null
* @since 2.7.4
*/
static DynamicConfiguration getDynamicConfiguration(URL connectionURL) {
String protocol = connectionURL.getProtocol();
DynamicConfigurationFactory factory = getDynamicConfigurationFactory(protocol);
return factory.getDynamicConfiguration(connectionURL);
}
}

View File

@ -17,14 +17,30 @@
package org.apache.dubbo.common.config.configcenter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
*
* The factory interface to create the instance of {@link DynamicConfiguration}
*/
@SPI("nop")
@SPI("file") // 2.7.4 change the default SPI implementation
public interface DynamicConfigurationFactory {
DynamicConfiguration getDynamicConfiguration(URL url);
/**
* Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
* extension of {@link DynamicConfigurationFactory}
*
* @param name the name of extension of {@link DynamicConfigurationFactory}
* @return non-null
* @see 2.7.4
*/
static DynamicConfigurationFactory getDynamicConfigurationFactory(String name) {
Class<DynamicConfigurationFactory> factoryClass = DynamicConfigurationFactory.class;
ExtensionLoader<DynamicConfigurationFactory> loader = getExtensionLoader(factoryClass);
return loader.hasExtension(name) ? loader.getExtension(name) : loader.getDefaultExtension();
}
}

View File

@ -0,0 +1,628 @@
/*
* 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.config.configcenter.file;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.function.ThrowableConsumer;
import org.apache.dubbo.common.function.ThrowableFunction;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import com.sun.nio.file.SensitivityWatchEventModifier;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.String.format;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableMap;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* File-System based {@link DynamicConfiguration} implementation
*
* @since 2.7.4
*/
public class FileSystemDynamicConfiguration implements DynamicConfiguration {
public static final String PARAM_NAME_PREFIX = "dubbo.config-center.";
public static final String CONFIG_CENTER_DIR_PARAM_NAME = PARAM_NAME_PREFIX + "dir";
public static final String THREAD_POOL_PREFIX_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.prefix";
public static final String THREAD_POOL_SIZE_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.size";
public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = PARAM_NAME_PREFIX + "encoding";
public static final String DEFAULT_CONFIG_CENTER_DIR_PATH = System.getProperty("user.home") + File.separator
+ ".dubbo" + File.separator + "config-center";
public static final String DEFAULT_THREAD_POOL_PREFIX = PARAM_NAME_PREFIX + "workers";
public static final String DEFAULT_THREAD_POOL_SIZE = "1";
public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8";
private static final WatchEvent.Kind[] INTEREST_PATH_KINDS = of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
/**
* The class name of {@linkplain sun.nio.fs.PollingWatchService}
*/
private static final String POLLING_WATCH_SERVICE_CLASS_NAME = "sun.nio.fs.PollingWatchService";
private static final int THREAD_POOL_SIZE = 1;
/**
* Logger
*/
private static final Log logger = LogFactory.getLog(FileSystemDynamicConfiguration.class);
/**
* The unmodifiable map for {@link ConfigChangeType} whose key is the {@link WatchEvent.Kind#name() name} of
* {@link WatchEvent.Kind WatchEvent's Kind}
*/
private static final Map<String, ConfigChangeType> CONFIG_CHANGE_TYPES_MAP =
unmodifiableMap(new HashMap<String, ConfigChangeType>() {
// Initializes the elements that is mapping ConfigChangeType
{
put(ENTRY_CREATE.name(), ConfigChangeType.ADDED);
put(ENTRY_DELETE.name(), ConfigChangeType.DELETED);
put(ENTRY_MODIFY.name(), ConfigChangeType.MODIFIED);
}
});
private static final Optional<WatchService> watchService;
/**
* Is Pooling Based Watch Service
*
* @see #detectPoolingBasedWatchService(Optional)
*/
private static final boolean basedPoolingWatchService;
private static final WatchEvent.Modifier[] modifiers;
/**
* the delay to action in seconds. If null, execute indirectly
*/
private static final Integer delay;
/**
* The thread pool for {@link WatchEvent WatchEvents} loop
* It's optional if there is not any {@link ConfigurationListener} registration
*
* @see ThreadPoolExecutor
*/
private static final ThreadPoolExecutor watchEventsLoopThreadPool;
// static initialization
static {
watchService = newWatchService();
basedPoolingWatchService = detectPoolingBasedWatchService(watchService);
modifiers = initWatchEventModifiers();
delay = initDelay(modifiers);
watchEventsLoopThreadPool = newWatchEventsLoopThreadPool();
}
/**
* The Root Directory for config center
*/
private final File rootDirectory;
private final String encoding;
/**
* The thread pool for workers who executes the tasks
*/
private final ThreadPoolExecutor workersThreadPool;
/**
* The {@link Set} of {@link #configDirectory(String) directories} that may be processing,
* <p>
* if {@link #isBasedPoolingWatchService()} is <code>false</code>, this properties will be
* {@link Collections#emptySet() empty}
*
* @see #initProcessingDirectories()
*/
private final Set<File> processingDirectories;
private final Map<File, List<ConfigurationListener>> listenersRepository;
public FileSystemDynamicConfiguration(URL url) {
this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url));
}
public FileSystemDynamicConfiguration(File rootDirectory, String encoding,
String threadPoolPrefixName,
int threadPoolSize
) {
this.rootDirectory = rootDirectory;
this.encoding = encoding;
this.workersThreadPool = initWorkersThreadPool(threadPoolPrefixName, threadPoolSize);
this.processingDirectories = initProcessingDirectories();
this.listenersRepository = new LinkedHashMap<>();
}
private Set<File> initProcessingDirectories() {
return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet();
}
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
doInListener(key, group, (configFilePath, listeners) -> {
if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
ThrowableConsumer.execute(configFilePath, configFile -> {
FileUtils.forceMkdirParent(configFile);
// A rootDirectory to be watched
File configDirectory = configFile.getParentFile();
if (configDirectory != null) {
// Register the configDirectory
configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, modifiers);
}
});
}
// Add into cache
listeners.add(listener);
});
}
@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
doInListener(key, group, (file, listeners) -> {
// Remove into cache
listeners.remove(listener);
});
}
protected File configDirectory(String group) {
String actualGroup = isBlank(group) ? DEFAULT_GROUP : group;
return new File(rootDirectory, actualGroup);
}
protected File configFile(String key, String group) {
return new File(configDirectory(group), key);
}
private void doInListener(String key, String group, BiConsumer<File, List<ConfigurationListener>> consumer) {
watchService.ifPresent(watchService -> {
File configFile = configFile(key, group);
executeMutually(configFile.getParentFile(), () -> {
// process the WatchEvents if not start
if (!isProcessingWatchEvents()) {
processWatchEvents(watchService);
}
List<ConfigurationListener> listeners = getListeners(configFile);
consumer.accept(configFile, listeners);
// Nothing to return
return null;
});
});
}
private static boolean isProcessingWatchEvents() {
return getWatchEventsLoopThreadPool().getActiveCount() > 0;
}
/**
* Process the {@link WatchEvent WatchEvents} loop in async execution
*
* @param watchService {@link WatchService}
*/
private void processWatchEvents(WatchService watchService) {
getWatchEventsLoopThreadPool().execute(() -> { // WatchEvents Loop
while (true) {
WatchKey watchKey = null;
try {
watchKey = watchService.take();
if (watchKey.isValid()) {
for (WatchEvent event : watchKey.pollEvents()) {
WatchEvent.Kind kind = event.kind();
// configChangeType's key to match WatchEvent's Kind
ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name());
if (configChangeType != null) {
Path configDirectoryPath = (Path) watchKey.watchable();
Path currentPath = (Path) event.context();
Path configFilePath = configDirectoryPath.resolve(currentPath);
File configDirectory = configDirectoryPath.toFile();
executeMutually(configDirectory, () -> {
fireConfigChangeEvent(configFilePath.toFile(), configChangeType);
signalConfigDirectory(configDirectory);
return null;
});
}
}
}
} catch (Exception e) {
return;
} finally {
if (watchKey != null) {
// reset
watchKey.reset();
}
}
}
});
}
private void signalConfigDirectory(File configDirectory) {
if (isBasedPoolingWatchService()) {
// remove configDirectory from processing set because it's done
removeProcessingDirectory(configDirectory);
// notify configDirectory
notifyProcessingDirectory(configDirectory);
if (logger.isDebugEnabled()) {
logger.debug(format("The config rootDirectory[%s] is signalled...", configDirectory.getName()));
}
}
}
private void removeProcessingDirectory(File configDirectory) {
processingDirectories.remove(configDirectory);
}
private void notifyProcessingDirectory(File configDirectory) {
configDirectory.notifyAll();
}
private List<ConfigurationListener> getListeners(File configFile) {
return listenersRepository.computeIfAbsent(configFile, p -> new LinkedList<>());
}
private void fireConfigChangeEvent(File configFile, ConfigChangeType configChangeType) {
String key = configFile.getName();
String value = getConfig(configFile, -1L);
// fire ConfigChangeEvent one by one
getListeners(configFile).forEach(listener -> {
try {
listener.process(new ConfigChangeEvent(key, value, configChangeType));
} catch (Throwable e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
});
}
@Override
public String getConfig(String key, String group, long timeout) throws IllegalStateException {
File configFile = configFile(key, group);
return getConfig(configFile, timeout);
}
protected String getConfig(File configFile, long timeout) {
return canRead(configFile) ? execute(() -> readFileToString(configFile, getEncoding()), timeout) : null;
}
private boolean canRead(File file) {
return file.exists() && file.canRead();
}
@Override
public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
return getConfig(key, group, timeout);
}
@Override
public Object getInternalProperty(String key) {
return null;
}
@Override
public boolean publishConfig(String key, String group, String content) {
return delay(key, group, configFile -> {
FileUtils.write(configFile, content, getEncoding());
return true;
});
}
@Override
public String removeConfig(String key, String group) {
return delay(key, group, configFile -> {
String content = getConfig(configFile, -1L);
FileUtils.deleteQuietly(configFile);
return content;
});
}
private ThreadPoolExecutor initWorkersThreadPool(String prefix, int size) {
return (ThreadPoolExecutor) newFixedThreadPool(size, new NamedThreadFactory(prefix));
}
/**
* Delay action for {@link #configFile(String, String) config file}
*
* @param key the key to represent a configuration
* @param group the group where the key belongs to
* @param function the customized {@link Function function} with {@link File}
* @param <V> the computed value
* @return
*/
protected <V> V delay(String key, String group, ThrowableFunction<File, V> function) {
File configFile = configFile(key, group);
// Must be based on PoolingWatchService and has listeners under config file
if (isBasedPoolingWatchService()) {
File configDirectory = configFile.getParentFile();
executeMutually(configDirectory, () -> {
if (hasListeners(configFile) && isProcessing(configDirectory)) {
Integer delay = getDelay();
if (delay != null) {
// wait for delay in seconds
long timeout = SECONDS.toMillis(delay);
if (logger.isDebugEnabled()) {
logger.debug(format("The config[key : %s, group : %s] is about to delay in %d ms.",
key, group, timeout));
}
configDirectory.wait(timeout);
}
}
addProcessing(configDirectory);
return null;
});
}
V value = null;
try {
value = function.apply(configFile);
} catch (Throwable e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
return value;
}
private boolean hasListeners(File configFile) {
return getListeners(configFile).size() > 0;
}
/**
* Is processing on {@link #configDirectory(String) config rootDirectory}
*
* @param configDirectory {@link #configDirectory(String) config rootDirectory}
* @return if processing , return <code>true</code>, or <code>false</code>
*/
private boolean isProcessing(File configDirectory) {
return processingDirectories.contains(configDirectory);
}
private void addProcessing(File configDirectory) {
processingDirectories.add(configDirectory);
}
@Override
public Set<String> getConfigKeys(String group) {
return Stream.of(configDirectory(group).listFiles(File::isFile))
.map(File::getName)
.collect(Collectors.toSet());
}
@Override
public Set<String> getConfigGroups() {
return Stream.of(getRootDirectory().listFiles())
.filter(File::isDirectory)
.map(File::getName)
.collect(Collectors.toSet());
}
@Override
public Map<String, String> getConfigs(String group) throws UnsupportedOperationException {
return getConfigs(group, -1);
}
@Override
public void close() throws Exception {
// TODO
}
private <V> V execute(Callable<V> task, long timeout) {
V value = null;
try {
if (timeout < 1) { // less or equal 0
value = task.call();
} else {
Future<V> future = workersThreadPool.submit(task);
value = future.get(timeout, TimeUnit.MILLISECONDS);
}
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
return value;
}
protected File getRootDirectory() {
return rootDirectory;
}
protected ThreadPoolExecutor getWorkersThreadPool() {
return workersThreadPool;
}
protected String getEncoding() {
return encoding;
}
protected Integer getDelay() {
return delay;
}
/**
* It's whether the implementation of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService}
* or not.
* <p>
*
* @return if based, return <code>true</code>, or <code>false</code>
* @see #detectPoolingBasedWatchService(Optional)
*/
protected static boolean isBasedPoolingWatchService() {
return basedPoolingWatchService;
}
private static String getThreadPoolPrefixName(URL url) {
return getParameter(url, THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX);
}
protected static ThreadPoolExecutor getWatchEventsLoopThreadPool() {
return watchEventsLoopThreadPool;
}
private <V> V executeMutually(Object mutex, Callable<V> callable) {
V value = null;
synchronized (mutex) {
try {
value = callable.call();
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
}
return value;
}
private static <T> T[] of(T... values) {
return values;
}
private static Integer initDelay(WatchEvent.Modifier[] modifiers) {
return Stream.of(modifiers)
.filter(modifier -> modifier instanceof SensitivityWatchEventModifier)
.map(SensitivityWatchEventModifier.class::cast)
.map(SensitivityWatchEventModifier::sensitivityValueInSeconds)
.max(Integer::compareTo)
.orElse(null);
}
private static WatchEvent.Modifier[] initWatchEventModifiers() {
if (isBasedPoolingWatchService()) { // If based on PollingWatchService, High sensitivity will be used
return of(SensitivityWatchEventModifier.HIGH);
} else {
return of();
}
}
/**
* Detect the argument of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService}
* or not.
* <p>
* Some platforms do not provide the native implementation of {@link WatchService}, just use
* {@linkplain sun.nio.fs.PollingWatchService} in periodic poll file modifications.
*
* @param watchService the instance of {@link WatchService}
* @return if based, return <code>true</code>, or <code>false</code>
*/
private static boolean detectPoolingBasedWatchService(Optional<WatchService> watchService) {
String className = watchService.map(Object::getClass).map(Class::getName).orElse(null);
return POLLING_WATCH_SERVICE_CLASS_NAME.equals(className);
}
private static Optional<WatchService> newWatchService() {
Optional<WatchService> watchService = null;
FileSystem fileSystem = FileSystems.getDefault();
try {
watchService = Optional.of(fileSystem.newWatchService());
} catch (IOException e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
watchService = Optional.empty();
}
return watchService;
}
private static File initDirectory(URL url) {
String directoryPath = getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH);
File rootDirectory = new File(getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH));
if (!rootDirectory.exists() && !rootDirectory.mkdirs()) {
throw new IllegalStateException(format("Dubbo config center rootDirectory[%s] can't be created!",
directoryPath));
}
return rootDirectory;
}
private static String getParameter(URL url, String name, String defaultValue) {
if (url != null) {
return url.getParameter(name, defaultValue);
}
return defaultValue;
}
private static String getEncoding(URL url) {
return getParameter(url, CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING);
}
private static int getThreadPoolSize(URL url) {
return Integer.parseInt(getParameter(url, THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE));
}
private static ThreadPoolExecutor newWatchEventsLoopThreadPool() {
return new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE,
0L, MILLISECONDS,
new SynchronousQueue(),
new NamedThreadFactory("dubbo-config-center-watch-events-loop", true));
}
}

View File

@ -14,23 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.bootstrap;
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
/**
* Abstract {@link Settings}
* File-System based {@link DynamicConfigurationFactory} implementation
*
* @since 2.7.4
*/
public class AbstractSettings implements Settings {
private final DubboBootstrap dubboBootstrap;
public AbstractSettings(DubboBootstrap dubboBootstrap) {
this.dubboBootstrap = dubboBootstrap;
}
public class FileSystemDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
@Override
public DubboBootstrap next() {
return dubboBootstrap;
protected DynamicConfiguration createDynamicConfiguration(URL url) {
return new FileSystemDynamicConfiguration(url);
}
}

View File

@ -28,6 +28,7 @@ import static java.util.Collections.emptySortedSet;
* The default extension of {@link DynamicConfiguration}. If user does not specify a config centre, or specifies one
* that is not a valid extension, it will default to this one.
*/
@Deprecated
public class NopDynamicConfiguration implements DynamicConfiguration {
public NopDynamicConfiguration(URL url) {

View File

@ -23,6 +23,7 @@ import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
/**
*
*/
@Deprecated
public class NopDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
@Override

View File

@ -89,9 +89,6 @@ public class CompositeDynamicConfiguration implements DynamicConfiguration {
Object value = null;
for (DynamicConfiguration configuration : configurations) {
value = func.apply(configuration);
if (value != null) {
break;
}
}
return value;
}

View File

@ -21,6 +21,9 @@ import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@ -48,6 +51,7 @@ import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
@ -1127,7 +1131,7 @@ public final class ReflectUtils {
}
return new Type[]{returnType, genericReturnType};
}
/**
* Find the {@link Set} of {@link ParameterizedType}
*
@ -1184,4 +1188,28 @@ public final class ReflectUtils {
return unmodifiableSet(hierarchicalTypes);
}
public static <T> T getProperty(Object bean, String propertyName) {
Class<?> beanClass = bean.getClass();
BeanInfo beanInfo = null;
T propertyValue = null;
try {
beanInfo = Introspector.getBeanInfo(beanClass);
propertyValue = (T) Stream.of(beanInfo.getPropertyDescriptors())
.filter(propertyDescriptor -> propertyName.equals(propertyDescriptor.getName()))
.map(PropertyDescriptor::getReadMethod)
.findFirst()
.map(method -> {
try {
return method.invoke(bean);
} catch (Exception e) {
}
return null;
}).get();
} catch (Exception e) {
}
return propertyValue;
}
}

View File

@ -1 +1,2 @@
nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory
nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory
file=org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory

View File

@ -14,19 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.bootstrap;
package org.apache.dubbo.common.config.configcenter;
import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* The Dubbo settings
* {@link DynamicConfigurationFactory} Test
*
* @since 2.7.4
*/
public interface Settings {
public class DynamicConfigurationFactoryTest {
/**
* Go next settings
*
* @return {@link DubboBootstrap}
*/
DubboBootstrap next();
@Test
public void testDefaultExtension() {
DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension();
assertEquals(FileSystemDynamicConfigurationFactory.class, factory.getClass());
assertEquals(factory, getExtensionLoader(DynamicConfigurationFactory.class).getExtension("file"));
}
}

View File

@ -0,0 +1,169 @@
/*
* 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.config.configcenter.file;
import org.apache.dubbo.common.URL;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.Collections.singleton;
import static org.apache.commons.io.FileUtils.deleteQuietly;
import static org.apache.dubbo.common.URL.valueOf;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link FileSystemDynamicConfiguration} Test
*/
public class FileSystemDynamicConfigurationTest {
private FileSystemDynamicConfiguration configuration;
private static final String KEY = "abc-def-ghi";
private static final String CONTENT = "Hello,World";
@BeforeEach
public void init() {
String classPath = getClassPath();
URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, classPath + File.separator + "config-center");
configuration = new FileSystemDynamicConfiguration(url);
deleteQuietly(configuration.getRootDirectory());
}
private String getClassPath() {
return getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
}
@Test
public void testInit() {
assertEquals(new File(getClassPath(), "config-center"), configuration.getRootDirectory());
assertEquals("UTF-8", configuration.getEncoding());
assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass());
assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize());
assertEquals(1, (configuration.getWorkersThreadPool()).getMaximumPoolSize());
assertNotNull(configuration.getWatchEventsLoopThreadPool());
assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getCorePoolSize());
assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize());
if (configuration.isBasedPoolingWatchService()) {
assertEquals(2, configuration.getDelay());
} else {
assertNull(configuration.getDelay());
}
}
@Test
public void testPublishAndGetConfig() {
assertTrue(configuration.publishConfig(KEY, CONTENT));
assertTrue(configuration.publishConfig(KEY, CONTENT));
assertTrue(configuration.publishConfig(KEY, CONTENT));
assertEquals(CONTENT, configuration.getConfig(KEY));
assertTrue(configuration.getConfigs(null).size() > 0);
}
@Test
public void testPublishAndRemoveConfig() throws InterruptedException {
assertTrue(configuration.publishConfig(KEY, CONTENT));
configuration.addListener(KEY, event -> {
System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
});
assertTrue(configuration.publishConfig(KEY, CONTENT));
assertEquals(CONTENT, configuration.removeConfig(KEY));
Thread.sleep(configuration.getDelay() * 1000);
}
@Test
public void testGetConfigsAndGroups() {
assertTrue(configuration.publishConfig(KEY, CONTENT));
assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP));
assertEquals(singleton(DEFAULT_GROUP), configuration.getConfigGroups());
assertTrue(configuration.publishConfig(KEY, "test", CONTENT));
assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP));
assertTrue(configuration.getConfigGroups().contains(DEFAULT_GROUP));
assertTrue(configuration.getConfigGroups().contains("test"));
}
@Test
public void testAddAndRemoveListener() throws InterruptedException {
configuration.publishConfig(KEY, "A");
AtomicBoolean processedEvent = new AtomicBoolean();
configuration.addListener(KEY, event -> {
processedEvent.set(true);
assertEquals(KEY, event.getKey());
System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
});
configuration.publishConfig(KEY, "B");
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
processedEvent.set(false);
configuration.publishConfig(KEY, "C");
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
processedEvent.set(false);
configuration.publishConfig(KEY, "D");
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
configuration.addListener("test", "test", event -> {
processedEvent.set(true);
assertEquals("test", event.getKey());
System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
});
processedEvent.set(false);
configuration.publishConfig("test", "test", "TEST");
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
configuration.publishConfig("test", "test", "TEST");
configuration.publishConfig("test", "test", "TEST");
configuration.publishConfig("test", "test", "TEST");
processedEvent.set(false);
File keyFile = configuration.configFile(KEY, DEFAULT_GROUP);
FileUtils.deleteQuietly(keyFile);
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
}
}

View File

@ -21,14 +21,14 @@
<!-- 以下是appender的定义 -->
<!-- ===================================================================== -->
<appender name="dubbo" class="org.apache.dubbo.common.utils.DubboAppender">
<param name="File" value="../dubbo.log"/>
<param name="File" value="${user.dir}/dubbo.log"/>
<param name="encoding" value="GBK"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c:%M] - %m%n"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<level value="DEBUG"/>
<appender-ref ref="dubbo"/>
</root>
</log4j:configuration>

View File

@ -255,7 +255,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
/**
*
* Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config
*
* @param provider whether it is the provider side
@ -298,7 +297,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
/**
*
* Load the monitor config from the system properties and conversation it to {@link URL}
*
* @param registryURL
@ -358,7 +356,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
* methods configured in the configuration file are included in the interface of remote service
*
* @param interfaceClass the interface of remote service
* @param methods the methods configured
* @param methods the methods configured
*/
protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
// interface cannot be null
@ -466,15 +464,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
private void convertRegistryIdsToRegistries() {
if (StringUtils.isEmpty(registryIds)) {
if (CollectionUtils.isEmpty(registries)) {
setRegistries(
ConfigManager.getInstance().getDefaultRegistries()
.filter(CollectionUtils::isNotEmpty)
.orElseGet(() -> {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.refresh();
return Arrays.asList(registryConfig);
})
);
List<RegistryConfig> registryConfigs = ConfigManager.getInstance().getDefaultRegistries();
if (registryConfigs.isEmpty()) {
registryConfigs = new ArrayList<>();
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.refresh();
registryConfigs.add(registryConfig);
}
setRegistries(registryConfigs);
}
} else {
String[] ids = COMMA_SPLIT_PATTERN.split(registryIds);
@ -668,7 +665,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
@SuppressWarnings({"unchecked"})
public void setRegistries(List<? extends RegistryConfig> registries) {
ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries, false);
ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries);
this.registries = (List<RegistryConfig>) registries;
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.remoting.Constants;
@ -179,9 +180,14 @@ public class RegistryConfig extends AbstractConfig {
public void setAddress(String address) {
this.address = address;
if (address != null) {
int i = address.indexOf("://");
if (i > 0) {
this.updateIdIfAbsent(address.substring(0, i));
try {
URL url = URL.valueOf(address);
setUsername(url.getUsername());
setPassword(url.getPassword());
setProtocol(url.getProtocol());
setPort(url.getPort());
setParameters(url.getParameters());
} catch (Exception ignored) {
}
}
}

View File

@ -882,15 +882,14 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
private void convertProtocolIdsToProtocols() {
if (StringUtils.isEmpty(protocolIds)) {
if (CollectionUtils.isEmpty(protocols)) {
setProtocols(
ConfigManager.getInstance().getDefaultProtocols()
.filter(CollectionUtils::isNotEmpty)
.orElseGet(() -> {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.refresh();
return new ArrayList<>(Arrays.asList(protocolConfig));
})
);
List<ProtocolConfig> protocolConfigs = ConfigManager.getInstance().getDefaultProtocols();
if (protocolConfigs.isEmpty()) {
protocolConfigs = new ArrayList<>(1);
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.refresh();
protocolConfigs.add(protocolConfig);
}
setProtocols(protocolConfigs);
}
} else {
String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds);

View File

@ -36,7 +36,7 @@ public abstract class AbstractBuilder<C extends AbstractConfig, B extends Abstra
protected String id;
protected String prefix;
protected B id(String id) {
public B id(String id) {
this.id = id;
return getThis();
}

View File

@ -19,8 +19,6 @@ package org.apache.dubbo.config.context;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
@ -34,16 +32,24 @@ import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.StampedLock;
import java.util.stream.Collectors;
import static java.lang.Boolean.TRUE;
import static java.util.Collections.unmodifiableSet;
import static java.util.Optional.ofNullable;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.common.utils.ReflectUtils.getProperty;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
@ -82,40 +88,34 @@ import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
* All workflow internally can rely on ConfigManager.
*/
public class ConfigManager {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
private ApplicationConfig application;
private MonitorConfig monitor;
private ModuleConfig module;
private volatile ModuleConfig module;
private volatile ApplicationConfig application;
private volatile MonitorConfig monitor;
private Map<String, ProtocolConfig> protocols = new ConcurrentHashMap<>();
private Map<String, RegistryConfig> registries = new ConcurrentHashMap<>();
private Map<String, ProviderConfig> providers = new ConcurrentHashMap<>();
private Map<String, ConsumerConfig> consumers = new ConcurrentHashMap<>();
private final Map<String, ProtocolConfig> protocols = new ConcurrentHashMap<>();
private final Map<String, RegistryConfig> registries = new ConcurrentHashMap<>();
private final Map<String, ProviderConfig> providers = new ConcurrentHashMap<>();
private final Map<String, ConsumerConfig> consumers = new ConcurrentHashMap<>();
private final Map<String, ConfigCenterConfig> configCenters = new ConcurrentHashMap<>();
private final Map<String, MetadataReportConfig> metadataConfigs = new ConcurrentHashMap<>();
private final Map<String, ServiceConfig<?>> serviceConfigs = new ConcurrentHashMap<>();
private final Map<String, ReferenceConfig<?>> referenceConfigs = new ConcurrentHashMap<>();
private List<ProtocolConfig> defaultProtocols = new ArrayList<>();
private List<RegistryConfig> defaultRegistries = new ArrayList<>();
private Set<ConfigCenterConfig> configCenters = new HashSet<>();
private Set<MetadataReportConfig> metadataConfigs = new HashSet<>();
private Set<String> registryIds = new HashSet<>();
private Set<String> protocolIds = new HashSet<>();
private List<ServiceConfig<?>> serviceConfigs = new ArrayList<>();
private List<ReferenceConfig<?>> referenceConfigs = new ArrayList<>();
private final StampedLock lock = new StampedLock();
public static ConfigManager getInstance() {
return CONFIG_MANAGER;
}
private ConfigManager() {
}
public Optional<ApplicationConfig> getApplication() {
return Optional.ofNullable(application);
}
// ApplicationConfig correlative methods
public void setApplication(ApplicationConfig application) {
if (application != null) {
@ -124,10 +124,12 @@ public class ConfigManager {
}
}
public Optional<MonitorConfig> getMonitor() {
return Optional.ofNullable(monitor);
public Optional<ApplicationConfig> getApplication() {
return ofNullable(application);
}
// MonitorConfig correlative methods
public void setMonitor(MonitorConfig monitor) {
if (monitor != null) {
checkDuplicate(this.monitor, monitor);
@ -135,10 +137,12 @@ public class ConfigManager {
}
}
public Optional<ModuleConfig> getModule() {
return Optional.ofNullable(module);
public Optional<MonitorConfig> getMonitor() {
return ofNullable(monitor);
}
// ModuleConfig correlative methods
public void setModule(ModuleConfig module) {
if (module != null) {
checkDuplicate(this.module, module);
@ -146,210 +150,175 @@ public class ConfigManager {
}
}
public Set<ConfigCenterConfig> getConfigCenters() {
return configCenters;
public Optional<ModuleConfig> getModule() {
return ofNullable(module);
}
// ConfigCenterConfig correlative methods
public void addConfigCenter(ConfigCenterConfig configCenter) {
if (configCenter != null && !configCenters.contains(configCenter)) {
this.configCenters.add(configCenter);
}
addIfAbsent(configCenter, configCenters);
}
public void addConfigCenter(List<ConfigCenterConfig> configCenters) {
if (CollectionUtils.isNotEmpty(configCenters)) {
this.configCenters.addAll(configCenters);
}
public void addConfigCenters(Iterable<ConfigCenterConfig> configCenters) {
configCenters.forEach(this::addConfigCenter);
}
public Set<MetadataReportConfig> getMetadataConfigs() {
return metadataConfigs;
public ConfigCenterConfig getConfigCenter(String id) {
return configCenters.get(id);
}
public Collection<ConfigCenterConfig> getConfigCenters() {
return configCenters.values();
}
// MetadataReportConfig correlative methods
public void addMetadataReport(MetadataReportConfig metadataReportConfig) {
if (metadataReportConfig != null && !metadataConfigs.contains(metadataReportConfig)) {
this.metadataConfigs.add(metadataReportConfig);
}
addIfAbsent(metadataReportConfig, metadataConfigs);
}
public void addMetadataReport(List<MetadataReportConfig> metadataReportConfigs) {
if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
this.metadataConfigs.addAll(metadataReportConfigs);
}
public void addMetadataReports(Iterable<MetadataReportConfig> metadataReportConfigs) {
metadataReportConfigs.forEach(this::addMetadataReport);
}
public Collection<MetadataReportConfig> getMetadataConfigs() {
return metadataConfigs.values();
}
// MetadataReportConfig correlative methods
public void addProvider(ProviderConfig providerConfig) {
addIfAbsent(providerConfig, providers);
}
public Optional<ProviderConfig> getProvider(String id) {
return Optional.ofNullable(providers.get(id));
return ofNullable(providers.get(id));
}
public Optional<ProviderConfig> getDefaultProvider() {
return Optional.ofNullable(providers.get(DEFAULT_KEY));
return getProvider(DEFAULT_KEY);
}
public void addProvider(ProviderConfig providerConfig) {
if (providerConfig == null) {
return;
}
public Collection<ProviderConfig> getProviders() {
return providers.values();
}
String key = StringUtils.isNotEmpty(providerConfig.getId())
? providerConfig.getId()
: (providerConfig.isDefault() == null || providerConfig.isDefault()) ? DEFAULT_KEY : null;
// ConsumerConfig correlative methods
if (StringUtils.isEmpty(key)) {
throw new IllegalStateException("A ProviderConfig should either has an id or it's the default one, " + providerConfig);
}
if (providers.containsKey(key) && !providerConfig.equals(providers.get(key))) {
logger.warn("Duplicate ProviderConfig found, there already has one default ProviderConfig or more than two ProviderConfigs have the same id, " +
"you can try to give each ProviderConfig a different id. " + providerConfig);
} else {
providers.put(key, providerConfig);
}
public void addConsumer(ConsumerConfig consumerConfig) {
addIfAbsent(consumerConfig, consumers);
}
public Optional<ConsumerConfig> getConsumer(String id) {
return Optional.ofNullable(consumers.get(id));
return ofNullable(consumers.get(id));
}
public Optional<ConsumerConfig> getDefaultConsumer() {
return Optional.ofNullable(consumers.get(DEFAULT_KEY));
return getConsumer(DEFAULT_KEY);
}
public void addConsumer(ConsumerConfig consumerConfig) {
if (consumerConfig == null) {
return;
}
public Collection<ConsumerConfig> getConsumers() {
return consumers.values();
}
String key = StringUtils.isNotEmpty(consumerConfig.getId())
? consumerConfig.getId()
: (consumerConfig.isDefault() == null || consumerConfig.isDefault()) ? DEFAULT_KEY : null;
// ProtocolConfig correlative methods
if (StringUtils.isEmpty(key)) {
throw new IllegalStateException("A ConsumerConfig should either has an id or it's the default one, " + consumerConfig);
}
public void addProtocol(ProtocolConfig protocolConfig) {
addIfAbsent(protocolConfig, protocols);
}
if (consumers.containsKey(key) && !consumerConfig.equals(consumers.get(key))) {
logger.warn("Duplicate ConsumerConfig found, there already has one default ConsumerConfig or more than two ConsumerConfigs have the same id, " +
"you can try to give each ConsumerConfig a different id. " + consumerConfig);
} else {
consumers.put(key, consumerConfig);
public void addProtocols(Iterable<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
if (protocolConfigs != null) {
protocolConfigs.forEach(this::addProtocol);
}
}
public Optional<ProtocolConfig> getProtocol(String id) {
return Optional.ofNullable(protocols.get(id));
return ofNullable(protocols.get(id));
}
public Optional<List<ProtocolConfig>> getDefaultProtocols() {
return Optional.of(defaultProtocols);
public List<ProtocolConfig> getDefaultProtocols() {
return getDefaultConfigs(protocols);
}
public void addProtocols(List<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
if (protocolConfigs != null) {
protocolConfigs.forEach(pc -> this.addProtocol(pc, canBeDefault));
}
public Collection<ProtocolConfig> getProtocols() {
return protocols.values();
}
public void addProtocol(ProtocolConfig protocolConfig, boolean canBeDefault) {
if (protocolConfig == null) {
return;
}
public Set<String> getProtocolIds() {
Set<String> protocolIds = new HashSet<>();
protocolIds.addAll(getSubProperties(Environment.getInstance()
.getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
protocolIds.addAll(getSubProperties(Environment.getInstance()
.getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
// if isDefault is not false and a ProtocolConfig is not specified being false.
if (canBeDefault && (protocolConfig.isDefault() == null || protocolConfig.isDefault())) {
this.defaultProtocols.add(protocolConfig);
}
protocolIds.addAll(protocols.keySet());
return unmodifiableSet(protocolIds);
}
String key = StringUtils.isNotEmpty(protocolConfig.getId())
? protocolConfig.getId()
: DEFAULT_KEY;
if (StringUtils.isEmpty(key)) {
throw new IllegalStateException("A ProtocolConfig should either has an id or it's the default one, " + protocolConfig);
}
// RegistryConfig correlative methods
if (protocols.containsKey(key) && !protocolConfig.equals(protocols.get(key))) {
logger.warn("Duplicate ProtocolConfig found, there already has one default ProtocolConfig or more than two ProtocolConfigs have the same id, " +
"you can try to give each ProtocolConfig a different id. " + protocolConfig);
} else {
protocols.put(key, protocolConfig);
public void addRegistry(RegistryConfig registryConfig) {
addIfAbsent(registryConfig, registries);
}
public void addRegistries(Iterable<RegistryConfig> registryConfigs) {
if (registryConfigs != null) {
registryConfigs.forEach(this::addRegistry);
}
}
public Optional<RegistryConfig> getRegistry(String id) {
return Optional.ofNullable(registries.get(id));
return ofNullable(registries.get(id));
}
public Optional<List<RegistryConfig>> getDefaultRegistries() {
return Optional.of(defaultRegistries);
public List<RegistryConfig> getDefaultRegistries() {
return getDefaultConfigs(registries);
}
public void addRegistries(List<RegistryConfig> registryConfigs, boolean canBeDefault) {
if (registryConfigs != null) {
registryConfigs.forEach(rc -> this.addRegistry(rc, canBeDefault));
}
}
public void addRegistry(RegistryConfig registryConfig, boolean canBeDefault) {
if (registryConfig == null) {
return;
}
if (canBeDefault && (registryConfig.isDefault() == null || registryConfig.isDefault())) {
this.defaultRegistries.add(registryConfig);
}
String key = StringUtils.isNotEmpty(registryConfig.getId())
? registryConfig.getId()
: DEFAULT_KEY;
if (StringUtils.isEmpty(key)) {
throw new IllegalStateException("A RegistryConfig should either has an id or it's the default one, " + registryConfig);
}
if (registries.containsKey(key) && !registryConfig.equals(registries.get(key))) {
logger.warn("Duplicate RegistryConfig found, there already has one default RegistryConfig or more than two RegistryConfigs have the same id, " +
"you can try to give each RegistryConfig a different id. " + registryConfig);
} else {
registries.put(key, registryConfig);
}
}
public void addProtocolIds(List<String> protocolIds) {
this.protocolIds.addAll(protocolIds);
}
public void addRegistryIds(List<String> registryIds) {
this.registryIds.addAll(registryIds);
}
public void addService(ServiceConfig<?> serviceConfig) {
this.serviceConfigs.add(serviceConfig);
}
public void addReference(ReferenceConfig<?> referenceConfig) {
this.referenceConfigs.add(referenceConfig);
public Collection<RegistryConfig> getRegistries() {
return registries.values();
}
public Set<String> getRegistryIds() {
Set<String> configedRegistries = new HashSet<>();
configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
Set<String> registryIds = new HashSet<>();
registryIds.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
REGISTRIES_SUFFIX));
configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
registryIds.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
REGISTRIES_SUFFIX));
configedRegistries.addAll(registryIds);
return configedRegistries;
registryIds.addAll(registries.keySet());
return unmodifiableSet(registryIds);
}
public Set<String> getProtocolIds() {
Set<String> configedProtocols = new HashSet<>();
configedProtocols.addAll(getSubProperties(Environment.getInstance()
.getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
configedProtocols.addAll(getSubProperties(Environment.getInstance()
.getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
// ServiceConfig correlative methods
configedProtocols.addAll(protocolIds);
return configedProtocols;
public void addService(ServiceConfig<?> serviceConfig) {
addIfAbsent(serviceConfig, serviceConfigs);
}
public Collection<ServiceConfig<?>> getServiceConfigs() {
return serviceConfigs.values();
}
public <T> ServiceConfig<T> getServiceConfig(String id) {
return (ServiceConfig<T>) serviceConfigs.get(id);
}
// ReferenceConfig correlative methods
public void addReference(ReferenceConfig<?> referenceConfig) {
addIfAbsent(referenceConfig, referenceConfigs);
}
public Collection<ReferenceConfig<?>> getReferenceConfigs() {
return referenceConfigs.values();
}
public <T> ReferenceConfig<T> getReferenceConfig(String id) {
return (ReferenceConfig<T>) referenceConfigs.get(id);
}
protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
@ -359,62 +328,130 @@ public class ConfigManager {
}).collect(Collectors.toSet());
}
public Map<String, ProtocolConfig> getProtocols() {
return protocols;
}
public Map<String, RegistryConfig> getRegistries() {
return registries;
}
public Map<String, ProviderConfig> getProviders() {
return providers;
}
public Map<String, ConsumerConfig> getConsumers() {
return consumers;
}
public List<ServiceConfig<?>> getServiceConfigs() {
return serviceConfigs;
}
public List<ReferenceConfig<?>> getReferenceConfigs() {
return referenceConfigs;
}
public void refreshAll() {
// refresh all configs here,
getApplication().ifPresent(ApplicationConfig::refresh);
getMonitor().ifPresent(MonitorConfig::refresh);
getModule().ifPresent(ModuleConfig::refresh);
write(() -> {
// refresh all configs here,
getApplication().ifPresent(ApplicationConfig::refresh);
getMonitor().ifPresent(MonitorConfig::refresh);
getModule().ifPresent(ModuleConfig::refresh);
getProtocols().forEach(ProtocolConfig::refresh);
getRegistries().forEach(RegistryConfig::refresh);
getProviders().forEach(ProviderConfig::refresh);
getConsumers().forEach(ConsumerConfig::refresh);
});
getProtocols().values().forEach(ProtocolConfig::refresh);
getRegistries().values().forEach(RegistryConfig::refresh);
getProviders().values().forEach(ProviderConfig::refresh);
getConsumers().values().forEach(ConsumerConfig::refresh);
}
private void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) {
// For test purpose
public void clear() {
write(() -> {
this.application = null;
this.monitor = null;
this.module = null;
this.registries.clear();
this.protocols.clear();
this.providers.clear();
this.consumers.clear();
this.configCenters.clear();
this.metadataConfigs.clear();
});
}
private <V> V write(Callable<V> callable) {
V value = null;
long stamp = lock.writeLock();
try {
value = callable.call();
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
lock.unlockWrite(stamp);
}
return value;
}
private void write(Runnable runnable) {
write(() -> {
runnable.run();
return null;
});
}
private <V> V read(Callable<V> callable) {
long stamp = lock.tryOptimisticRead();
boolean readLock = false;
V value = null;
try {
readLock = !lock.validate(stamp);
if (readLock) {
stamp = lock.readLock();
}
value = callable.call();
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
if (readLock) {
lock.unlockRead(stamp);
}
}
return value;
}
private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) {
if (oldOne != null && !oldOne.equals(newOne)) {
String configName = oldOne.getClass().getSimpleName();
throw new IllegalStateException("Duplicate Config found for " + configName + ", you should use only one unique " + configName + " for one application.");
}
}
// For test purpose
public void clear() {
this.application = null;
this.monitor = null;
this.module = null;
this.registries.clear();
this.protocols.clear();
this.providers.clear();
this.consumers.clear();
this.configCenters.clear();
this.metadataConfigs.clear();
this.registryIds.clear();
this.protocolIds.clear();
private static Map<Class<? extends AbstractConfig>, Map<String, ? extends AbstractConfig>> newMap() {
return new HashMap<>();
}
private static <C extends AbstractConfig> void addIfAbsent(C config, Map<String, C> configsMap) {
if (config == null) {
return;
}
String key = getId(config);
C existedConfig = configsMap.get(key);
if (existedConfig != null && !config.equals(existedConfig)) {
if (logger.isWarnEnabled()) {
String type = config.getClass().getSimpleName();
logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
"you can try to give each %s a different id : %s", type, type, type, type, config));
}
} else {
configsMap.put(key, config);
}
}
static <C extends AbstractConfig> String getId(C config) {
String id = config.getId();
return isNotEmpty(id) ? id : isDefaultConfig(config) ?
config.getClass().getSimpleName() + "#" + DEFAULT_KEY : null;
}
static <C extends AbstractConfig> boolean isDefaultConfig(C config) {
Boolean isDefault = getProperty(config, "default");
return isDefault == null || TRUE.equals(isDefault);
}
static <C extends AbstractConfig> List<C> getDefaultConfigs(Map<String, C> configsMap) {
return configsMap.values()
.stream()
.filter(ConfigManager::isDefaultConfig)
.collect(Collectors.toList());
}
}

View File

@ -38,7 +38,6 @@ public class ServiceInstancePortCustomizer implements ServiceInstanceCustomizer
ConfigManager.getInstance()
.getProtocols()
.values()
.stream()
.findFirst()
.ifPresent(protocolConfig -> {

View File

@ -0,0 +1,71 @@
/*
* 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.config.context;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.config.context.ConfigManager.getInstance;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link ConfigManager} Test
*
* @since 2.7.4
*/
public class ConfigManagerTest {
private ConfigManager configManager = getInstance();
@BeforeEach
public void init() {
configManager.clear();
assertFalse(configManager.getApplication().isPresent());
assertFalse(configManager.getMonitor().isPresent());
assertFalse(configManager.getMonitor().isPresent());
}
@Test
public void testApplicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
configManager.setApplication(applicationConfig);
assertTrue(configManager.getApplication().isPresent());
assertEquals(applicationConfig, configManager.getApplication().get());
}
@Test
public void testMonitorConfig() {
MonitorConfig monitorConfig = new MonitorConfig();
configManager.setMonitor(monitorConfig);
assertTrue(configManager.getMonitor().isPresent());
assertEquals(monitorConfig, configManager.getMonitor().get());
}
@Test
public void tesModuleConfig() {
ModuleConfig config = new ModuleConfig();
configManager.setModule(config);
assertTrue(configManager.getModule().isPresent());
assertEquals(config, configManager.getModule().get());
}
}

View File

@ -49,9 +49,9 @@ public class ConfigurableMetadataServiceExporterTest {
configManager.setApplication(applicationConfig);
// Add ProtocolConfig
configManager.addProtocol(protocolConfig(), true);
configManager.addProtocol(protocolConfig());
// Add RegistryConfig
configManager.addRegistry(registryConfig(), true);
configManager.addRegistry(registryConfig());
}
private static ProtocolConfig protocolConfig() {

View File

@ -21,8 +21,22 @@
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
">
<bean id="a" class="java.lang.String" abstract="true">
<property name="value" value="1" />
</bean>
<bean id="b" parent="a" >
<property name="value2" value="2" />
</bean>
<bean id="c" class="java.lang.Object">
<property name="b" ref="b" />
</bean>
<!-- 当前应用信息配置 -->
<dubbo:application name="dubbo-spring-test"/>
<dubbo:application name="dubbo-spring-test" >
<dubbo:parameter key="" value="" />
</dubbo:application>
<!-- 连接注册中心配置 -->
<dubbo:registry address="N/A"/>

View File

@ -94,12 +94,19 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
}
public void publishNacosConfig(String key, String value) {
String[] keyAndGroup = getKeyAndGroup(key);
publishConfig(keyAndGroup[0], keyAndGroup[1], value);
}
@Override
public boolean publishConfig(String key, String group, String content) {
boolean published = false;
try {
String[] keyAndGroup = getKeyAndGroup(key);
configService.publishConfig(keyAndGroup[0], keyAndGroup[1], value);
published = configService.publishConfig(key, group, content);
} catch (NacosException e) {
logger.error(e.getErrMsg());
}
return published;
}
private String[] getKeyAndGroup(String key) {
@ -107,7 +114,7 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
if (i < 0) {
return new String[]{key, null};
} else {
return new String[]{key.substring(0, i), key.substring(i+1)};
return new String[]{key.substring(0, i), key.substring(i + 1)};
}
}

View File

@ -15,14 +15,15 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>21</version>
<relativePath />
<relativePath/>
</parent>
<groupId>org.apache.dubbo</groupId>
@ -135,6 +136,7 @@
<log4j_version>1.2.16</log4j_version>
<logback_version>1.2.2</logback_version>
<log4j2_version>2.11.1</log4j2_version>
<commons_io_version>2.6</commons_io_version>
<embedded_redis_version>0.6</embedded_redis_version>
@ -442,6 +444,11 @@
<artifactId>commons-logging</artifactId>
<version>${jcl_version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons_io_version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>

View File

@ -0,0 +1,114 @@
/*
* 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.registry.client;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration;
import org.apache.dubbo.event.EventListener;
import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import java.util.Set;
import static com.alibaba.fastjson.JSON.toJSONString;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
* File System {@link ServiceDiscovery} implementation
*
* @see FileSystemDynamicConfiguration
* @since 2.7.4
*/
public class FileSystemServiceDiscovery implements ServiceDiscovery, EventListener<ServiceInstancesChangedEvent> {
private final URL connectionURL;
private FileSystemDynamicConfiguration dynamicConfiguration;
public FileSystemServiceDiscovery(URL connectionURL) {
this.connectionURL = connectionURL;
}
@Override
public void onEvent(ServiceInstancesChangedEvent event) {
}
@Override
public void start() {
if (dynamicConfiguration == null) {
dynamicConfiguration = createDynamicConfiguration(connectionURL);
}
}
@Override
public void stop() {
try {
if (dynamicConfiguration != null) {
dynamicConfiguration.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private String getConfigKey(ServiceInstance serviceInstance) {
return serviceInstance.getId();
}
private String getConfigGroup(ServiceInstance serviceInstance) {
return serviceInstance.getServiceName();
}
@Override
public void register(ServiceInstance serviceInstance) throws RuntimeException {
String key = getConfigKey(serviceInstance);
String group = getConfigGroup(serviceInstance);
String content = toJSONString(serviceInstance);
dynamicConfiguration.publishConfig(key, group, content);
}
@Override
public void update(ServiceInstance serviceInstance) throws RuntimeException {
register(serviceInstance);
}
@Override
public void unregister(ServiceInstance serviceInstance) throws RuntimeException {
String key = getConfigKey(serviceInstance);
String group = getConfigGroup(serviceInstance);
dynamicConfiguration.removeConfig(key, group);
}
@Override
public Set<String> getServices() {
return null;
}
@Override
public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws
NullPointerException, IllegalArgumentException {
}
private static FileSystemDynamicConfiguration createDynamicConfiguration(URL connectionURL) {
String protocol = connectionURL.getProtocol();
DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getExtension(protocol);
return (FileSystemDynamicConfiguration) factory.getDynamicConfiguration(connectionURL);
}
}