org.apache.dubbo.rpc.model.ApplicationModel Maven / Gradle / Ivy
Show all versions of dubbo Show documentation
/*
* 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.rpc.model;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.context.ApplicationExt;
import org.apache.dubbo.common.deploy.ApplicationDeployer;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
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.Assert;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
/**
* {@link ExtensionLoader}, {@code DubboBootstrap} and this class are at present designed to be
* singleton or static (by itself totally static or uses some static fields). So the instances
* returned from them are of process scope. If you want to support multiple dubbo servers in one
* single process, you may need to refactor those three classes.
*
* Represent an application which is using Dubbo and store basic metadata info for using
* during the processing of RPC invoking.
*
* ApplicationModel includes many ProviderModel which is about published services
* and many Consumer Model which is about subscribed services.
*
*/
public class ApplicationModel extends ScopeModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
public static final String NAME = "ApplicationModel";
private final List moduleModels = new CopyOnWriteArrayList<>();
private final List pubModuleModels = new CopyOnWriteArrayList<>();
private volatile Environment environment;
private volatile ConfigManager configManager;
private volatile ServiceRepository serviceRepository;
private volatile ApplicationDeployer deployer;
private final FrameworkModel frameworkModel;
private final ModuleModel internalModule;
private volatile ModuleModel defaultModule;
// internal module index is 0, default module index is 1
private final AtomicInteger moduleIndex = new AtomicInteger(0);
// --------- static methods ----------//
public static ApplicationModel ofNullable(ApplicationModel applicationModel) {
if (applicationModel != null) {
return applicationModel;
} else {
return defaultModel();
}
}
/**
* During destroying the default FrameworkModel, the FrameworkModel.defaultModel() or ApplicationModel.defaultModel()
* will return a broken model, maybe cause unpredictable problem.
* Recommendation: Avoid using the default model as much as possible.
*
* @return the global default ApplicationModel
*/
public static ApplicationModel defaultModel() {
// should get from default FrameworkModel, avoid out of sync
return FrameworkModel.defaultModel().defaultApplication();
}
// ------------- instance methods ---------------//
protected ApplicationModel(FrameworkModel frameworkModel) {
this(frameworkModel, false);
}
protected ApplicationModel(FrameworkModel frameworkModel, boolean isInternal) {
super(frameworkModel, ExtensionScope.APPLICATION, isInternal);
synchronized (instLock) {
Assert.notNull(frameworkModel, "FrameworkModel can not be null");
this.frameworkModel = frameworkModel;
frameworkModel.addApplication(this);
if (LOGGER.isInfoEnabled()) {
LOGGER.info(getDesc() + " is created");
}
initialize();
this.internalModule = new ModuleModel(this, true);
this.serviceRepository = new ServiceRepository(this);
ExtensionLoader extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
Set listenerNames = extensionLoader.getSupportedExtensions();
for (String listenerName : listenerNames) {
extensionLoader.getExtension(listenerName).init();
}
initApplicationExts();
ExtensionLoader initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
Set initializers = initializerExtensionLoader.getSupportedExtensionInstances();
for (ScopeModelInitializer initializer : initializers) {
initializer.initializeApplicationModel(this);
}
Assert.notNull(getApplicationServiceRepository(), "ApplicationServiceRepository can not be null");
Assert.notNull(getApplicationConfigManager(), "ApplicationConfigManager can not be null");
Assert.assertTrue(getApplicationConfigManager().isInitialized(), "ApplicationConfigManager can not be initialized");
}
}
// already synchronized in constructor
private void initApplicationExts() {
Set exts = this.getExtensionLoader(ApplicationExt.class).getSupportedExtensionInstances();
for (ApplicationExt ext : exts) {
ext.initialize();
}
}
@Override
protected void onDestroy() {
synchronized (instLock) {
// 1. remove from frameworkModel
frameworkModel.removeApplication(this);
// 2. pre-destroy, set stopping
if (deployer != null) {
// destroy registries and unregister services from registries first to notify consumers to stop consuming this instance.
deployer.preDestroy();
}
// 3. Try to destroy protocols to stop this instance from receiving new requests from connections
frameworkModel.tryDestroyProtocols();
// 4. destroy application resources
for (ModuleModel moduleModel : moduleModels) {
if (moduleModel != internalModule) {
moduleModel.destroy();
}
}
// 5. destroy internal module later
internalModule.destroy();
// 6. post-destroy, release registry resources
if (deployer != null) {
deployer.postDestroy();
}
// 7. destroy other resources (e.g. ZookeeperTransporter )
notifyDestroy();
if (environment != null) {
environment.destroy();
environment = null;
}
if (configManager != null) {
configManager.destroy();
configManager = null;
}
if (serviceRepository != null) {
serviceRepository.destroy();
serviceRepository = null;
}
// 8. destroy framework if none application
frameworkModel.tryDestroy();
}
}
public FrameworkModel getFrameworkModel() {
return frameworkModel;
}
public ModuleModel newModule() {
synchronized (instLock) {
return new ModuleModel(this);
}
}
@Override
public Environment getModelEnvironment() {
if (environment == null) {
environment = (Environment) this.getExtensionLoader(ApplicationExt.class)
.getExtension(Environment.NAME);
}
return environment;
}
public ConfigManager getApplicationConfigManager() {
if (configManager == null) {
configManager = (ConfigManager) this.getExtensionLoader(ApplicationExt.class)
.getExtension(ConfigManager.NAME);
}
return configManager;
}
public ServiceRepository getApplicationServiceRepository() {
return serviceRepository;
}
public ExecutorRepository getApplicationExecutorRepository() {
return ExecutorRepository.getInstance(this);
}
public boolean NotExistApplicationConfig() {
return !getApplicationConfigManager().getApplication().isPresent();
}
public ApplicationConfig getCurrentConfig() {
return getApplicationConfigManager().getApplicationOrElseThrow();
}
public String getApplicationName() {
return getCurrentConfig().getName();
}
public String tryGetApplicationName() {
Optional appCfgOptional = getApplicationConfigManager().getApplication();
return appCfgOptional.isPresent() ? appCfgOptional.get().getName() : null;
}
void addModule(ModuleModel moduleModel, boolean isInternal) {
synchronized (instLock) {
if (!this.moduleModels.contains(moduleModel)) {
checkDestroyed();
this.moduleModels.add(moduleModel);
moduleModel.setInternalId(buildInternalId(getInternalId(), moduleIndex.getAndIncrement()));
if (!isInternal) {
pubModuleModels.add(moduleModel);
}
}
}
}
public void removeModule(ModuleModel moduleModel) {
synchronized (instLock) {
this.moduleModels.remove(moduleModel);
this.pubModuleModels.remove(moduleModel);
if (moduleModel == defaultModule) {
defaultModule = findDefaultModule();
}
}
}
void tryDestroy() {
synchronized (instLock) {
if (this.moduleModels.isEmpty()
|| (this.moduleModels.size() == 1 && this.moduleModels.get(0) == internalModule)) {
destroy();
}
}
}
private void checkDestroyed() {
if (isDestroyed()) {
throw new IllegalStateException("ApplicationModel is destroyed");
}
}
public List getModuleModels() {
return Collections.unmodifiableList(moduleModels);
}
public List getPubModuleModels() {
return Collections.unmodifiableList(pubModuleModels);
}
public ModuleModel getDefaultModule() {
if (defaultModule == null) {
synchronized (instLock) {
if (defaultModule == null) {
defaultModule = findDefaultModule();
if (defaultModule == null) {
defaultModule = this.newModule();
}
}
}
}
return defaultModule;
}
private ModuleModel findDefaultModule() {
synchronized (instLock) {
for (ModuleModel moduleModel : moduleModels) {
if (moduleModel != internalModule) {
return moduleModel;
}
}
return null;
}
}
public ModuleModel getInternalModule() {
return internalModule;
}
@Override
public void addClassLoader(ClassLoader classLoader) {
super.addClassLoader(classLoader);
if (environment != null) {
environment.refreshClassLoaders();
}
}
@Override
public void removeClassLoader(ClassLoader classLoader) {
super.removeClassLoader(classLoader);
if (environment != null) {
environment.refreshClassLoaders();
}
}
@Override
protected boolean checkIfClassLoaderCanRemoved(ClassLoader classLoader) {
return super.checkIfClassLoaderCanRemoved(classLoader) && !containsClassLoader(classLoader);
}
protected boolean containsClassLoader(ClassLoader classLoader) {
return moduleModels.stream().anyMatch(moduleModel -> moduleModel.getClassLoaders().contains(classLoader));
}
public ApplicationDeployer getDeployer() {
return deployer;
}
public void setDeployer(ApplicationDeployer deployer) {
this.deployer = deployer;
}
@Override
protected Lock acquireDestroyLock() {
return frameworkModel.acquireDestroyLock();
}
// =============================== Deprecated Methods Start =======================================
/**
* @deprecated use {@link ServiceRepository#allConsumerModels()}
*/
@Deprecated
public static Collection allConsumerModels() {
return defaultModel().getApplicationServiceRepository().allConsumerModels();
}
/**
* @deprecated use {@link ServiceRepository#allProviderModels()}
*/
@Deprecated
public static Collection allProviderModels() {
return defaultModel().getApplicationServiceRepository().allProviderModels();
}
/**
* @deprecated use {@link FrameworkServiceRepository#lookupExportedService(String)}
*/
@Deprecated
public static ProviderModel getProviderModel(String serviceKey) {
return defaultModel().getDefaultModule().getServiceRepository().lookupExportedService(serviceKey);
}
/**
* @deprecated ConsumerModel should fetch from context
*/
@Deprecated
public static ConsumerModel getConsumerModel(String serviceKey) {
return defaultModel().getDefaultModule().getServiceRepository().lookupReferredService(serviceKey);
}
/**
* @deprecated Replace to {@link ScopeModel#getModelEnvironment()}
*/
@Deprecated
public static Environment getEnvironment() {
return defaultModel().getModelEnvironment();
}
/**
* @deprecated Replace to {@link ApplicationModel#getApplicationConfigManager()}
*/
@Deprecated
public static ConfigManager getConfigManager() {
return defaultModel().getApplicationConfigManager();
}
/**
* @deprecated Replace to {@link ApplicationModel#getApplicationServiceRepository()}
*/
@Deprecated
public static ServiceRepository getServiceRepository() {
return defaultModel().getApplicationServiceRepository();
}
/**
* @deprecated Replace to {@link ApplicationModel#getApplicationExecutorRepository()}
*/
@Deprecated
public static ExecutorRepository getExecutorRepository() {
return defaultModel().getApplicationExecutorRepository();
}
/**
* @deprecated Replace to {@link ApplicationModel#getCurrentConfig()}
*/
@Deprecated
public static ApplicationConfig getApplicationConfig() {
return defaultModel().getCurrentConfig();
}
/**
* @deprecated Replace to {@link ApplicationModel#getApplicationName()}
*/
@Deprecated
public static String getName() {
return defaultModel().getCurrentConfig().getName();
}
/**
* @deprecated Replace to {@link ApplicationModel#getApplicationName()}
*/
@Deprecated
public static String getApplication() {
return getName();
}
// only for unit test
@Deprecated
public static void reset() {
if (FrameworkModel.defaultModel().getDefaultAppModel() != null) {
FrameworkModel.defaultModel().getDefaultAppModel().destroy();
}
}
/**
* @deprecated only for ut
*/
@Deprecated
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* @deprecated only for ut
*/
@Deprecated
public void setConfigManager(ConfigManager configManager) {
this.configManager = configManager;
}
/**
* @deprecated only for ut
*/
@Deprecated
public void setServiceRepository(ServiceRepository serviceRepository) {
this.serviceRepository = serviceRepository;
}
// =============================== Deprecated Methods End =======================================
}