You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2021/07/31 07:54:53 UTC

[hbase] branch branch-2 updated: HBASE-26151 Reimplement MasterAddressTracker to also cache backup master addresses (#3548)

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

zhangduo pushed a commit to branch branch-2
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-2 by this push:
     new f7baa195 HBASE-26151 Reimplement MasterAddressTracker to also cache backup master addresses (#3548)
f7baa195 is described below

commit f7baa195e3d745a74cab1b9c7d7ed0dd77849024
Author: Duo Zhang <zh...@apache.org>
AuthorDate: Sat Jul 31 15:39:08 2021 +0800

    HBASE-26151 Reimplement MasterAddressTracker to also cache backup master addresses (#3548)
    
    Signed-off-by: Yulin Niu <ni...@apache.org>
---
 .../hadoop/hbase/master/TestSplitLogManager.java   |  3 +-
 .../hbase/zookeeper/MasterAddressTracker.java      | 30 +++++++-
 .../hadoop/hbase/zookeeper/ZKNodeTracker.java      | 25 ++++---
 .../hbase/zookeeper}/TestMasterAddressTracker.java | 83 ++++++++++------------
 4 files changed, 81 insertions(+), 60 deletions(-)

diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestSplitLogManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestSplitLogManager.java
index 17b0f6b..5fee364 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestSplitLogManager.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestSplitLogManager.java
@@ -33,6 +33,7 @@ import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_task_deleted;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+
 import java.io.IOException;
 import java.util.Map;
 import java.util.concurrent.atomic.LongAdder;
@@ -51,10 +52,10 @@ import org.apache.hadoop.hbase.coordination.ZKSplitLogManagerCoordination;
 import org.apache.hadoop.hbase.coordination.ZkCoordinatedStateManager;
 import org.apache.hadoop.hbase.master.SplitLogManager.Task;
 import org.apache.hadoop.hbase.master.SplitLogManager.TaskBatch;
-import org.apache.hadoop.hbase.regionserver.TestMasterAddressTracker.NodeCreationListener;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
 import org.apache.hadoop.hbase.testclassification.MasterTests;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
+import org.apache.hadoop.hbase.zookeeper.TestMasterAddressTracker.NodeCreationListener;
 import org.apache.hadoop.hbase.zookeeper.ZKSplitLog;
 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
 import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
diff --git a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/MasterAddressTracker.java b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/MasterAddressTracker.java
index 133d966..748fb8b 100644
--- a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/MasterAddressTracker.java
+++ b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/MasterAddressTracker.java
@@ -19,7 +19,6 @@ package org.apache.hadoop.hbase.zookeeper;
 
 import java.io.IOException;
 import java.io.InterruptedIOException;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -33,6 +32,7 @@ import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.data.Stat;
 
 import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
+
 import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos;
@@ -57,6 +57,9 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos;
  */
 @InterfaceAudience.Private
 public class MasterAddressTracker extends ZKNodeTracker {
+
+  private volatile List<ServerName> backupMasters = Collections.emptyList();
+
   /**
    * Construct a master address listener with the specified
    * <code>zookeeper</code> reference.
@@ -72,6 +75,26 @@ public class MasterAddressTracker extends ZKNodeTracker {
     super(watcher, watcher.getZNodePaths().masterAddressZNode, abortable);
   }
 
+  private void loadBackupMasters() {
+    try {
+      backupMasters = Collections.unmodifiableList(getBackupMastersAndRenewWatch(watcher));
+    } catch (InterruptedIOException e) {
+      abortable.abort("Unexpected exception handling nodeChildrenChanged event", e);
+    }
+  }
+
+  @Override
+  protected void postStart() {
+    loadBackupMasters();
+  }
+
+  @Override
+  public void nodeChildrenChanged(String path) {
+    if (path.equals(watcher.getZNodePaths().backupMasterAddressesZNode)) {
+      loadBackupMasters();
+    }
+  }
+
   /**
    * Get the address of the current master if one is available.  Returns null
    * if no current master.
@@ -252,11 +275,12 @@ public class MasterAddressTracker extends ZKNodeTracker {
     }
     int prefixLen = ProtobufUtil.lengthOfPBMagic();
     try {
-      return ZooKeeperProtos.Master.PARSER.parseFrom(data, prefixLen, data.length - prefixLen);
+      return ZooKeeperProtos.Master.parser().parseFrom(data, prefixLen, data.length - prefixLen);
     } catch (InvalidProtocolBufferException e) {
       throw new DeserializationException(e);
     }
   }
+
   /**
    * delete the master znode if its content is same as the parameter
    * @param zkw must not be null
@@ -284,7 +308,7 @@ public class MasterAddressTracker extends ZKNodeTracker {
   }
 
   public List<ServerName> getBackupMasters() throws InterruptedIOException {
-    return getBackupMastersAndRenewWatch(watcher);
+    return backupMasters;
   }
 
   /**
diff --git a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKNodeTracker.java b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKNodeTracker.java
index 3dc9efa..63de74c 100644
--- a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKNodeTracker.java
+++ b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKNodeTracker.java
@@ -42,7 +42,7 @@ public abstract class ZKNodeTracker extends ZKListener {
   protected final String node;
 
   /** Data of the node being tracked */
-  private byte [] data;
+  private byte[] data;
 
   /** Used to abort if a fatal error occurs */
   protected final Abortable abortable;
@@ -51,16 +51,14 @@ public abstract class ZKNodeTracker extends ZKListener {
 
   /**
    * Constructs a new ZK node tracker.
-   *
-   * <p>After construction, use {@link #start} to kick off tracking.
-   *
+   * <p/>
+   * After construction, use {@link #start} to kick off tracking.
    * @param watcher reference to the {@link ZKWatcher} which also contains configuration and
-   *                constants
+   *          constants
    * @param node path of the node being tracked
    * @param abortable used to abort if a fatal error occurs
    */
-  public ZKNodeTracker(ZKWatcher watcher, String node,
-                       Abortable abortable) {
+  public ZKNodeTracker(ZKWatcher watcher, String node, Abortable abortable) {
     super(watcher);
     this.node = node;
     this.abortable = abortable;
@@ -69,9 +67,9 @@ public abstract class ZKNodeTracker extends ZKListener {
 
   /**
    * Starts the tracking of the node in ZooKeeper.
-   *
-   * <p>Use {@link #blockUntilAvailable()} to block until the node is available
-   * or {@link #getData(boolean)} to get the data of the node if it is available.
+   * <p/>
+   * Use {@link #blockUntilAvailable()} to block until the node is available or
+   * {@link #getData(boolean)} to get the data of the node if it is available.
    */
   public synchronized void start() {
     this.watcher.registerListener(this);
@@ -89,6 +87,13 @@ public abstract class ZKNodeTracker extends ZKListener {
     } catch (KeeperException e) {
       abortable.abort("Unexpected exception during initialization, aborting", e);
     }
+    postStart();
+  }
+
+  /**
+   * Called after start is called. Sub classes could implement this method to load more data on zk.
+   */
+  protected void postStart() {
   }
 
   public synchronized void stop() {
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMasterAddressTracker.java b/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestMasterAddressTracker.java
similarity index 73%
rename from hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMasterAddressTracker.java
rename to hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestMasterAddressTracker.java
index cba05a4..e2ada94 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMasterAddressTracker.java
+++ b/hbase-zookeeper/src/test/java/org/apache/hadoop/hbase/zookeeper/TestMasterAddressTracker.java
@@ -15,7 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.hadoop.hbase.regionserver;
+package org.apache.hadoop.hbase.zookeeper;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -25,16 +25,11 @@ import static org.junit.Assert.assertTrue;
 import java.util.List;
 import java.util.concurrent.Semaphore;
 import org.apache.hadoop.hbase.HBaseClassTestRule;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HBaseZKTestingUtility;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
-import org.apache.hadoop.hbase.testclassification.RegionServerTests;
+import org.apache.hadoop.hbase.testclassification.ZKTests;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
-import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
-import org.apache.hadoop.hbase.zookeeper.ZKListener;
-import org.apache.hadoop.hbase.zookeeper.ZKUtil;
-import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
-import org.apache.hadoop.hbase.zookeeper.ZNodePaths;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -46,18 +41,19 @@ import org.junit.rules.TestName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Category({RegionServerTests.class, MediumTests.class})
+@Category({ ZKTests.class, MediumTests.class })
 public class TestMasterAddressTracker {
 
   @ClassRule
   public static final HBaseClassTestRule CLASS_RULE =
-      HBaseClassTestRule.forClass(TestMasterAddressTracker.class);
+    HBaseClassTestRule.forClass(TestMasterAddressTracker.class);
 
   private static final Logger LOG = LoggerFactory.getLogger(TestMasterAddressTracker.class);
 
-  private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+  private final static HBaseZKTestingUtility TEST_UTIL = new HBaseZKTestingUtility();
+
   // Cleaned up after each unit test.
-  private static ZKWatcher zk;
+  private ZKWatcher zk;
 
   @Rule
   public TestName name = new TestName();
@@ -81,15 +77,15 @@ public class TestMasterAddressTracker {
 
   @Test
   public void testDeleteIfEquals() throws Exception {
-    final ServerName sn = ServerName.valueOf("localhost", 1234,
-      EnvironmentEdgeManager.currentTime());
+    final ServerName sn =
+      ServerName.valueOf("localhost", 1234, EnvironmentEdgeManager.currentTime());
     final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1772);
     try {
       assertFalse("shouldn't have deleted wrong master server.",
-          MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), "some other string."));
+        MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), "some other string."));
     } finally {
       assertTrue("Couldn't clean up master",
-          MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
+        MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
     }
   }
 
@@ -99,9 +95,8 @@ public class TestMasterAddressTracker {
    * @param infoPort if there is an active master, set its info port.
    */
   private MasterAddressTracker setupMasterTracker(final ServerName sn, final int infoPort)
-      throws Exception {
-    zk = new ZKWatcher(TEST_UTIL.getConfiguration(),
-        name.getMethodName(), null);
+    throws Exception {
+    zk = new ZKWatcher(TEST_UTIL.getConfiguration(), name.getMethodName(), null);
     ZKUtil.createAndFailSilent(zk, zk.getZNodePaths().baseZNode);
     ZKUtil.createAndFailSilent(zk, zk.getZNodePaths().backupMasterAddressesZNode);
 
@@ -112,14 +107,14 @@ public class TestMasterAddressTracker {
     zk.registerListener(addressTracker);
 
     // Use a listener to capture when the node is actually created
-    NodeCreationListener listener = new NodeCreationListener(zk,
-            zk.getZNodePaths().masterAddressZNode);
+    NodeCreationListener listener =
+      new NodeCreationListener(zk, zk.getZNodePaths().masterAddressZNode);
     zk.registerListener(listener);
 
     if (sn != null) {
       LOG.info("Creating master node");
-      MasterAddressTracker.setMasterAddress(zk, zk.getZNodePaths().masterAddressZNode,
-              sn, infoPort);
+      MasterAddressTracker.setMasterAddress(zk, zk.getZNodePaths().masterAddressZNode, sn,
+        infoPort);
 
       // Wait for the node to be created
       LOG.info("Waiting for master address manager to be notified");
@@ -130,16 +125,15 @@ public class TestMasterAddressTracker {
   }
 
   /**
-   * Unit tests that uses ZooKeeper but does not use the master-side methods
-   * but rather acts directly on ZK.
-   * @throws Exception
+   * Unit tests that uses ZooKeeper but does not use the master-side methods but rather acts
+   * directly on ZK.
    */
   @Test
   public void testMasterAddressTrackerFromZK() throws Exception {
     // Create the master node with a dummy address
     final int infoPort = 1235;
-    final ServerName sn = ServerName.valueOf("localhost", 1234,
-      EnvironmentEdgeManager.currentTime());
+    final ServerName sn =
+      ServerName.valueOf("localhost", 1234, EnvironmentEdgeManager.currentTime());
     final MasterAddressTracker addressTracker = setupMasterTracker(sn, infoPort);
     try {
       assertTrue(addressTracker.hasMaster());
@@ -148,11 +142,10 @@ public class TestMasterAddressTracker {
       assertEquals(infoPort, addressTracker.getMasterInfoPort());
     } finally {
       assertTrue("Couldn't clean up master",
-          MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
+        MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
     }
   }
 
-
   @Test
   public void testParsingNull() throws Exception {
     assertNull("parse on null data should return null.", MasterAddressTracker.parse(null));
@@ -160,17 +153,16 @@ public class TestMasterAddressTracker {
 
   @Test
   public void testNoBackups() throws Exception {
-    final ServerName sn = ServerName.valueOf("localhost", 1234,
-      EnvironmentEdgeManager.currentTime());
+    final ServerName sn =
+      ServerName.valueOf("localhost", 1234, EnvironmentEdgeManager.currentTime());
     final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1772);
     try {
       assertEquals("Should receive 0 for backup not found.", 0,
-        addressTracker.getBackupMasterInfoPort(
-          ServerName.valueOf("doesnotexist.example.com", 1234,
-            EnvironmentEdgeManager.currentTime())));
+        addressTracker.getBackupMasterInfoPort(ServerName.valueOf("doesnotexist.example.com", 1234,
+          EnvironmentEdgeManager.currentTime())));
     } finally {
       assertTrue("Couldn't clean up master",
-          MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
+        MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
     }
   }
 
@@ -184,8 +176,8 @@ public class TestMasterAddressTracker {
 
   @Test
   public void testBackupMasters() throws Exception {
-    final ServerName sn = ServerName.valueOf("localhost", 5678,
-      EnvironmentEdgeManager.currentTime());
+    final ServerName sn =
+      ServerName.valueOf("localhost", 5678, EnvironmentEdgeManager.currentTime());
     final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1111);
     assertTrue(addressTracker.hasMaster());
     ServerName activeMaster = addressTracker.getMasterAddress();
@@ -195,13 +187,14 @@ public class TestMasterAddressTracker {
     assertEquals(0, backupMasters.size());
     ServerName backupMaster1 = ServerName.valueOf("localhost", 2222, -1);
     ServerName backupMaster2 = ServerName.valueOf("localhost", 3333, -1);
-    String backupZNode1 = ZNodePaths.joinZNode(
-        zk.getZNodePaths().backupMasterAddressesZNode, backupMaster1.toString());
-    String backupZNode2 = ZNodePaths.joinZNode(
-        zk.getZNodePaths().backupMasterAddressesZNode, backupMaster2.toString());
-    // Add a backup master
+    String backupZNode1 =
+      ZNodePaths.joinZNode(zk.getZNodePaths().backupMasterAddressesZNode, backupMaster1.toString());
+    String backupZNode2 =
+      ZNodePaths.joinZNode(zk.getZNodePaths().backupMasterAddressesZNode, backupMaster2.toString());
+    // Add backup masters
     MasterAddressTracker.setMasterAddress(zk, backupZNode1, backupMaster1, 2222);
     MasterAddressTracker.setMasterAddress(zk, backupZNode2, backupMaster2, 3333);
+    TEST_UTIL.waitFor(30000, () -> addressTracker.getBackupMasters().size() == 2);
     backupMasters = addressTracker.getBackupMasters();
     assertEquals(2, backupMasters.size());
     assertTrue(backupMasters.contains(backupMaster1));
@@ -222,7 +215,7 @@ public class TestMasterAddressTracker {
 
     @Override
     public void nodeCreated(String path) {
-      if(path.equals(node)) {
+      if (path.equals(node)) {
         LOG.debug("nodeCreated(" + path + ")");
         lock.release();
       }
@@ -232,6 +225,4 @@ public class TestMasterAddressTracker {
       lock.acquire();
     }
   }
-
 }
-