All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.dubbo.config.bootstrap.DubboBootstrap Maven / Gradle / Ivy

There is a newer version: 3.3.2
Show newest version
/*
 * 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.bootstrap;

import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.ReferenceCache;
import org.apache.dubbo.common.deploy.ApplicationDeployer;
import org.apache.dubbo.common.deploy.DeployListenerAdapter;
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.threadpool.manager.ExecutorRepository;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
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.MetricsConfig;
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.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.bootstrap.builders.ApplicationBuilder;
import org.apache.dubbo.config.bootstrap.builders.ConfigCenterBuilder;
import org.apache.dubbo.config.bootstrap.builders.ConsumerBuilder;
import org.apache.dubbo.config.bootstrap.builders.MetadataReportBuilder;
import org.apache.dubbo.config.bootstrap.builders.ProtocolBuilder;
import org.apache.dubbo.config.bootstrap.builders.ProviderBuilder;
import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder;
import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder;
import org.apache.dubbo.config.bootstrap.builders.ServiceBuilder;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

import static java.util.Collections.singletonList;

/**
 * See {@link ApplicationModel} and {@link ExtensionLoader} for why this class is designed to be singleton.
 * 

* The bootstrap class of Dubbo *

* Get singleton instance by calling static method {@link #getInstance()}. * Designed as singleton because some classes inside Dubbo, such as ExtensionLoader, are designed only for one instance per process. * * @since 2.7.5 */ public final class DubboBootstrap { private static final String NAME = DubboBootstrap.class.getSimpleName(); private static final Logger logger = LoggerFactory.getLogger(DubboBootstrap.class); private static final ConcurrentMap instanceMap = new ConcurrentHashMap<>(); private static volatile DubboBootstrap instance; private final AtomicBoolean awaited = new AtomicBoolean(false); private volatile BootstrapTakeoverMode takeoverMode = BootstrapTakeoverMode.AUTO; private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private final ExecutorRepository executorRepository; private final Environment environment; private final ApplicationModel applicationModel; private final ConfigManager configManager; private final ApplicationDeployer applicationDeployer; /** * See {@link ApplicationModel} and {@link ExtensionLoader} for why DubboBootstrap is designed to be singleton. */ public static DubboBootstrap getInstance() { if (instance == null) { synchronized (DubboBootstrap.class) { if (instance == null) { instance = DubboBootstrap.getInstance(ApplicationModel.defaultModel()); } } } return instance; } public static DubboBootstrap getInstance(ApplicationModel applicationModel) { return ConcurrentHashMapUtils.computeIfAbsent( instanceMap, applicationModel, _k -> new DubboBootstrap(applicationModel)); } public static DubboBootstrap newInstance() { return getInstance(FrameworkModel.defaultModel().newApplication()); } public static DubboBootstrap newInstance(FrameworkModel frameworkModel) { return getInstance(frameworkModel.newApplication()); } /** * Try reset dubbo status for new instance. * * @deprecated For testing purposes only */ @Deprecated public static void reset() { reset(true); } /** * Try reset dubbo status for new instance. * * @deprecated For testing purposes only */ @Deprecated public static void reset(boolean destroy) { if (destroy) { if (instance != null) { instance.destroy(); instance = null; } FrameworkModel.destroyAll(); } else { instance = null; } ApplicationModel.reset(); } private DubboBootstrap(ApplicationModel applicationModel) { this.applicationModel = applicationModel; configManager = applicationModel.getApplicationConfigManager(); environment = applicationModel.modelEnvironment(); executorRepository = ExecutorRepository.getInstance(applicationModel); applicationDeployer = applicationModel.getDeployer(); // listen deploy events applicationDeployer.addDeployListener(new DeployListenerAdapter() { @Override public void onStarted(ApplicationModel scopeModel) { notifyStarted(applicationModel); } @Override public void onStopped(ApplicationModel scopeModel) { notifyStopped(applicationModel); } @Override public void onFailure(ApplicationModel scopeModel, Throwable cause) { notifyStopped(applicationModel); } }); // register DubboBootstrap bean applicationModel.getBeanFactory().registerBean(this); } private void notifyStarted(ApplicationModel applicationModel) { ExtensionLoader exts = applicationModel.getExtensionLoader(DubboBootstrapStartStopListener.class); exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(DubboBootstrap.this)); } private void notifyStopped(ApplicationModel applicationModel) { ExtensionLoader exts = applicationModel.getExtensionLoader(DubboBootstrapStartStopListener.class); exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(DubboBootstrap.this)); executeMutually(() -> { awaited.set(true); condition.signalAll(); }); instanceMap.remove(applicationModel); } /** * Initialize */ public void initialize() { applicationDeployer.initialize(); } /** * Start dubbo application and wait for finish */ public DubboBootstrap start() { this.start(true); return this; } /** * Start dubbo application * * @param wait If true, wait for startup to complete, or else no waiting. * @return */ public DubboBootstrap start(boolean wait) { Future future = applicationDeployer.start(); if (wait) { try { future.get(); } catch (Exception e) { throw new IllegalStateException("await dubbo application start finish failure", e); } } return this; } /** * Start dubbo application but no wait for finish. * * @return the future object */ public Future asyncStart() { return applicationDeployer.start(); } /** * Stop dubbo application * * @return * @throws IllegalStateException */ public DubboBootstrap stop() throws IllegalStateException { destroy(); return this; } public void destroy() { applicationModel.destroy(); } public boolean isInitialized() { return applicationDeployer.isInitialized(); } public boolean isPending() { return applicationDeployer.isPending(); } /** * @return true if the dubbo application is starting or has been started. */ public boolean isRunning() { return applicationDeployer.isRunning(); } /** * @return true if the dubbo application is starting. * @see #isStarted() */ public boolean isStarting() { return applicationDeployer.isStarting(); } /** * @return true if the dubbo application has been started. * @see #start() * @see #isStarting() */ public boolean isStarted() { return applicationDeployer.isStarted(); } public boolean isCompletion() { return applicationDeployer.isCompletion(); } /** * @return true if the dubbo application is stopping. * @see #isStopped() */ public boolean isStopping() { return applicationDeployer.isStopping(); } /** * @return true if the dubbo application is stopping. * @see #isStopped() */ public boolean isStopped() { return applicationDeployer.isStopped(); } /** * Block current thread to be await. * * @return {@link DubboBootstrap} */ public DubboBootstrap await() { // if has been waited, no need to wait again, return immediately if (!awaited.get()) { if (!isStopped()) { executeMutually(() -> { while (!awaited.get()) { if (logger.isInfoEnabled()) { logger.info(NAME + " awaiting ..."); } try { condition.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); } } return this; } public ReferenceCache getCache() { return applicationDeployer.getReferenceCache(); } private void executeMutually(Runnable runnable) { try { lock.lock(); runnable.run(); } finally { lock.unlock(); } } public ApplicationConfig getApplication() { return configManager.getApplicationOrElseThrow(); } public void setTakeoverMode(BootstrapTakeoverMode takeoverMode) { // TODO this.started.set(false); this.takeoverMode = takeoverMode; } public BootstrapTakeoverMode getTakeoverMode() { return takeoverMode; } public ApplicationModel getApplicationModel() { return applicationModel; } public ConfigManager getConfigManager() { return configManager; } // MetadataReportConfig correlative methods public DubboBootstrap metadataReport(Consumer consumerBuilder) { return metadataReport(null, consumerBuilder); } public DubboBootstrap metadataReport(String id, Consumer consumerBuilder) { MetadataReportBuilder metadataReportBuilder = createMetadataReportBuilder(id); consumerBuilder.accept(metadataReportBuilder); return this; } public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) { configManager.addMetadataReport(metadataReportConfig); return this; } public DubboBootstrap metadataReports(List metadataReportConfigs) { if (CollectionUtils.isEmpty(metadataReportConfigs)) { return this; } 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 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) { applicationConfig.setScopeModel(applicationModel); configManager.setApplication(applicationConfig); return this; } // {@link RegistryConfig} correlative methods /** * Add an instance of {@link RegistryConfig} * * @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder} * @return current {@link DubboBootstrap} instance */ public DubboBootstrap registry(Consumer consumerBuilder) { return registry(null, 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 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) { registryConfig.setScopeModel(applicationModel); configManager.addRegistry(registryConfig); return this; } /** * Add an instance of {@link RegistryConfig} * * @param registryConfigs the multiple instances of {@link RegistryConfig} * @return current {@link DubboBootstrap} instance */ public DubboBootstrap registries(List registryConfigs) { if (CollectionUtils.isEmpty(registryConfigs)) { return this; } registryConfigs.forEach(this::registry); return this; } // {@link ProtocolConfig} correlative methods public DubboBootstrap protocol(Consumer consumerBuilder) { return protocol(null, consumerBuilder); } public DubboBootstrap protocol(String id, Consumer consumerBuilder) { ProtocolBuilder builder = createProtocolBuilder(id); consumerBuilder.accept(builder); return protocol(builder.build()); } public DubboBootstrap protocol(ProtocolConfig protocolConfig) { return protocols(singletonList(protocolConfig)); } public DubboBootstrap protocols(List protocolConfigs) { if (CollectionUtils.isEmpty(protocolConfigs)) { return this; } for (ProtocolConfig protocolConfig : protocolConfigs) { protocolConfig.setScopeModel(applicationModel); configManager.addProtocol(protocolConfig); } return this; } // {@link ServiceConfig} correlative methods public DubboBootstrap service(Consumer> consumerBuilder) { return service(null, consumerBuilder); } public DubboBootstrap service(String id, Consumer> consumerBuilder) { return service(createServiceConfig(id, consumerBuilder)); } private ServiceConfig createServiceConfig(String id, Consumer> consumerBuilder) { ServiceBuilder builder = createServiceBuilder(id); consumerBuilder.accept(builder); return builder.build(); } public DubboBootstrap services(List serviceConfigs) { if (CollectionUtils.isEmpty(serviceConfigs)) { return this; } for (ServiceConfig serviceConfig : serviceConfigs) { this.service(serviceConfig); } return this; } public DubboBootstrap service(ServiceConfig serviceConfig) { this.service(serviceConfig, applicationModel.getDefaultModule()); return this; } public DubboBootstrap service(ServiceConfig serviceConfig, ModuleModel moduleModel) { serviceConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().addService(serviceConfig); return this; } // {@link Reference} correlative methods public DubboBootstrap reference(Consumer> consumerBuilder) { return reference(null, consumerBuilder); } public DubboBootstrap reference(String id, Consumer> consumerBuilder) { return reference(createReferenceConfig(id, consumerBuilder)); } private ReferenceConfig createReferenceConfig(String id, Consumer> consumerBuilder) { ReferenceBuilder builder = createReferenceBuilder(id); consumerBuilder.accept(builder); return builder.build(); } public DubboBootstrap references(List referenceConfigs) { if (CollectionUtils.isEmpty(referenceConfigs)) { return this; } for (ReferenceConfig referenceConfig : referenceConfigs) { this.reference(referenceConfig); } return this; } public DubboBootstrap reference(ReferenceConfig referenceConfig) { return reference(referenceConfig, applicationModel.getDefaultModule()); } public DubboBootstrap reference(ReferenceConfig referenceConfig, ModuleModel moduleModel) { referenceConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().addReference(referenceConfig); return this; } // {@link ProviderConfig} correlative methods public DubboBootstrap provider(Consumer builderConsumer) { provider(null, builderConsumer); return this; } public DubboBootstrap provider(String id, Consumer builderConsumer) { this.provider(createProviderConfig(id, builderConsumer)); return this; } private ProviderConfig createProviderConfig(String id, Consumer builderConsumer) { ProviderBuilder builder = createProviderBuilder(id); builderConsumer.accept(builder); return builder.build(); } public DubboBootstrap provider(ProviderConfig providerConfig) { return this.provider(providerConfig, applicationModel.getDefaultModule()); } public DubboBootstrap providers(List providerConfigs) { for (ProviderConfig providerConfig : providerConfigs) { this.provider(providerConfig, applicationModel.getDefaultModule()); } return this; } public DubboBootstrap provider(ProviderConfig providerConfig, ModuleModel moduleModel) { providerConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().addProvider(providerConfig); return this; } // {@link ConsumerConfig} correlative methods public DubboBootstrap consumer(Consumer builderConsumer) { return consumer(null, builderConsumer); } public DubboBootstrap consumer(String id, Consumer builderConsumer) { return consumer(createConsumerConfig(id, builderConsumer)); } private ConsumerConfig createConsumerConfig(String id, Consumer builderConsumer) { ConsumerBuilder builder = createConsumerBuilder(id); builderConsumer.accept(builder); return builder.build(); } public DubboBootstrap consumer(ConsumerConfig consumerConfig) { return this.consumer(consumerConfig, applicationModel.getDefaultModule()); } public DubboBootstrap consumers(List consumerConfigs) { for (ConsumerConfig consumerConfig : consumerConfigs) { this.consumer(consumerConfig, applicationModel.getDefaultModule()); } return this; } public DubboBootstrap consumer(ConsumerConfig consumerConfig, ModuleModel moduleModel) { consumerConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().addConsumer(consumerConfig); return this; } public DubboBootstrap module(ModuleConfig moduleConfig) { this.module(moduleConfig, applicationModel.getDefaultModule()); return this; } public DubboBootstrap module(ModuleConfig moduleConfig, ModuleModel moduleModel) { moduleConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().setModule(moduleConfig); return this; } // module configs end // {@link ConfigCenterConfig} correlative methods public DubboBootstrap configCenter(Consumer consumerBuilder) { return configCenter(null, consumerBuilder); } public DubboBootstrap configCenter(String id, Consumer consumerBuilder) { ConfigCenterBuilder configCenterBuilder = createConfigCenterBuilder(id); consumerBuilder.accept(configCenterBuilder); return this; } public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) { configCenterConfig.setScopeModel(applicationModel); configManager.addConfigCenter(configCenterConfig); return this; } public DubboBootstrap configCenters(List configCenterConfigs) { if (CollectionUtils.isEmpty(configCenterConfigs)) { return this; } for (ConfigCenterConfig configCenterConfig : configCenterConfigs) { this.configCenter(configCenterConfig); } return this; } public DubboBootstrap monitor(MonitorConfig monitor) { monitor.setScopeModel(applicationModel); configManager.setMonitor(monitor); return this; } public DubboBootstrap metrics(MetricsConfig metrics) { metrics.setScopeModel(applicationModel); configManager.setMetrics(metrics); return this; } public DubboBootstrap tracing(TracingConfig tracing) { tracing.setScopeModel(applicationModel); configManager.setTracing(tracing); return this; } public DubboBootstrap ssl(SslConfig sslConfig) { sslConfig.setScopeModel(applicationModel); configManager.setSsl(sslConfig); return this; } /* serve for builder apis, begin */ private ApplicationBuilder createApplicationBuilder(String name) { return new ApplicationBuilder().name(name); } private RegistryBuilder createRegistryBuilder(String id) { return new RegistryBuilder().id(id); } private MetadataReportBuilder createMetadataReportBuilder(String id) { return new MetadataReportBuilder().id(id); } private ConfigCenterBuilder createConfigCenterBuilder(String id) { return new ConfigCenterBuilder().id(id); } private ProtocolBuilder createProtocolBuilder(String id) { return new ProtocolBuilder().id(id); } private ServiceBuilder createServiceBuilder(String id) { return new ServiceBuilder().id(id); } private ReferenceBuilder createReferenceBuilder(String id) { return new ReferenceBuilder().id(id); } private ProviderBuilder createProviderBuilder(String id) { return new ProviderBuilder().id(id); } private ConsumerBuilder createConsumerBuilder(String id) { return new ConsumerBuilder().id(id); } /* serve for builder apis, end */ public Module newModule() { return new Module(applicationModel.newModule()); } public Module newModule(ModuleConfig moduleConfig) { ModuleModel moduleModel = applicationModel.newModule(); moduleConfig.setScopeModel(moduleModel); moduleModel.getConfigManager().setModule(moduleConfig); return new Module(moduleModel); } public DubboBootstrap endModule() { return this; } public class Module { private ModuleModel moduleModel; private DubboBootstrap bootstrap; public Module(ModuleModel moduleModel) { this.moduleModel = moduleModel; this.bootstrap = DubboBootstrap.this; } public DubboBootstrap endModule() { return this.bootstrap.endModule(); } public ModuleModel getModuleModel() { return moduleModel; } public Module config(ModuleConfig moduleConfig) { this.moduleModel.getConfigManager().setModule(moduleConfig); return this; } // {@link ServiceConfig} correlative methods public Module service(Consumer> consumerBuilder) { return service(null, consumerBuilder); } public Module service(String id, Consumer> consumerBuilder) { return service(createServiceConfig(id, consumerBuilder)); } public Module services(List serviceConfigs) { if (CollectionUtils.isEmpty(serviceConfigs)) { return this; } for (ServiceConfig serviceConfig : serviceConfigs) { this.service(serviceConfig); } return this; } public Module service(ServiceConfig serviceConfig) { DubboBootstrap.this.service(serviceConfig, moduleModel); return this; } // {@link Reference} correlative methods public Module reference(Consumer> consumerBuilder) { return reference(null, consumerBuilder); } public Module reference(String id, Consumer> consumerBuilder) { return reference(createReferenceConfig(id, consumerBuilder)); } public Module reference(ReferenceConfig referenceConfig) { DubboBootstrap.this.reference(referenceConfig, moduleModel); return this; } public Module references(List referenceConfigs) { if (CollectionUtils.isEmpty(referenceConfigs)) { return this; } for (ReferenceConfig referenceConfig : referenceConfigs) { this.reference(referenceConfig); } return this; } // {@link ProviderConfig} correlative methods public Module provider(Consumer builderConsumer) { return provider(null, builderConsumer); } public Module provider(String id, Consumer builderConsumer) { return provider(createProviderConfig(id, builderConsumer)); } public Module provider(ProviderConfig providerConfig) { DubboBootstrap.this.provider(providerConfig, moduleModel); return this; } public Module providers(List providerConfigs) { if (CollectionUtils.isEmpty(providerConfigs)) { return this; } for (ProviderConfig providerConfig : providerConfigs) { DubboBootstrap.this.provider(providerConfig, moduleModel); } return this; } // {@link ConsumerConfig} correlative methods public Module consumer(Consumer builderConsumer) { return consumer(null, builderConsumer); } public Module consumer(String id, Consumer builderConsumer) { return consumer(createConsumerConfig(id, builderConsumer)); } public Module consumer(ConsumerConfig consumerConfig) { DubboBootstrap.this.consumer(consumerConfig, moduleModel); return this; } public Module consumers(List consumerConfigs) { if (CollectionUtils.isEmpty(consumerConfigs)) { return this; } for (ConsumerConfig consumerConfig : consumerConfigs) { DubboBootstrap.this.consumer(consumerConfig, moduleModel); } return this; } } }