From bcc9513934412681e5fd5567d950286c0068e0e8 Mon Sep 17 00:00:00 2001 From: "ken.lj" Date: Mon, 16 Nov 2020 18:53:45 +0800 Subject: [PATCH] performance tuning, fix cache registry url creation bug (#6914) --- .../url/component/DubboServiceAddressURL.java | 7 +++ .../migration/MigrationRuleListener.java | 12 ++--- .../integration/RegistryDirectory.java | 51 ++++++------------- .../support/CacheableFailbackRegistry.java | 22 ++------ 4 files changed, 34 insertions(+), 58 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java index 80cadc6853..fbb31b661f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java @@ -22,9 +22,16 @@ import org.apache.dubbo.common.utils.StringUtils; import java.util.Map; import java.util.Objects; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; public class DubboServiceAddressURL extends ServiceAddressURL { + public static final String[] PROVIDER_FIRST_KEYS = new String[]{RELEASE_KEY, DUBBO_VERSION_KEY, METHODS_KEY, TIMESTAMP_KEY, TAG_KEY}; + public static DubboServiceAddressURL valueOf(String rawURL, URL consumerURL) { return valueOf(rawURL, consumerURL, null); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java index 0eeb5202cd..6c00944cc2 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java @@ -42,7 +42,7 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur private static final String RULE_KEY = ApplicationModel.getName() + ".migration"; private static final String DUBBO_SERVICEDISCOVERY_MIGRATION = "DUBBO_SERVICEDISCOVERY_MIGRATION"; - private Set listeners = new ConcurrentHashSet<>(); + private Set handlers = new ConcurrentHashSet<>(); private DynamicConfiguration configuration; private volatile String rawRule; @@ -71,8 +71,8 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur logger.info("Using the following migration rule to migrate:"); logger.info(rawRule); - if (CollectionUtils.isNotEmpty(listeners)) { - listeners.forEach(listener -> listener.doMigrate(rawRule)); + if (CollectionUtils.isNotEmpty(handlers)) { + handlers.forEach(listener -> listener.doMigrate(rawRule)); } } @@ -85,10 +85,10 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur public synchronized void onRefer(RegistryProtocol registryProtocol, ClusterInvoker invoker, URL url) { MigrationInvoker migrationInvoker = (MigrationInvoker) invoker; - MigrationRuleHandler migrationListener = new MigrationRuleHandler<>(migrationInvoker, url); - listeners.add(migrationListener); + MigrationRuleHandler migrationRuleHandler = new MigrationRuleHandler<>(migrationInvoker, url); + handlers.add(migrationRuleHandler); - migrationListener.doMigrate(rawRule); + migrationRuleHandler.doMigrate(rawRule); } @Override diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index cf89e51433..bef93179d6 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -45,7 +45,6 @@ import org.apache.dubbo.rpc.cluster.support.ClusterUtils; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -329,7 +328,7 @@ public class RegistryDirectory extends DynamicDirectory implements NotifyL // Cache key is url that does not merge with consumer side parameters, regardless of how the consumer combines parameters, if the server url changes, then refer again Map> localUrlInvokerMap = this.urlInvokerMap; // local reference - Invoker invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.get(url); + Invoker invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.remove(url); if (invoker == null) { // Not in the cache, refer again try { boolean enabled = true; @@ -459,49 +458,31 @@ public class RegistryDirectory extends DynamicDirectory implements NotifyL cachedInvokerUrls = null; } - /** - * Check whether the invoker in the cache needs to be destroyed - * If set attribute of url: refer.autodestroy=false, the invokers will only increase without decreasing,there may be a refer leak - * - * @param oldUrlInvokerMap - * @param newUrlInvokerMap - */ private void destroyUnusedInvokers(Map> oldUrlInvokerMap, Map> newUrlInvokerMap) { if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) { destroyAllInvokers(); return; } - // check deleted invoker - List deleted = null; - if (oldUrlInvokerMap != null) { - Collection> newInvokers = newUrlInvokerMap.values(); - for (Map.Entry> entry : oldUrlInvokerMap.entrySet()) { - if (!newInvokers.contains(entry.getValue())) { - if (deleted == null) { - deleted = new ArrayList<>(); + + if (oldUrlInvokerMap == null || oldUrlInvokerMap.size() == 0) { + return; + } + + for (Map.Entry> entry : oldUrlInvokerMap.entrySet()) { + Invoker invoker = entry.getValue(); + if (invoker != null) { + try { + invoker.destroy(); + if (logger.isDebugEnabled()) { + logger.debug("destroy invoker[" + invoker.getUrl() + "] success. "); } - deleted.add(entry.getKey()); + } catch (Exception e) { + logger.warn("destroy invoker[" + invoker.getUrl() + "] failed. " + e.getMessage(), e); } } } - if (deleted != null) { - for (URL url : deleted) { - if (url != null) { - Invoker invoker = oldUrlInvokerMap.remove(url); - if (invoker != null) { - try { - invoker.destroy(); - if (logger.isDebugEnabled()) { - logger.debug("destroy invoker[" + invoker.getUrl() + "] success. "); - } - } catch (Exception e) { - logger.warn("destroy invoker[" + invoker.getUrl() + "] failed. " + e.getMessage(), e); - } - } - } - } - } + logger.info("New url total size, " + newUrlInvokerMap.size() + ", destroyed total size " + oldUrlInvokerMap.size()); } @Override diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java index 9ca1b74d29..e5f2a34363 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java @@ -51,17 +51,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.CACHE_CLEAR_TASK import static org.apache.dubbo.common.constants.CommonConstants.CACHE_CLEAR_WAITING_THRESHOLD; import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_SEPARATOR_ENCODED; -import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; +import static org.apache.dubbo.common.url.component.DubboServiceAddressURL.PROVIDER_FIRST_KEYS; /** * Useful for registries who's sdk returns raw string as provider instance, for example, zookeeper and etcd. @@ -85,7 +81,7 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry { ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); cacheRemovalScheduler = executorRepository.nextScheduledExecutor(); cacheRemovalTaskIntervalInMillis = getIntConfig(CACHE_CLEAR_TASK_INTERVAL, 10 * 60 * 1000); - cacheClearWaitingThresholdInMillis = getIntConfig(CACHE_CLEAR_WAITING_THRESHOLD, 10 * 60 * 1000); + cacheClearWaitingThresholdInMillis = getIntConfig(CACHE_CLEAR_WAITING_THRESHOLD, 30 * 60 * 1000); } public CacheableFailbackRegistry(URL url) { @@ -203,18 +199,10 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry { String rawAddress = parts[0]; String rawParams = parts[1]; boolean isEncoded = encoded; - URLAddress address = stringAddress.computeIfAbsent(rawAddress, k -> { - URLAddress newAddress = URLAddress.parse(k, getDefaultURLProtocol(), isEncoded); - stringAddress.put(k, newAddress); - return newAddress; - }); + URLAddress address = stringAddress.computeIfAbsent(rawAddress, k -> URLAddress.parse(k, getDefaultURLProtocol(), isEncoded)); address.setTimestamp(System.currentTimeMillis()); - URLParam param = stringParam.computeIfAbsent(rawParams, k -> { - URLParam newParam = URLParam.parse(k, isEncoded, extraParameters); - stringParam.put(k, newParam); - return newParam; - }); + URLParam param = stringParam.computeIfAbsent(rawParams, k -> URLParam.parse(k, isEncoded, extraParameters)); param.setTimestamp(System.currentTimeMillis()); ServiceAddressURL cachedURL = createServiceURL(address, param, consumerURL); @@ -230,7 +218,7 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry { } protected URL removeParamsFromConsumer(URL consumer) { - return consumer.removeParameters(RELEASE_KEY, DUBBO_VERSION_KEY, METHODS_KEY, TIMESTAMP_KEY, TAG_KEY); + return consumer.removeParameters(PROVIDER_FIRST_KEYS); } private String stripOffVariableKeys(String rawProvider) {