Skip to content

Commit 049a9d4

Browse files
committed
ZOOKEEPER-3100. Add feature flag with false default value
1 parent cdab396 commit 049a9d4

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

zookeeper-docs/src/main/resources/markdown/zookeeperProgrammers.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,22 @@ and [SASL authentication for ZooKeeper](https://cwiki.apache.org/confluence/disp
13761376
* *zookeeper.kinit* :
13771377
Specifies path to kinit binary. Default is "/usr/bin/kinit".
13781378
1379+
* *zookeeper.shuffleDnsResponse* :
1380+
**New in 3.10.0:**
1381+
Specifies whether ZooKeeper client should randomly pick an IP address from the DNS lookup query result when resolving
1382+
server addresses or not. This is a feature flag in order to keep the old behavior of the default DNS resolver in
1383+
`StaticHostProvider`, because we disabled it by default. The reason behind that is shuffling the response of DNS queries
1384+
shadows JVM network property `java.net.preferIPv6Addresses` (default: false). This property controls whether JVM's built-in
1385+
resolver should prioritize v4 (false value) or v6 (true value) addresses when putting together the list of IP addresses
1386+
in the result. In other words the above Java system property was completely ineffective in the case of ZooKeeper server host
1387+
resolution protocol and this must have been fixed. In a dual stack environment one might want to prefer one stack over
1388+
the other which, in case of Java processes, should be controlled by JVM network properties and ZooKeeper must honor
1389+
these settings. Since the old behavior has been with us since day zero, we introduced this feature flag in case you
1390+
need it. Such case could be when you have a buggy DNS server which responds IP addresses always in the same order and
1391+
you want to randomize that.
1392+
Default: false
1393+
1394+
13791395
<a name="C+Binding"></a>
13801396
13811397
### C Binding

zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ public ZooKeeper(ZooKeeperOptions options) throws IOException {
11401140
if (options.getHostProvider() != null) {
11411141
hostProvider = options.getHostProvider().apply(connectStringParser.getServerAddresses());
11421142
} else {
1143-
hostProvider = new StaticHostProvider(connectStringParser.getServerAddresses());
1143+
hostProvider = new StaticHostProvider(connectStringParser.getServerAddresses(), clientConfig);
11441144
}
11451145
this.hostProvider = hostProvider;
11461146

zookeeper-server/src/main/java/org/apache/zookeeper/client/StaticHostProvider.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public interface Resolver {
5050

5151
private static final Logger LOG = LoggerFactory.getLogger(StaticHostProvider.class);
5252

53+
private ZKClientConfig clientConfig = null;
54+
5355
private List<InetSocketAddress> serverAddresses = new ArrayList<>(5);
5456

5557
private Random sourceOfRandomness;
@@ -90,6 +92,26 @@ public InetAddress[] getAllByName(String name) throws UnknownHostException {
9092
});
9193
}
9294

95+
/**
96+
* Constructs a SimpleHostSet with ZKClientConfig.
97+
*
98+
* Introduced this new overload in 3.10.0 in order to take advantage of some newly introduced feature flags. Like
99+
* the shuffle (old) / not to shuffle (new) behavior of DNS resolution.
100+
*
101+
* @param serverAddresses
102+
* possibly unresolved ZooKeeper server addresses
103+
* @param clientConfig
104+
* ZooKeeper client configuration
105+
*/
106+
public StaticHostProvider(Collection<InetSocketAddress> serverAddresses, ZKClientConfig clientConfig) {
107+
init(serverAddresses, System.currentTimeMillis() ^ this.hashCode(), new Resolver() {
108+
@Override
109+
public InetAddress[] getAllByName(String name) throws UnknownHostException {
110+
return InetAddress.getAllByName(name);
111+
}
112+
}, clientConfig);
113+
}
114+
93115
/**
94116
* Constructs a SimpleHostSet.
95117
*
@@ -125,6 +147,12 @@ public InetAddress[] getAllByName(String name) throws UnknownHostException {
125147
}
126148

127149
private void init(Collection<InetSocketAddress> serverAddresses, long randomnessSeed, Resolver resolver) {
150+
init(serverAddresses, randomnessSeed, resolver, null);
151+
}
152+
153+
private void init(Collection<InetSocketAddress> serverAddresses, long randomnessSeed, Resolver resolver,
154+
ZKClientConfig clientConfig) {
155+
this.clientConfig = clientConfig == null ? new ZKClientConfig() : clientConfig;
128156
this.sourceOfRandomness = new Random(randomnessSeed);
129157
this.resolver = resolver;
130158
if (serverAddresses.isEmpty()) {
@@ -142,6 +170,9 @@ private InetSocketAddress resolve(InetSocketAddress address) {
142170
if (resolvedAddresses.isEmpty()) {
143171
return address;
144172
}
173+
if (clientConfig.isShuffleDnsResponseEnabled()) {
174+
Collections.shuffle(resolvedAddresses);
175+
}
145176
return new InetSocketAddress(resolvedAddresses.get(0), address.getPort());
146177
} catch (UnknownHostException e) {
147178
LOG.error("Unable to resolve address: {}", address.toString(), e);

zookeeper-server/src/main/java/org/apache/zookeeper/client/ZKClientConfig.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ public class ZKClientConfig extends ZKConfig {
6060
* Feature is disabled by default.
6161
*/
6262
public static final long ZOOKEEPER_REQUEST_TIMEOUT_DEFAULT = 0;
63+
/**
64+
* True value preserves the old behavior is to shuffle the addresses in DNS response regardless of address type.
65+
* This could help with buggy DNS servers which always return addresses in the same order, but at the same time
66+
* ignores the JVM option java.net.preferIPv6Addresses.
67+
*/
68+
public static final String ZOOKEEPER_SHUFFLE_DNS_RESPONSE = "zookeeper.shuffleDnsResponse";
69+
public static final boolean ZOOKEEPER_SHUFFLE_DNS_RESPONSE_DEFAULT = false;
6370

6471
public ZKClientConfig() {
6572
super();
@@ -134,6 +141,14 @@ public boolean isSaslClientEnabled() {
134141
return Boolean.valueOf(getProperty(ENABLE_CLIENT_SASL_KEY, ENABLE_CLIENT_SASL_DEFAULT));
135142
}
136143

144+
/**
145+
* Return true if we need to use the old behavior of default DNS resolver and always shuffle the IP addresses
146+
* in the DNS lookup response in order to pick a completely random IP address.
147+
*/
148+
public boolean isShuffleDnsResponseEnabled() {
149+
return getBoolean(ZOOKEEPER_SHUFFLE_DNS_RESPONSE, ZOOKEEPER_SHUFFLE_DNS_RESPONSE_DEFAULT);
150+
}
151+
137152
/**
138153
* Get the value of the <code>key</code> property as an <code>long</code>.
139154
* If property is not set, the provided <code>defaultValue</code> is

0 commit comments

Comments
 (0)