This is an automated email from the ASF dual-hosted git repository.
nkalmar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push:
new b1105cc ZOOKEEPER-3758: Leader reachability check fails with single
address
b1105cc is described below
commit b1105ccc47685c64d1cca7ccb0b2bb66c194374a
Author: Mate Szalay-Beko <[email protected]>
AuthorDate: Thu Mar 19 17:09:38 2020 +0100
ZOOKEEPER-3758: Leader reachability check fails with single address
Since ZooKeeper 3.6.0 we can specify multiple addresses for each ZooKeeper
server instance
(this can increase availability when multiple physical network interfaces
can be used parallel
in the cluster). ZooKeeper will perform ICMP ECHO requests or try to
establish a TCP connection
on port 7 (Echo) of the destination host in order to find the reachable
addresses. This should
happen only if the user provide multiple addresses in the configuration, in
a single address is
used then ZooKeeper shouldn’t send any ICMP requests.
This works as we expected for the leader election connections, but in this
Jira issue we found
a bug when the reachability check was performed even with a single address
when the Follower
tries to connect to the newly elected Leader.
The fix follows the same approach we discussed for the election protocol
before (see
ZOOKEEPER-3698). We avoid the reachability check for single addresses. Also
when we have
multiple addresses and none of them can be reached, we still start to
connect to all addresses
in parallel.
Author: Mate Szalay-Beko <[email protected]>
Reviewers: Enrico Olivelli <[email protected]>, Norbert Kalmar
<[email protected]>
Closes #1288 from symat/ZOOKEEPER-3758
---
.../apache/zookeeper/server/quorum/Learner.java | 4 +++-
.../zookeeper/server/quorum/MultipleAddresses.java | 18 +++++++++++++++
.../server/quorum/MultipleAddressesTest.java | 26 ++++++++++++++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
index 0f8f444..8a0cac1 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
@@ -303,7 +303,9 @@ public class Learner {
this.leaderAddr = multiAddr;
Set<InetSocketAddress> addresses;
if (self.isMultiAddressReachabilityCheckEnabled()) {
- addresses = multiAddr.getAllReachableAddresses();
+ // even if none of the addresses are reachable, we want to try to
establish connection
+ // see ZOOKEEPER-3758
+ addresses = multiAddr.getAllReachableAddressesOrAll();
} else {
addresses = multiAddr.getAllAddresses();
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/MultipleAddresses.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/MultipleAddresses.java
index 3ee63fa..9f15389 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/MultipleAddresses.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/MultipleAddresses.java
@@ -140,6 +140,24 @@ public final class MultipleAddresses {
}
/**
+ * Returns a set of all reachable addresses. If none is reachable than
returns all addresses.
+ *
+ * @return all reachable addresses, or all addresses if none is reachable.
+ */
+ public Set<InetSocketAddress> getAllReachableAddressesOrAll() {
+ // if there is only a single address provided then we don't need to do
any reachability check
+ if (addresses.size() == 1) {
+ return getAllAddresses();
+ }
+
+ Set<InetSocketAddress> allReachable = getAllReachableAddresses();
+ if (allReachable.isEmpty()) {
+ return getAllAddresses();
+ }
+ return allReachable;
+ }
+
+ /**
* Returns a reachable address or an arbitrary one, if none is reachable.
It throws an exception
* if there are no addresses registered. The function is nondeterministic
in the sense that the
* result of calling this function twice with the same set of reachable
addresses might lead
diff --git
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/MultipleAddressesTest.java
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/MultipleAddressesTest.java
index e8f08c6..0e1615d 100644
---
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/MultipleAddressesTest.java
+++
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/MultipleAddressesTest.java
@@ -188,6 +188,32 @@ public class MultipleAddressesTest {
}
@Test
+ public void testGetAllReachableAddressesOrAllWhenSomeReachable() throws
Exception {
+ InetSocketAddress reachableHost1 = new InetSocketAddress("127.0.0.1",
1234);
+ InetSocketAddress reachableHost2 = new InetSocketAddress("127.0.0.1",
2345);
+ InetSocketAddress unreachableHost1 = new
InetSocketAddress("unreachable1.address.zookeeper.apache.com", 1234);
+ InetSocketAddress unreachableHost2 = new
InetSocketAddress("unreachable2.address.zookeeper.apache.com", 1234);
+
+ MultipleAddresses multipleAddresses = new MultipleAddresses(
+ Arrays.asList(unreachableHost1, unreachableHost2, reachableHost1,
reachableHost2));
+
+ Set<InetSocketAddress> reachableHosts = new
HashSet<>(Arrays.asList(reachableHost1, reachableHost2));
+ Assert.assertEquals(reachableHosts,
multipleAddresses.getAllReachableAddressesOrAll());
+ }
+
+ @Test
+ public void testGetAllReachableAddressesOrAllWhenNoneReachable() throws
Exception {
+ InetSocketAddress unreachableHost1 = new
InetSocketAddress("unreachable1.address.zookeeper.apache.com", 1234);
+ InetSocketAddress unreachableHost2 = new
InetSocketAddress("unreachable2.address.zookeeper.apache.com", 1234);
+ InetSocketAddress unreachableHost3 = new
InetSocketAddress("unreachable3.address.zookeeper.apache.com", 1234);
+ List<InetSocketAddress> allUnreachableAddresses =
Arrays.asList(unreachableHost1, unreachableHost2, unreachableHost3);
+
+ MultipleAddresses multipleAddresses = new
MultipleAddresses(allUnreachableAddresses);
+
+ Assert.assertEquals(new HashSet<>(allUnreachableAddresses),
multipleAddresses.getAllReachableAddressesOrAll());
+ }
+
+ @Test
public void testEquals() {
List<InetSocketAddress> addresses = getAddressList();