From e79e0214cb4c0121fd8370b4074ed3d8f23934f4 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Thu, 22 Jun 2023 14:30:06 +0800 Subject: [PATCH] Enhance register type of ServiceConfig (#12583) * Enhance register type of ServiceConfig * fix else --- .../common/constants/RegisterTypeEnum.java | 44 +++++++++ .../dubbo/config/ServiceConfigBase.java | 12 +-- .../apache/dubbo/config/ServiceConfig.java | 97 +++++++++++-------- .../config/deploy/DefaultModuleDeployer.java | 3 +- .../org/apache/dubbo/registry/Constants.java | 1 - 5 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegisterTypeEnum.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegisterTypeEnum.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegisterTypeEnum.java new file mode 100644 index 00000000000..2aaeb929fcb --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegisterTypeEnum.java @@ -0,0 +1,44 @@ +/* + * 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.constants; + +/** + * Indicate that a service need to be registered to registry or not + */ +public enum RegisterTypeEnum { + + /** + * Never register. Cannot be registered by any command(like QoS-online). + */ + NEVER_REGISTER, + + /** + * Manual register. Can be registered by command(like QoS-online), but not register by default. + */ + MANUAL_REGISTER, + + /** + * (INTERNAL) Auto register by deployer. Will be registered after deployer started. + * (Delay publish when starting. Prevent service from being invoked before all services are started) + */ + AUTO_REGISTER_BY_DEPLOYER, + + /** + * Auto register. Will be registered when one service is exported. + */ + AUTO_REGISTER; +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java index 60c5c641ec3..93279cf6571 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java @@ -17,6 +17,7 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.RegisterTypeEnum; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.Service; @@ -417,7 +418,7 @@ public Boolean shouldExportAsync() { * export service and auto start application instance */ public final void export() { - export(true); + export(RegisterTypeEnum.AUTO_REGISTER); } public abstract void unexport(); @@ -429,10 +430,9 @@ public final void export() { /** * Export service to network * - * @param register Whether register service to registry. If false, can be registered manually - * through the {@link ServiceConfigBase#register(boolean)} API. + * @param registerType register type of current export action. */ - public abstract void export(boolean register); + public abstract void export(RegisterTypeEnum registerType); /** * Register delay published service to registry. @@ -444,7 +444,7 @@ public final void register() { /** * Register delay published service to registry. * - * @param onlyDefault only register those services that export with configured register false + * @param byDeployer register by deployer or not. */ - public abstract void register(boolean onlyDefault); + public abstract void register(boolean byDeployer); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index b22b0d2ab34..e3d3028a444 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.Version; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.constants.RegisterTypeEnum; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -57,11 +58,14 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -99,7 +103,6 @@ import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_REGISTRY; import static org.apache.dubbo.config.Constants.SCOPE_NONE; import static org.apache.dubbo.registry.Constants.REGISTER_KEY; -import static org.apache.dubbo.registry.Constants.REGISTER_ORIGIN_KEY; import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY; import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY; import static org.apache.dubbo.remoting.Constants.IS_PU_SERVER_KEY; @@ -149,7 +152,7 @@ public class ServiceConfig extends ServiceConfigBase { /** * The exported services */ - private final List> exporters = new ArrayList>(); + private final Map>> exporters = new ConcurrentHashMap<>(); private final List serviceListeners = new ArrayList<>(); @@ -197,19 +200,23 @@ public void unexport() { return; } if (!exporters.isEmpty()) { - for (Exporter exporter : exporters) { - try { - exporter.unregister(); - } catch (Throwable t) { - logger.warn(CONFIG_UNEXPORT_ERROR, "", "", "Unexpected error occurred when unexport " + exporter, t); + for (List> es : exporters.values()) { + for (Exporter exporter : es) { + try { + exporter.unregister(); + } catch (Throwable t) { + logger.warn(CONFIG_UNEXPORT_ERROR, "", "", "Unexpected error occurred when unexport " + exporter, t); + } } } waitForIdle(); - for (Exporter exporter : exporters) { - try { - exporter.unexport(); - } catch (Throwable t) { - logger.warn(CONFIG_UNEXPORT_ERROR, "", "", "Unexpected error occurred when unexport " + exporter, t); + for (List> es : exporters.values()) { + for (Exporter exporter : es) { + try { + exporter.unexport(); + } catch (Throwable t) { + logger.warn(CONFIG_UNEXPORT_ERROR, "", "", "Unexpected error occurred when unexport " + exporter, t); + } } } exporters.clear(); @@ -281,7 +288,7 @@ public void init() { } @Override - public void export(boolean register) { + public void export(RegisterTypeEnum registerType) { if (this.exported) { return; } @@ -302,16 +309,19 @@ public void export(boolean register) { if (shouldDelay()) { // should register if delay export - doDelayExport(true); + doDelayExport(); + } else if (Integer.valueOf(-1).equals(getDelay())) { + // should not register by default + doExport(RegisterTypeEnum.MANUAL_REGISTER); } else { - doExport(register); + doExport(registerType); } } } } @Override - public void register(boolean onlyDefault) { + public void register(boolean byDeployer) { if (!this.exported) { return; } @@ -321,19 +331,23 @@ public void register(boolean onlyDefault) { return; } - for (Exporter exporter : exporters) { - if (!onlyDefault || exporter.getInvoker().getUrl().getParameter(REGISTER_ORIGIN_KEY, true)) { + for (Exporter exporter : exporters.getOrDefault(RegisterTypeEnum.AUTO_REGISTER, Collections.emptyList())) { + exporter.register(); + } + + if (byDeployer) { + for (Exporter exporter : exporters.getOrDefault(RegisterTypeEnum.AUTO_REGISTER_BY_DEPLOYER, Collections.emptyList())) { exporter.register(); } } } } - protected void doDelayExport(boolean register) { + protected void doDelayExport() { ExecutorRepository.getInstance(getScopeModel().getApplicationModel()).getServiceExportExecutor() .schedule(() -> { try { - doExport(register); + doExport(RegisterTypeEnum.AUTO_REGISTER); } catch (Exception e) { logger.error(CONFIG_FAILED_EXPORT_SERVICE, "configuration server disconnected", "", "Failed to (async)export service config: " + interfaceName, e); } @@ -460,7 +474,7 @@ protected void postProcessRefresh() { checkAndUpdateSubConfigs(); } - protected synchronized void doExport(boolean register) { + protected synchronized void doExport(RegisterTypeEnum registerType) { if (unexported) { throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!"); } @@ -471,12 +485,12 @@ protected synchronized void doExport(boolean register) { if (StringUtils.isEmpty(path)) { path = interfaceName; } - doExportUrls(register); + doExportUrls(registerType); exported(); } @SuppressWarnings({"unchecked", "rawtypes"}) - private void doExportUrls(boolean register) { + private void doExportUrls(RegisterTypeEnum registerType) { ModuleServiceRepository repository = getScopeModel().getServiceRepository(); ServiceDescriptor serviceDescriptor; final boolean serverService = ref instanceof ServerService; @@ -508,10 +522,10 @@ private void doExportUrls(boolean register) { .orElse(path), group, version); // stub service will use generated service name if (!serverService) { - // In case user specified path, register service one more time to map it to path. + // In case user specified path, registerImmediately service one more time to map it to path. repository.registerService(pathKey, interfaceClass); } - doExportUrlsFor1Protocol(protocolConfig, registryURLs, register); + doExportUrlsFor1Protocol(protocolConfig, registryURLs, registerType); } return null; } @@ -520,7 +534,7 @@ private void doExportUrls(boolean register) { providerModel.setServiceUrls(urls); } - private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs, boolean register) { + private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs, RegisterTypeEnum registerType) { Map map = buildAttributes(protocolConfig); // remove null key and null value @@ -532,7 +546,7 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List r processServiceExecutor(url); - exportUrl(url, registryURLs, register); + exportUrl(url, registryURLs, registerType); } private void processServiceExecutor(URL url) { @@ -714,7 +728,7 @@ private URL buildUrl(ProtocolConfig protocolConfig, Map params) return url; } - private void exportUrl(URL url, List registryURLs, boolean register) { + private void exportUrl(URL url, List registryURLs, RegisterTypeEnum registerType) { String scope = url.getParameter(SCOPE_KEY); // don't export when none is configured if (!SCOPE_NONE.equalsIgnoreCase(scope)) { @@ -738,7 +752,7 @@ private void exportUrl(URL url, List registryURLs, boolean register) { build(); } - url = exportRemote(url, registryURLs, register); + url = exportRemote(url, registryURLs, registerType); if (!isGeneric(generic) && !getScopeModel().isInternal()) { MetadataUtils.publishServiceDefinition(url, providerModel.getServiceModel(), getApplicationModel()); } @@ -753,7 +767,7 @@ private void exportUrl(URL url, List registryURLs, boolean register) { URL localUrl = URLBuilder.from(url). setProtocol(protocol). build(); - localUrl = exportRemote(localUrl, registryURLs, register); + localUrl = exportRemote(localUrl, registryURLs, registerType); if (!isGeneric(generic) && !getScopeModel().isInternal()) { MetadataUtils.publishServiceDefinition(localUrl, providerModel.getServiceModel(), getApplicationModel()); } @@ -765,8 +779,8 @@ private void exportUrl(URL url, List registryURLs, boolean register) { this.urls.add(url); } - private URL exportRemote(URL url, List registryURLs, boolean register) { - if (CollectionUtils.isNotEmpty(registryURLs)) { + private URL exportRemote(URL url, List registryURLs, RegisterTypeEnum registerType) { + if (CollectionUtils.isNotEmpty(registryURLs) && registerType != RegisterTypeEnum.NEVER_REGISTER) { for (URL registryURL : registryURLs) { if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) { url = url.addParameterIfAbsent(SERVICE_NAME_MAPPING_KEY, "true"); @@ -797,7 +811,7 @@ private URL exportRemote(URL url, List registryURLs, boolean register) { } } - doExportUrl(registryURL.putAttribute(EXPORT_KEY, url), true, register); + doExportUrl(registryURL.putAttribute(EXPORT_KEY, url), true, registerType); } } else { @@ -806,7 +820,7 @@ private URL exportRemote(URL url, List registryURLs, boolean register) { logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url); } - doExportUrl(url, true, register); + doExportUrl(url, true, registerType); } @@ -814,17 +828,22 @@ private URL exportRemote(URL url, List registryURLs, boolean register) { } @SuppressWarnings({"unchecked", "rawtypes"}) - private void doExportUrl(URL url, boolean withMetaData, boolean register) { - if (!register) { - url = url.addParameter(REGISTER_ORIGIN_KEY, url.getParameter(REGISTER_KEY, true)); + private void doExportUrl(URL url, boolean withMetaData, RegisterTypeEnum registerType) { + if (!url.getParameter(REGISTER_KEY, true)) { + registerType = RegisterTypeEnum.MANUAL_REGISTER; + } + if (registerType == RegisterTypeEnum.NEVER_REGISTER || + registerType == RegisterTypeEnum.MANUAL_REGISTER || + registerType == RegisterTypeEnum.AUTO_REGISTER_BY_DEPLOYER) { url = url.addParameter(REGISTER_KEY, false); } + Invoker invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); if (withMetaData) { invoker = new DelegateProviderMetaDataInvoker(invoker, this); } Exporter exporter = protocolSPI.export(invoker); - exporters.add(exporter); + exporters.computeIfAbsent(registerType, k -> new CopyOnWriteArrayList<>()).add(exporter); } @@ -840,7 +859,7 @@ private void exportLocal(URL url) { local = local.setScopeModel(getScopeModel()) .setServiceModel(providerModel); local = local.addParameter(EXPORTER_LISTENER_KEY, LOCAL_PROTOCOL); - doExportUrl(local, false, true); + doExportUrl(local, false, RegisterTypeEnum.AUTO_REGISTER); logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry url : " + local); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java index 004be0e224a..9ddd1646da7 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.config.ReferenceCache; import org.apache.dubbo.common.constants.LoggerCodeConstants; +import org.apache.dubbo.common.constants.RegisterTypeEnum; import org.apache.dubbo.common.deploy.AbstractDeployer; import org.apache.dubbo.common.deploy.ApplicationDeployer; import org.apache.dubbo.common.deploy.DeployListener; @@ -427,7 +428,7 @@ private void exportServiceInternal(ServiceConfigBase sc) { asyncExportingFutures.add(future); } else { if (!sc.isExported()) { - sc.export(false); + sc.export(RegisterTypeEnum.AUTO_REGISTER_BY_DEPLOYER); exportedServices.add(sc); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java index be991b256ec..d21534436c4 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java @@ -21,7 +21,6 @@ public interface Constants { String REGISTER_IP_KEY = "register.ip"; String REGISTER_KEY = "register"; - String REGISTER_ORIGIN_KEY = "register_origin"; String SUBSCRIBE_KEY = "subscribe";