Merge branch 'apache-3.1' into apache-3.2

# Conflicts:
#	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
This commit is contained in:
Albumen Kevin 2023-01-06 16:48:39 +08:00
commit 0419f25ac2
11 changed files with 256 additions and 72 deletions

2
NOTICE
View File

@ -1,5 +1,5 @@
Apache Dubbo
Copyright 2018-2022 The Apache Software Foundation
Copyright 2018-2023 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@ -17,13 +17,13 @@
package org.apache.dubbo.common.constants;
import org.apache.dubbo.common.URL;
import java.net.NetworkInterface;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
import org.apache.dubbo.common.URL;
public interface CommonConstants {
String DUBBO = "dubbo";
@ -367,6 +367,13 @@ public interface CommonConstants {
*/
String REGISTRY_LOCAL_FILE_CACHE_ENABLED = "file.cache";
String METADATA_INFO_CACHE_EXPIRE_KEY = "metadata-info-cache.expire";
int DEFAULT_METADATA_INFO_CACHE_EXPIRE = 10 * 60 * 1000;
String METADATA_INFO_CACHE_SIZE_KEY = "metadata-info-cache.size";
int DEFAULT_METADATA_INFO_CACHE_SIZE = 16;
/**
* The limit of callback service instances for one interface on every client

View File

@ -19,6 +19,10 @@ package org.apache.dubbo.registry.client;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
@ -37,9 +41,14 @@ import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
import org.apache.dubbo.registry.client.metadata.store.MetaCacheManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_INFO_CACHE_EXPIRE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_INFO_CACHE_SIZE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_INFO_CACHE_EXPIRE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_INFO_CACHE_SIZE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_FETCH_INSTANCE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_LOAD_METADATA;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
@ -59,6 +68,8 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
protected final String serviceName;
protected volatile ServiceInstance serviceInstance;
protected volatile MetadataInfo metadataInfo;
protected final ConcurrentHashMap<String, MetadataInfoStat> metadataInfos = new ConcurrentHashMap<>();
protected final ScheduledFuture<?> refreshCacheFuture;
protected MetadataReport metadataReport;
protected String metadataType;
protected final MetaCacheManager metaCacheManager;
@ -88,6 +99,30 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
this.metaCacheManager = new MetaCacheManager(localCacheEnabled, getCacheNameSuffix(),
applicationModel.getFrameworkModel().getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getCacheRefreshingScheduledExecutor());
int metadataInfoCacheExpireTime = registryURL.getParameter(METADATA_INFO_CACHE_EXPIRE_KEY, DEFAULT_METADATA_INFO_CACHE_EXPIRE);
int metadataInfoCacheSize = registryURL.getParameter(METADATA_INFO_CACHE_SIZE_KEY, DEFAULT_METADATA_INFO_CACHE_SIZE);
this.refreshCacheFuture = applicationModel.getFrameworkModel().getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getSharedScheduledExecutor()
.scheduleAtFixedRate(() -> {
try {
while (metadataInfos.size() > metadataInfoCacheSize) {
AtomicReference<String> oldestRevision = new AtomicReference<>();
AtomicReference<MetadataInfoStat> oldestStat = new AtomicReference<>();
metadataInfos.forEach((k, v) -> {
if (System.currentTimeMillis() - v.getUpdateTime() > metadataInfoCacheExpireTime &&
(oldestStat.get() == null || oldestStat.get().getUpdateTime() > v.getUpdateTime())) {
oldestRevision.set(k);
oldestStat.set(v);
}
});
if (oldestStat.get() != null) {
metadataInfos.remove(oldestRevision.get(), oldestStat.get());
}
}
} catch (Throwable t) {
logger.error(INTERNAL_ERROR, "", "", "Error occurred when clean up metadata info cache.", t);
}
}, metadataInfoCacheExpireTime / 2, metadataInfoCacheExpireTime / 2, TimeUnit.MILLISECONDS);
}
@ -163,6 +198,16 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
return this.metadataInfo;
}
@Override
public MetadataInfo getLocalMetadata(String revision) {
MetadataInfoStat metadataInfoStat = metadataInfos.get(revision);
if (metadataInfoStat != null) {
return metadataInfoStat.getMetadataInfo();
} else {
return null;
}
}
@Override
public MetadataInfo getRemoteMetadata(String revision, List<ServiceInstance> instances) {
MetadataInfo metadata = metaCacheManager.get(revision);
@ -217,6 +262,7 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
public final void destroy() throws Exception {
isDestroy = true;
metaCacheManager.destroy();
refreshCacheFuture.cancel(true);
doDestroy();
}
@ -291,12 +337,17 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
}
protected void reportMetadata(MetadataInfo metadataInfo) {
if (metadataInfo == null) {
return;
}
if (metadataReport != null) {
SubscriberMetadataIdentifier identifier = new SubscriberMetadataIdentifier(serviceName, metadataInfo.getRevision());
if ((DEFAULT_METADATA_STORAGE_TYPE.equals(metadataType) && metadataReport.shouldReportMetadata()) || REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
metadataReport.publishAppMetadata(identifier, metadataInfo);
}
}
MetadataInfo clonedMetadataInfo = metadataInfo.clone();
metadataInfos.put(metadataInfo.getRevision(), new MetadataInfoStat(clonedMetadataInfo));
}
protected void unReportMetadata(MetadataInfo metadataInfo) {
@ -328,4 +379,21 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
}
return stringBuilder.toString();
}
private static class MetadataInfoStat {
private final MetadataInfo metadataInfo;
private final long updateTime = System.currentTimeMillis();
public MetadataInfoStat(MetadataInfo metadataInfo) {
this.metadataInfo = metadataInfo;
}
public MetadataInfo getMetadataInfo() {
return metadataInfo;
}
public long getUpdateTime() {
return updateTime;
}
}
}

View File

@ -16,15 +16,15 @@
*/
package org.apache.dubbo.registry.client;
import java.util.List;
import java.util.Set;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.MetadataInfo;
import org.apache.dubbo.registry.RegistryService;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import java.util.List;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_DELAY_NOTIFICATION_KEY;
/**
@ -69,6 +69,10 @@ public interface ServiceDiscovery extends RegistryService, Prioritized {
MetadataInfo getLocalMetadata();
default MetadataInfo getLocalMetadata(String revision) {
return getLocalMetadata();
}
MetadataInfo getRemoteMetadata(String revision);
MetadataInfo getRemoteMetadata(String revision, List<ServiceInstance> instances);

View File

@ -16,6 +16,22 @@
*/
package org.apache.dubbo.registry.client.event.listener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.dubbo.common.ProtocolServiceKey;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
@ -38,25 +54,9 @@ import org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCust
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_REFRESH_ADDRESS;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_REFRESH_ADDRESS;
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_ENABLE_EMPTY_PROTECTION;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.ENABLE_EMPTY_PROTECTION_KEY;
@ -458,12 +458,12 @@ public class ServiceInstancesChangedListener {
return false;
}
ServiceInstancesChangedListener that = (ServiceInstancesChangedListener) o;
return Objects.equals(getServiceNames(), that.getServiceNames());
return Objects.equals(getServiceNames(), that.getServiceNames()) && Objects.equals(listeners, that.listeners);
}
@Override
public int hashCode() {
return Objects.hash(getClass(), getServiceNames());
return Objects.hash(getClass(), getServiceNames(), listeners);
}
protected class AddressRefreshRetryTask implements Runnable {

View File

@ -16,18 +16,6 @@
*/
package org.apache.dubbo.registry.client.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.resource.Disposable;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.InstanceMetadataChangedListener;
import org.apache.dubbo.metadata.MetadataInfo;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.support.RegistryManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
@ -40,6 +28,18 @@ import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.resource.Disposable;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.InstanceMetadataChangedListener;
import org.apache.dubbo.metadata.MetadataInfo;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.support.RegistryManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static java.util.Collections.emptySortedSet;
import static java.util.Collections.unmodifiableSortedSet;
import static org.apache.dubbo.common.URL.buildKey;
@ -182,8 +182,8 @@ public class MetadataServiceDelegation implements MetadataService, Disposable {
}
for (ServiceDiscovery sd : registryManager.getServiceDiscoveries()) {
MetadataInfo metadataInfo = sd.getLocalMetadata();
if (revision.equals(metadataInfo.getRevision())) {
MetadataInfo metadataInfo = sd.getLocalMetadata(revision);
if (metadataInfo != null && revision.equals(metadataInfo.getRevision())) {
return metadataInfo;
}
}

View File

@ -16,6 +16,16 @@
*/
package org.apache.dubbo.registry.integration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
@ -25,6 +35,7 @@ import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.common.timer.HashedWheelTimer;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.common.utils.UrlUtils;
@ -59,15 +70,6 @@ import org.apache.dubbo.rpc.model.ScopeModelUtil;
import org.apache.dubbo.rpc.protocol.InvokerWrapper;
import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
@ -194,8 +196,8 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
return 9090;
}
public Map<URL, NotifyListener> getOverrideListeners() {
Map<URL, NotifyListener> map = new HashMap<>();
public Map<URL, Set<NotifyListener>> getOverrideListeners() {
Map<URL, Set<NotifyListener>> map = new HashMap<>();
List<ApplicationModel> applicationModels = frameworkModel.getApplicationModels();
if (applicationModels.size() == 1) {
return applicationModels.get(0).getBeanFactory().getBean(ProviderConfigurationListener.class).getOverrideListeners();
@ -231,8 +233,9 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
// subscription information to cover.
final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl);
final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
Map<URL, NotifyListener> overrideListeners = getProviderConfigurationListener(providerUrl).getOverrideListeners();
overrideListeners.put(registryUrl, overrideSubscribeListener);
Map<URL, Set<NotifyListener>> overrideListeners = getProviderConfigurationListener(overrideSubscribeUrl).getOverrideListeners();
overrideListeners.computeIfAbsent(overrideSubscribeUrl, k -> new ConcurrentHashSet<>())
.add(overrideSubscribeListener);
providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener);
//export invoker
@ -254,6 +257,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
exporter.setRegisterUrl(registeredProviderUrl);
exporter.setSubscribeUrl(overrideSubscribeUrl);
exporter.setNotifyListener(overrideSubscribeListener);
if (!registry.isServiceDiscovery()) {
// Deprecated! Subscribe to override rules in 2.6.x or before.
@ -819,7 +823,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
private class ProviderConfigurationListener extends AbstractConfiguratorListener {
private final Map<URL, NotifyListener> overrideListeners = new ConcurrentHashMap<>();
private final Map<URL, Set<NotifyListener>> overrideListeners = new ConcurrentHashMap<>();
public ProviderConfigurationListener(ModuleModel moduleModel) {
super(moduleModel);
@ -841,10 +845,14 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
@Override
protected void notifyOverrides() {
overrideListeners.values().forEach(listener -> ((OverrideListener) listener).doOverrideIfNecessary());
overrideListeners.values().forEach(listeners -> {
for (NotifyListener listener : listeners) {
((OverrideListener) listener).doOverrideIfNecessary();
}
});
}
public Map<URL, NotifyListener> getOverrideListeners() {
public Map<URL, Set<NotifyListener>> getOverrideListeners() {
return overrideListeners;
}
}
@ -864,6 +872,8 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
private URL subscribeUrl;
private URL registerUrl;
private NotifyListener notifyListener;
public ExporterChangeableWrapper(Exporter<T> exporter, Invoker<T> originInvoker) {
this.exporter = exporter;
this.originInvoker = originInvoker;
@ -898,11 +908,11 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
}
try {
if (subscribeUrl != null) {
Map<URL, NotifyListener> overrideListeners = getProviderConfigurationListener(subscribeUrl).getOverrideListeners();
NotifyListener listener = overrideListeners.remove(registerUrl);
if (listener != null) {
Map<URL, Set<NotifyListener>> overrideListeners = getProviderConfigurationListener(subscribeUrl).getOverrideListeners();
Set<NotifyListener> listeners = overrideListeners.get(subscribeUrl);
if (listeners.remove(notifyListener)) {
if (!registry.isServiceDiscovery()) {
registry.unsubscribe(subscribeUrl, listener);
registry.unsubscribe(subscribeUrl, notifyListener);
}
ApplicationModel applicationModel = getApplicationModel(registerUrl.getScopeModel());
if (applicationModel.getModelEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) {
@ -915,6 +925,9 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
}
}
}
if (listeners.isEmpty()) {
overrideListeners.remove(subscribeUrl);
}
}
} catch (Throwable t) {
logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t);
@ -942,6 +955,10 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
this.registerUrl = registerUrl;
}
public void setNotifyListener(NotifyListener notifyListener) {
this.notifyListener = notifyListener;
}
public URL getRegisterUrl() {
return registerUrl;
}

View File

@ -0,0 +1,85 @@
/*
* 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.client;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metadata.MetadataInfo;
import org.apache.dubbo.registry.client.support.MockServiceDiscovery;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_INFO_CACHE_EXPIRE_KEY;
import static org.awaitility.Awaitility.await;
class ServiceDiscoveryCacheTest {
@Test
void test() throws InterruptedException {
ApplicationModel applicationModel = FrameworkModel.defaultModel().newApplication();
applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("Test"));
URL registryUrl = URL.valueOf("mock://127.0.0.1:12345").addParameter(METADATA_INFO_CACHE_EXPIRE_KEY, 10);
MockServiceDiscovery mockServiceDiscovery = Mockito.spy(new MockServiceDiscovery(applicationModel, registryUrl));
mockServiceDiscovery.register(URL.valueOf("mock://127.0.0.1:12345")
.setServiceInterface("org.apache.dubbo.registry.service.DemoService"));
mockServiceDiscovery.register();
ServiceInstance localInstance = mockServiceDiscovery.getLocalInstance();
Assertions.assertEquals(localInstance.getServiceMetadata(), mockServiceDiscovery.getLocalMetadata(localInstance.getServiceMetadata().getRevision()));
List<MetadataInfo> instances = new LinkedList<>();
instances.add(localInstance.getServiceMetadata().clone());
for (int i = 0; i < 15; i++) {
Thread.sleep(1);
mockServiceDiscovery.register(URL.valueOf("mock://127.0.0.1:12345")
.setServiceInterface("org.apache.dubbo.registry.service.DemoService" + i));
mockServiceDiscovery.update();
instances.add(mockServiceDiscovery.getLocalInstance().getServiceMetadata().clone());
}
for (MetadataInfo instance : instances) {
Assertions.assertEquals(instance, mockServiceDiscovery.getLocalMetadata(instance.getRevision()));
}
for (int i = 0; i < 5; i++) {
Thread.sleep(1);
mockServiceDiscovery.register(URL.valueOf("mock://127.0.0.1:12345")
.setServiceInterface("org.apache.dubbo.registry.service.DemoService-new" + i));
mockServiceDiscovery.update();
instances.add(mockServiceDiscovery.getLocalInstance().getServiceMetadata().clone());
}
await().until(() -> Objects.isNull(mockServiceDiscovery.getLocalMetadata(instances.get(4).getRevision())));
for (int i = 0; i < 5; i++) {
Assertions.assertNull(mockServiceDiscovery.getLocalMetadata(instances.get(i).getRevision()));
}
applicationModel.destroy();
}
}

View File

@ -40,11 +40,6 @@ public class MockServiceDiscovery extends AbstractServiceDiscovery {
}
@Override
public void doUpdate(ServiceInstance oldServiceInstance, ServiceInstance newServiceInstance) throws RuntimeException {
}
@Override
public void doUnregister(ServiceInstance serviceInstance) {

View File

@ -16,6 +16,14 @@
*/
package org.apache.dubbo.registry.multiple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.metadata.MetadataInfo;
@ -26,14 +34,6 @@ import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
public class MultipleServiceDiscovery implements ServiceDiscovery {
public static final String REGISTRY_PREFIX_KEY = "child.";
private static final String REGISTRY_TYPE = "registry-type";
@ -137,6 +137,11 @@ public class MultipleServiceDiscovery implements ServiceDiscovery {
throw new UnsupportedOperationException("Multiple registry implementation does not support getMetadata() method.");
}
@Override
public MetadataInfo getLocalMetadata(String revision) {
throw new UnsupportedOperationException("Multiple registry implementation does not support getLocalMetadata() method.");
}
@Override
public MetadataInfo getRemoteMetadata(String revision) {
throw new UnsupportedOperationException("Multiple registry implementation does not support getMetadata() method.");

View File

@ -156,6 +156,9 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
@Override
public void removeServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws IllegalArgumentException {
if (!instanceListeners.remove(listener)) {
return;
}
listener.getServiceNames().forEach(serviceName -> {
ZookeeperServiceDiscoveryChangeWatcher watcher = watcherCaches.get(serviceName);
if (watcher != null) {