瀏覽代碼

ZOOKEEPER-3203: Tracking the number of non voting followers in ZK

Author: Fangmin Lyu <fangmin@apache.org>

Reviewers: andor@apache.org

Closes #722 from lvfangmin/ZOOKEEPER-3203
Fangmin Lyu 6 年之前
父節點
當前提交
9e309557c0

+ 1 - 0
zookeeper-server/src/main/java/org/apache/zookeeper/server/admin/Commands.java

@@ -369,6 +369,7 @@ public class Commands {
 
                 response.put("learners", leader.getLearners().size());
                 response.put("synced_followers", leader.getForwardingFollowers().size());
+                response.put("synced_non_voting_followers", leader.getNonVotingFollowers().size());
                 response.put("synced_observers", leader.getObservingLearners().size());
                 response.put("pending_syncs", leader.getNumPendingSyncs());
                 response.put("leader_uptime", leader.getUptime());

+ 1 - 0
zookeeper-server/src/main/java/org/apache/zookeeper/server/command/MonitorCommand.java

@@ -73,6 +73,7 @@ public class MonitorCommand extends AbstractFourLetterCommand {
 
             print("learners", leader.getLearners().size());
             print("synced_followers", leader.getForwardingFollowers().size());
+            print("synced_non_voting_followers", leader.getNonVotingFollowers().size());
             print("pending_syncs", leader.getNumPendingSyncs());
 
             print("last_proposal_size", leader.getProposalStats().getLastBufferSize());

+ 13 - 1
zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java

@@ -152,7 +152,19 @@ public class Leader implements LearnerMaster {
         }
     }
 
-    private void addForwardingFollower(LearnerHandler lh) {
+    public List<LearnerHandler> getNonVotingFollowers() {
+        List<LearnerHandler> nonVotingFollowers = new ArrayList<LearnerHandler>();
+        synchronized (forwardingFollowers) {
+            for (LearnerHandler lh : forwardingFollowers) {
+                if (!isParticipant(lh.getSid())) {
+                    nonVotingFollowers.add(lh);
+                }
+            }
+        }
+        return nonVotingFollowers;
+    }
+
+    void addForwardingFollower(LearnerHandler lh) {
         synchronized (forwardingFollowers) {
             forwardingFollowers.add(lh);
         }

+ 9 - 0
zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/LeaderBean.java

@@ -51,6 +51,15 @@ public class LeaderBean extends ZooKeeperServerBean implements LeaderMXBean {
         return sb.toString();
     }
 
+    @Override
+    public String nonVotingFollowerInfo() {
+        StringBuilder sb = new StringBuilder();
+        for (LearnerHandler handler : leader.getNonVotingFollowers()) {
+            sb.append(handler.toString()).append("\n");
+        }
+        return sb.toString();
+    }
+
     @Override
     public long getElectionTimeTaken() {
         return leader.self.getElectionTimeTaken();

+ 5 - 0
zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/LeaderMXBean.java

@@ -34,6 +34,11 @@ public interface LeaderMXBean extends ZooKeeperServerMXBean {
      */
     public String followerInfo();
 
+    /**
+     * @return information about current non-voting followers
+     */
+    public String nonVotingFollowerInfo();
+
     /**
      * @return time taken for leader election in milliseconds.
      */

+ 25 - 1
zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java

@@ -45,6 +45,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertNotEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
@@ -58,6 +59,7 @@ public class LeaderBeanTest {
     private FileTxnSnapLog fileTxnSnapLog;
     private LeaderZooKeeperServer zks;
     private QuorumPeer qp;
+    private QuorumVerifier quorumVerifierMock;
 
     @Before
     public void setUp() throws IOException, X509Exception {
@@ -73,7 +75,7 @@ public class LeaderBeanTest {
                         new InetSocketAddress(clientIP, PortAssignment.unique()),
                         new InetSocketAddress(clientIP, clientPort), LearnerType.PARTICIPANT));
 
-        QuorumVerifier quorumVerifierMock = mock(QuorumVerifier.class);
+        quorumVerifierMock = mock(QuorumVerifier.class);
         when(quorumVerifierMock.getAllMembers()).thenReturn(peersView);
 
         qp.setQuorumVerifier(quorumVerifierMock, false);
@@ -173,12 +175,21 @@ public class LeaderBeanTest {
 
     @Test
     public void testFollowerInfo() throws IOException {
+        Map<Long, QuorumServer> votingMembers = new HashMap<Long, QuorumServer>();
+        votingMembers.put(1L, null);
+        votingMembers.put(2L, null);
+        votingMembers.put(3L, null);
+        when(quorumVerifierMock.getVotingMembers()).thenReturn(votingMembers);
+
         LearnerHandler follower = mock(LearnerHandler.class);
         when(follower.getLearnerType()).thenReturn(LearnerType.PARTICIPANT);
         when(follower.toString()).thenReturn("1");
+        when(follower.getSid()).thenReturn(1L);
         leader.addLearnerHandler(follower);
+        leader.addForwardingFollower(follower);
 
         assertEquals("1\n", leaderBean.followerInfo());
+        assertEquals("", leaderBean.nonVotingFollowerInfo());
 
         LearnerHandler observer = mock(LearnerHandler.class);
         when(observer.getLearnerType()).thenReturn(LearnerType.OBSERVER);
@@ -186,5 +197,18 @@ public class LeaderBeanTest {
         leader.addLearnerHandler(observer);
 
         assertEquals("1\n", leaderBean.followerInfo());
+        assertEquals("", leaderBean.nonVotingFollowerInfo());
+
+        LearnerHandler nonVotingFollower = mock(LearnerHandler.class);
+        when(nonVotingFollower.getLearnerType()).thenReturn(LearnerType.PARTICIPANT);
+        when(nonVotingFollower.toString()).thenReturn("5");
+        when(nonVotingFollower.getSid()).thenReturn(5L);
+        leader.addLearnerHandler(nonVotingFollower);
+        leader.addForwardingFollower(nonVotingFollower);
+
+        String followerInfo = leaderBean.followerInfo();
+        assertTrue(followerInfo.contains("1"));
+        assertTrue(followerInfo.contains("5"));
+        assertEquals("5\n", leaderBean.nonVotingFollowerInfo());
     }
 }