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 <bao....@huawei.com>
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
ningji...@apache.org.

Reply via email to