This is an automated email from the ASF dual-hosted git repository. mercyblitz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/master by this push: new cb12928 [Dubbo-5871][Dubbo-5885][Dubbo-5899] Fix nacos registry not work bug since 2.7.6 (#5902) cb12928 is described below commit cb12928a710a34142e8c6a9b93e532239906a69e Author: Lei Jiang <53557551+lad...@users.noreply.github.com> AuthorDate: Tue Mar 31 14:55:10 2020 +0800 [Dubbo-5871][Dubbo-5885][Dubbo-5899] Fix nacos registry not work bug since 2.7.6 (#5902) * TO FIX bug with https://github.com/apache/dubbo/issues/5885 * Avoid instances overwriting problem with different service name * Avoid duplicated service name which will lead duplicated subscribe * Resolve Conflicts * Resolve conflicts * Use ConcurrentHashMap instead of HashMap * Resolve conflicts * Resolve conflicts * Resolve conflicts * Format codes --- .../apache/dubbo/registry/nacos/NacosRegistry.java | 76 +++++++++++++++++++--- .../nacos/util/NacosInstanceManageUtil.java | 67 +++++++++++++++++++ 2 files changed, 135 insertions(+), 8 deletions(-) diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java index 070c526..a13fa88 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java @@ -17,6 +17,7 @@ package org.apache.dubbo.registry.nacos; +import com.google.common.collect.Lists; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.common.logger.Logger; @@ -25,6 +26,7 @@ import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.nacos.util.NacosInstanceManageUtil; import org.apache.dubbo.registry.support.FailbackRegistry; import com.alibaba.nacos.api.exception.NacosException; @@ -162,20 +164,62 @@ public class NacosRegistry extends FailbackRegistry { @Override public void doSubscribe(final URL url, final NotifyListener listener) { Set<String> serviceNames = getServiceNames(url, listener); + + //Set corresponding serviceNames for easy search later + if(isServiceNamesWithCompatibleMode(url)){ + for(String serviceName:serviceNames){ + NacosInstanceManageUtil.setCorrespondingServiceNames(serviceName, serviceNames); + } + } + doSubscribe(url, listener, serviceNames); } private void doSubscribe(final URL url, final NotifyListener listener, final Set<String> serviceNames) { execute(namingService -> { - List<Instance> instances = new LinkedList(); - for (String serviceName : serviceNames) { - instances.addAll(namingService.getAllInstances(serviceName)); - subscribeEventListener(serviceName, url, listener); + if (isServiceNamesWithCompatibleMode(url)) { + List<Instance> allCorrespondingInstanceList = Lists.newArrayList(); + + /** + * Get all instances with serviceNames to avoid instance overwrite and but with empty instance mentioned + * in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899 + */ + for (String serviceName : serviceNames) { + List<Instance> instances = namingService.getAllInstances(serviceName); + NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, instances); + allCorrespondingInstanceList.addAll(instances); + } + notifySubscriber(url, listener, allCorrespondingInstanceList); + for (String serviceName : serviceNames) { + subscribeEventListener(serviceName, url, listener); + } + } else { + List<Instance> instances = new LinkedList(); + for (String serviceName : serviceNames) { + instances.addAll(namingService.getAllInstances(serviceName)); + notifySubscriber(url, listener, instances); + subscribeEventListener(serviceName, url, listener); + } } - notifySubscriber(url, listener, instances); + }); } + /** + * Since 2.7.6 the legacy service name will be added to serviceNames + * to fix bug with https://github.com/apache/dubbo/issues/5442 + * + * @param url + * @return + */ + private boolean isServiceNamesWithCompatibleMode(final URL url) { + if (!isAdminProtocol(url) && createServiceName(url).isConcrete()) { + return true; + } else { + return false; + } + } + @Override public void doUnsubscribe(URL url, NotifyListener listener) { if (isAdminProtocol(url)) { @@ -214,7 +258,11 @@ public class NacosRegistry extends FailbackRegistry { serviceNames = new LinkedHashSet<>(); serviceNames.add(serviceName.toString()); // Add the legacy service name since 2.7.6 - serviceNames.add(getLegacySubscribedServiceName(url)); + String legacySubscribedServiceName = getLegacySubscribedServiceName(url); + if (!serviceName.toString().equals(legacySubscribedServiceName)) { + //avoid duplicated service names + serviceNames.add(legacySubscribedServiceName); + } } else { serviceNames = filterServiceNames(serviceName); } @@ -422,7 +470,19 @@ public class NacosRegistry extends FailbackRegistry { EventListener eventListener = event -> { if (event instanceof NamingEvent) { NamingEvent e = (NamingEvent) event; - notifySubscriber(url, listener, e.getInstances()); + List<Instance> instances = e.getInstances(); + + + if(isServiceNamesWithCompatibleMode(url)){ + /** + * Get all instances with corresponding serviceNames to avoid instance overwrite and but with empty instance mentioned + * in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899 + */ + NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, instances); + instances = NacosInstanceManageUtil.getAllCorrespondingServiceInstanceList(serviceName); + } + + notifySubscriber(url, listener, instances); } }; namingService.subscribe(serviceName, eventListener); @@ -542,4 +602,4 @@ public class NacosRegistry extends FailbackRegistry { void callback(NamingService namingService) throws NacosException; } -} +} \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosInstanceManageUtil.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosInstanceManageUtil.java new file mode 100644 index 0000000..190a5aa --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosInstanceManageUtil.java @@ -0,0 +1,67 @@ +/* + * 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.nacos.util; + +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.dubbo.common.utils.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Instance manage util for multiple serviceNames + * To resolve bug with https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899 + * + * @since 2.7.6 + */ +public class NacosInstanceManageUtil { + + /** + * serviceName -> refreshed instance list + */ + private static final Map<String, List<Instance>> SERVICE_INSTANCE_LIST_MAP = Maps.newConcurrentMap(); + + /** + * serviceName -> corresponding serviceName list + */ + private static final Map<String, Set<String>> CORRESPONDING_SERVICE_NAMES_MAP = Maps.newConcurrentMap(); + + public static void setCorrespondingServiceNames(String serviceName, Set<String> serviceNames) { + CORRESPONDING_SERVICE_NAMES_MAP.put(serviceName, serviceNames); + } + + public static void initOrRefreshServiceInstanceList(String serviceName, List<Instance> instanceList) { + SERVICE_INSTANCE_LIST_MAP.put(serviceName, instanceList); + } + + public static List<Instance> getAllCorrespondingServiceInstanceList(String serviceName) { + if (!CORRESPONDING_SERVICE_NAMES_MAP.containsKey(serviceName)) { + return Lists.newArrayList(); + } + List<Instance> allInstances = Lists.newArrayList(); + for (String correspondingServiceName : CORRESPONDING_SERVICE_NAMES_MAP.get(serviceName)) { + if (SERVICE_INSTANCE_LIST_MAP.containsKey(correspondingServiceName) && CollectionUtils.isNotEmpty(SERVICE_INSTANCE_LIST_MAP.get(correspondingServiceName))) { + allInstances.addAll(SERVICE_INSTANCE_LIST_MAP.get(correspondingServiceName)); + } + } + return allInstances; + } + +}