This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 22eaa4b1c46f1da7a8bb21290e18288478f1dd9d Author: bao.liu <[email protected]> AuthorDate: Wed Feb 7 14:15:36 2018 +0800 [SCB-294]when send a request to a not exist microservice, edge will always try to find instances of it --- .../consumer/MicroserviceManager.java | 28 ++++++++++++- .../consumer/MicroserviceVersions.java | 24 +++++++---- .../consumer/TestMicroserviceManager.java | 46 ++++++++++++++++++++++ .../consumer/TestMicroserviceVersions.java | 3 +- 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java index 0e93516..cc3fde5 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java @@ -17,6 +17,10 @@ package org.apache.servicecomb.serviceregistry.consumer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import java.util.Map; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; @@ -26,6 +30,8 @@ import org.apache.servicecomb.serviceregistry.task.event.RecoveryEvent; import com.google.common.eventbus.Subscribe; public class MicroserviceManager { + private static final int MAX_NUM_OF_MICROSERVICES = 1000; + private AppManager appManager; private String appId; @@ -41,11 +47,31 @@ public class MicroserviceManager { } public MicroserviceVersions getOrCreateMicroserviceVersions(String microserviceName) { - return versionsByName.computeIfAbsent(microserviceName, name -> { + MicroserviceVersions microserviceVersions = versionsByName.computeIfAbsent(microserviceName, name -> { MicroserviceVersions instance = new MicroserviceVersions(appManager, appId, microserviceName); instance.submitPull(); return instance; }); + if (!microserviceVersions.isValidated()) { + // remove this microservice if it does not exist or not registered in order to get it back when access it again + versionsByName.remove(microserviceName); + } else { + microserviceVersions.updateLastAccessTime(); + } + if (versionsByName.size() >= MAX_NUM_OF_MICROSERVICES) { + // do clean up for cache so many things + List<MicroserviceVersions> entries = new ArrayList<>(versionsByName.size()); + versionsByName.values().forEach((item) -> { + entries.add(item); + }); + Collections.sort(entries, Comparator.comparingLong(MicroserviceVersions::getLastAccessedTime)); + entries.forEach((item) -> { + if (versionsByName.size() > MAX_NUM_OF_MICROSERVICES / 2) { + versionsByName.remove(item.getMicroserviceName()); + } + }); + } + return microserviceVersions; } public MicroserviceVersionRule getOrCreateMicroserviceVersionRule(String microserviceName, diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java index f26ee05..5616aa2 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java @@ -19,7 +19,6 @@ package org.apache.servicecomb.serviceregistry.consumer; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -64,6 +63,8 @@ public class MicroserviceVersions { // only pendingPullCount is 0, then do a real pull private AtomicInteger pendingPullCount = new AtomicInteger(); + private long lastAccessedTime = -1; + public MicroserviceVersions(AppManager appManager, String appId, String microserviceName) { this.appManager = appManager; this.appId = appId; @@ -76,6 +77,18 @@ public class MicroserviceVersions { appManager.getEventBus().register(this); } + public void updateLastAccessTime() { + this.lastAccessedTime = System.currentTimeMillis(); + } + + public boolean isValidated() { + return this.lastAccessedTime != -1; + } + + public long getLastAccessedTime() { + return this.lastAccessedTime; + } + public String getAppId() { return appId; } @@ -109,8 +122,6 @@ public class MicroserviceVersions { DefinitionConst.VERSION_RULE_ALL, revision); if (microserviceInstances == null) { - // exception happens and try pull again later. - postPullInstanceEvent(TimeUnit.SECONDS.toMillis(1)); return; } if (!microserviceInstances.isNeedRefresh()) { @@ -125,13 +136,12 @@ public class MicroserviceVersions { protected void safeSetInstances(List<MicroserviceInstance> pulledInstances, String rev) { try { setInstances(pulledInstances, rev); + updateLastAccessTime(); } catch (Throwable e) { LOGGER.error("Failed to setInstances, appId={}, microserviceName={}.", getAppId(), getMicroserviceName(), e); - // exception happens and try pull again later. - postPullInstanceEvent(TimeUnit.SECONDS.toMillis(1)); } } @@ -210,9 +220,9 @@ public class MicroserviceVersions { // if pull 1/2/3, and then delete 3, but "delete 3" received before pull result, will have wrong 3. // EXPIRE:: // black/white config in SC changed, we must refresh all data from sc. - postPullInstanceEvent(TimeUnit.MILLISECONDS.toMillis(1)); + postPullInstanceEvent(0); } - + protected boolean isEventAccept(MicroserviceInstanceChangedEvent changedEvent) { return (appId.equals(changedEvent.getKey().getAppId()) && microserviceName.equals(changedEvent.getKey().getServiceName())) || diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java index 786a2d0..a703f04 100644 --- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java @@ -53,6 +53,8 @@ public class TestMicroserviceManager { MicroserviceManager microserviceManager = new MicroserviceManager(appManager, appId); + Map<String, MicroserviceVersions> cachedVersions = Deencapsulation.getField(microserviceManager, "versionsByName"); + MicroserviceInstances microserviceInstances = null; FindInstancesResponse findInstancesResponse = null; @@ -84,6 +86,50 @@ public class TestMicroserviceManager { microserviceManager.getOrCreateMicroserviceVersionRule(serviceName, versionRule); Assert.assertEquals("0.0.0+", microserviceVersionRule.getVersionRule().getVersionRule()); Assert.assertNull(microserviceVersionRule.getLatestMicroserviceVersion()); + Assert.assertEquals(1, cachedVersions.size()); + } + + @Test + public void testCreateRuleServiceNotExists() throws Exception { + new Expectations(RegistryUtils.class) { + { + RegistryUtils.findServiceInstances(appId, anyString, DefinitionConst.VERSION_RULE_ALL, null); + result = microserviceInstances; + } + }; + + for (int i = 0; i < 1005; i++) { + MicroserviceVersionRule microserviceVersionRule = + microserviceManager.getOrCreateMicroserviceVersionRule(serviceName + i, versionRule); + Assert.assertEquals("0.0.0+", microserviceVersionRule.getVersionRule().getVersionRule()); + Assert.assertNull(microserviceVersionRule.getLatestMicroserviceVersion()); + if (i == 499) { + Thread.sleep(1); + } + } + + Assert.assertEquals(505, cachedVersions.size()); + Assert.assertEquals("msName1004", cachedVersions.get("msName1004").getMicroserviceName()); + Assert.assertEquals("msName1000", cachedVersions.get("msName1000").getMicroserviceName()); + Assert.assertEquals("msName500", cachedVersions.get("msName500").getMicroserviceName()); + Assert.assertEquals(null, cachedVersions.get("msName0")); + Assert.assertEquals(null, cachedVersions.get("msName499")); + } + + @Test + public void testCreateRuleServiceMany() { + new Expectations(RegistryUtils.class) { + { + RegistryUtils.findServiceInstances(appId, serviceName, DefinitionConst.VERSION_RULE_ALL, null); + result = null; + } + }; + + MicroserviceVersionRule microserviceVersionRule = + microserviceManager.getOrCreateMicroserviceVersionRule(serviceName, versionRule); + Assert.assertEquals("0.0.0+", microserviceVersionRule.getVersionRule().getVersionRule()); + Assert.assertNull(microserviceVersionRule.getLatestMicroserviceVersion()); + Assert.assertEquals(0, cachedVersions.size()); } @Test diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java index be1e8c7..b336d88 100644 --- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java @@ -291,7 +291,8 @@ public class TestMicroserviceVersions { microserviceVersions.safeSetInstances(null, null); - Assert.assertEquals(1, pendingPullCount.get()); + Assert.assertEquals(0, pendingPullCount.get()); + Assert.assertEquals(microserviceVersions.isValidated(), false); } public void checkIsEventAccept(MicroserviceKey key, boolean expected) { -- To stop receiving notification emails like this one, please contact [email protected].
