Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class SimpleReferenceCache implements ReferenceCache {
/**
* Create the key with the <b>Group</b>, <b>Interface</b> and <b>version</b> attribute of {@link ReferenceConfigBase}.
* <p>
* key example: <code>group1/org.apache.dubbo.foo.FooService:1.0.0</code>.
* key example: <code>group1/org.apache.dubbo.foo.FooService:1.0.0@registry=registry1</code>
*/
public static final KeyGenerator DEFAULT_KEY_GENERATOR = referenceConfig -> {
String iName = referenceConfig.getInterface();
Expand All @@ -63,7 +63,15 @@ public class SimpleReferenceCache implements ReferenceCache {
throw new IllegalArgumentException("No interface info in ReferenceConfig" + referenceConfig);
}

return BaseServiceMetadata.buildServiceKey(iName, referenceConfig.getGroup(), referenceConfig.getVersion());
String key =
BaseServiceMetadata.buildServiceKey(iName, referenceConfig.getGroup(), referenceConfig.getVersion());

String registryIds = referenceConfig.getRegistryIds();
if (StringUtils.isNotEmpty(registryIds)) {
key += "@registry=" + registryIds;
}

return key;
};

private static final AtomicInteger nameIndex = new AtomicInteger();
Expand All @@ -74,7 +82,6 @@ public class SimpleReferenceCache implements ReferenceCache {

private final ConcurrentMap<String, List<ReferenceConfigBase<?>>> referenceKeyMap = new ConcurrentHashMap<>();
private final ConcurrentMap<Class<?>, List<ReferenceConfigBase<?>>> referenceTypeMap = new ConcurrentHashMap<>();
private final Map<ReferenceConfigBase<?>, Object> references = new ConcurrentHashMap<>();

protected SimpleReferenceCache(String name, KeyGenerator generator) {
this.name = name;
Expand Down Expand Up @@ -133,9 +140,11 @@ public <T> T get(ReferenceConfigBase<T> rc, boolean check) {
if (proxy == null) {
List<ReferenceConfigBase<?>> referencesOfType = ConcurrentHashMapUtils.computeIfAbsent(
referenceTypeMap, type, _t -> Collections.synchronizedList(new ArrayList<>()));
assert referencesOfType != null;
referencesOfType.add(rc);
List<ReferenceConfigBase<?>> referenceConfigList = ConcurrentHashMapUtils.computeIfAbsent(
referenceKeyMap, key, _k -> Collections.synchronizedList(new ArrayList<>()));
assert referenceConfigList != null;
referenceConfigList.add(rc);
proxy = rc.get(check);
}
Expand Down Expand Up @@ -302,10 +311,6 @@ public Map<String, List<ReferenceConfigBase<?>>> getReferenceMap() {
return referenceKeyMap;
}

public Map<Class<?>, List<ReferenceConfigBase<?>>> getReferenceTypeMap() {
return referenceTypeMap;
}

@Override
public String toString() {
return "ReferenceCache(name: " + name + ")";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.apache.dubbo.common.config.ReferenceCache;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.SysProps;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
Expand All @@ -26,9 +27,11 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ReferenceCacheTest {
Expand All @@ -52,17 +55,15 @@ public void tearDown() {
}

@Test
void testGetCacheSameReference() throws Exception {
void testGetCacheSameReference() {
ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
assertEquals(0L, config.getCounter());
Object proxy = cache.get(config);
assertTrue(config.isGetMethodRun());

// singleton reference config by default
MockReferenceConfig configCopy =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig configCopy = buildMockReferenceConfig();
assertEquals(1L, configCopy.getCounter());
Object proxyOfCopyConfig = cache.get(configCopy);
assertFalse(configCopy.isGetMethodRun());
Expand All @@ -73,47 +74,43 @@ void testGetCacheSameReference() throws Exception {
}

@Test
void testGetCacheDiffReference() throws Exception {
void testGetCacheDiffReference() {
ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
assertEquals(0L, config.getCounter());
cache.get(config);
assertEquals(1L, config.getCounter());
assertTrue(config.isGetMethodRun());
cache.get(config);
assertEquals(1L, config.getCounter());

XxxMockReferenceConfig configCopy =
buildXxxMockReferenceConfig("org.apache.dubbo.config.utils.service.XxxService", "group1", "1.0.0");
XxxMockReferenceConfig configCopy = buildXxxMockReferenceConfig();
assertEquals(0L, configCopy.getCounter());
cache.get(configCopy);
assertTrue(configCopy.isGetMethodRun());
assertEquals(1L, configCopy.getCounter());
}

@Test
void testGetCacheWithKey() throws Exception {
void testGetCacheWithKey() {
ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
FooService value = cache.get(config);
assertEquals(
value, cache.get("group1/org.apache.dubbo.config.utils.service.FooService:1.0.0", FooService.class));
}

@Test
void testGetCacheDiffName() throws Exception {
void testGetCacheDiffName() {
SimpleReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
assertEquals(0L, config.getCounter());
cache.get(config);
assertTrue(config.isGetMethodRun());
assertEquals(1L, config.getCounter());

cache = SimpleReferenceCache.getCache("foo");
config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
config = buildMockReferenceConfig();
assertEquals(1L, config.getCounter());
cache.get(config);
// still init for the same ReferenceConfig if the cache is different
Expand All @@ -122,13 +119,11 @@ void testGetCacheDiffName() throws Exception {
}

@Test
void testDestroy() throws Exception {
void testDestroy() {
SimpleReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
cache.get(config);
XxxMockReferenceConfig configCopy =
buildXxxMockReferenceConfig("org.apache.dubbo.config.utils.service.XxxService", "group1", "1.0.0");
XxxMockReferenceConfig configCopy = buildXxxMockReferenceConfig();
cache.get(configCopy);
assertEquals(2, cache.getReferenceMap().size());
cache.destroy(config);
Expand All @@ -140,13 +135,11 @@ void testDestroy() throws Exception {
}

@Test
void testDestroyAll() throws Exception {
void testDestroyAll() {
SimpleReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config =
buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
MockReferenceConfig config = buildMockReferenceConfig();
cache.get(config);
XxxMockReferenceConfig configCopy =
buildXxxMockReferenceConfig("org.apache.dubbo.config.utils.service.XxxService", "group1", "1.0.0");
XxxMockReferenceConfig configCopy = buildXxxMockReferenceConfig();
cache.get(configCopy);
assertEquals(2, cache.getReferenceMap().size());
cache.destroyAll();
Expand All @@ -155,25 +148,51 @@ void testDestroyAll() throws Exception {
assertEquals(0, cache.getReferenceMap().size());
}

private MockReferenceConfig buildMockReferenceConfig(String service, String group, String version) {
private MockReferenceConfig buildMockReferenceConfig() {
MockReferenceConfig config = new MockReferenceConfig();
config.setApplication(new ApplicationConfig("cache"));
config.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
config.setCheck(false);
config.setInterface(service);
config.setGroup(group);
config.setVersion(version);
config.setInterface("org.apache.dubbo.config.utils.service.FooService");
config.setGroup("group1");
config.setVersion("1.0.0");
return config;
}

private XxxMockReferenceConfig buildXxxMockReferenceConfig(String service, String group, String version) {
private XxxMockReferenceConfig buildXxxMockReferenceConfig() {
XxxMockReferenceConfig config = new XxxMockReferenceConfig();
config.setApplication(new ApplicationConfig("cache"));
config.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
config.setInterface(service);
config.setInterface("org.apache.dubbo.config.utils.service.XxxService");
config.setCheck(false);
config.setGroup(group);
config.setVersion(version);
config.setGroup("group1");
config.setVersion("1.0.0");
return config;
}

@Test
void testKeyGenerationWithRegistry() {
// Mock two ReferenceConfigs with same Interface/Group/Version
ReferenceConfigBase<?> rc1 = Mockito.mock(ReferenceConfigBase.class);
ReferenceConfigBase<?> rc2 = Mockito.mock(ReferenceConfigBase.class);

Mockito.when(rc1.getInterface()).thenReturn("org.apache.dubbo.config.utils.service.FooService");
Mockito.when(rc1.getGroup()).thenReturn("group1");
Mockito.when(rc1.getVersion()).thenReturn("1.0.0");

Mockito.when(rc2.getInterface()).thenReturn("org.apache.dubbo.config.utils.service.FooService");
Mockito.when(rc2.getGroup()).thenReturn("group1");
Mockito.when(rc2.getVersion()).thenReturn("1.0.0");

Mockito.when(rc1.getRegistryIds()).thenReturn("registry-A");
Mockito.when(rc2.getRegistryIds()).thenReturn("registry-B");

String key1 = SimpleReferenceCache.DEFAULT_KEY_GENERATOR.generateKey(rc1);
String key2 = SimpleReferenceCache.DEFAULT_KEY_GENERATOR.generateKey(rc2);

assertNotEquals(key1, key2, "Keys should be different for different registries!");

assertTrue(key1.contains("@registry=registry-A"));
assertTrue(key2.contains("@registry=registry-B"));
}
}
Loading