You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/01/26 01:10:43 UTC

[incubator-servicecomb-java-chassis] branch master updated: SCB-299 bug fix: ClientPoolManager thread binding memory leak.

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new ed15183  SCB-299 bug fix: ClientPoolManager thread binding memory leak.
ed15183 is described below

commit ed15183f8e0047fadadf562e1b411968a923ef3b
Author: wujimin <wu...@huawei.com>
AuthorDate: Wed Jan 24 21:40:13 2018 +0800

    SCB-299 bug fix: ClientPoolManager thread binding memory leak.
---
 .../foundation/vertx/client/ClientPoolManager.java | 27 +++++---------
 .../vertx/client/TestClientPoolManager.java        | 42 ++++++++++++++++++++++
 2 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java
index b346947..a79b86d 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java
@@ -18,13 +18,10 @@
 package org.apache.servicecomb.foundation.vertx.client;
 
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
-
 import io.vertx.core.Context;
 import io.vertx.core.Vertx;
 
@@ -50,12 +47,9 @@ public class ClientPoolManager<CLIENT_POOL> {
 
   private List<CLIENT_POOL> pools = new CopyOnWriteArrayList<>();
 
-  private AtomicInteger bindIndex = new AtomicInteger();
-
-  // send的调用线程与CLIENT_POOL的绑定关系,不直接用hash,是担心分配不均
-  // key是调用者的线程id
-  // TODO:要不要考虑已经绑定的线程消失了的场景?
-  private Map<Long, CLIENT_POOL> threadBindMap = new ConcurrentHashMapEx<>();
+  // reactive mode, when call from other thread, must select a context for it
+  // if we use threadId to hash a context, will always select the same context from one thread
+  private AtomicInteger reactiveNextIndex = new AtomicInteger();
 
   public ClientPoolManager(Vertx vertx, ClientPoolFactory<CLIENT_POOL> factory) {
     this.vertx = vertx;
@@ -103,18 +97,15 @@ public class ClientPoolManager<CLIENT_POOL> {
     // 2.vertx worker thread
     // 3.other vertx thread
     // select a existing context
-    return nextPool();
+    int idx = reactiveNextIndex.getAndIncrement() % pools.size();
+    if (idx < 0) {
+      idx = -idx;
+    }
+    return pools.get(idx);
   }
 
   public CLIENT_POOL findThreadBindClientPool() {
-    long threadId = Thread.currentThread().getId();
-    return threadBindMap.computeIfAbsent(threadId, tid -> {
-      return nextPool();
-    });
-  }
-
-  protected CLIENT_POOL nextPool() {
-    int idx = bindIndex.getAndIncrement() % pools.size();
+    int idx = (int) (Thread.currentThread().getId() % pools.size());
     return pools.get(idx);
   }
 }
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java
index 3817d1b..884aecc 100644
--- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.foundation.vertx.client;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext;
 import org.hamcrest.Matchers;
@@ -117,9 +118,27 @@ public class TestClientPoolManager {
     pools.add(pool1);
     pools.add(pool2);
 
+    new MockUp<Thread>() {
+      @Mock
+      long getId() {
+        return 0;
+      }
+    };
+
     Assert.assertSame(pool1, poolMgr.findThreadBindClientPool());
     // find again, get the same result
     Assert.assertSame(pool1, poolMgr.findThreadBindClientPool());
+
+    new MockUp<Thread>() {
+      @Mock
+      long getId() {
+        return 1;
+      }
+    };
+
+    Assert.assertSame(pool2, poolMgr.findThreadBindClientPool());
+    // find again, get the same result
+    Assert.assertSame(pool2, poolMgr.findThreadBindClientPool());
   }
 
   @Test
@@ -143,6 +162,29 @@ public class TestClientPoolManager {
   }
 
   @Test
+  public void findByContext_wrongContext_reverse() {
+    HttpClientWithContext pool1 = new HttpClientWithContext(null, null);
+    HttpClientWithContext pool2 = new HttpClientWithContext(null, null);
+    pools.add(pool1);
+    pools.add(pool2);
+
+    new Expectations(VertxImpl.class) {
+      {
+        VertxImpl.context();
+        result = null;
+      }
+    };
+
+    AtomicInteger reactiveNextIndex = Deencapsulation.getField(poolMgr, "reactiveNextIndex");
+    reactiveNextIndex.set(Integer.MAX_VALUE);
+    // each time invoke find, reactiveNextIndex will inc 1
+    Assert.assertSame(pool2, poolMgr.findByContext());
+    Assert.assertSame(pool1, poolMgr.findByContext());
+    Assert.assertSame(pool2, poolMgr.findByContext());
+    Assert.assertSame(pool1, poolMgr.findByContext());
+  }
+
+  @Test
   public void findByContext_normalThread() {
     HttpClientWithContext pool = new HttpClientWithContext(null, null);
     pools.add(pool);

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.