All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bazaarvoice.curator.ResolvingEnsembleProvider Maven / Gradle / Ivy

There is a newer version: 2.1.2
Show newest version
package com.bazaarvoice.curator;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.net.HostAndPort;
import org.apache.curator.ensemble.EnsembleProvider;
import org.apache.curator.ensemble.fixed.FixedEnsembleProvider;
import org.apache.zookeeper.client.ConnectStringParser;
import org.apache.zookeeper.version.Info;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * DEPRECATED: Newer versions of ZooKeeper do the right thing, so this is no longer necessary. This is now
 * just a a compatibility shim and will be removed in future versions.
 * 

* An ensemble provider that performs DNS resolution to build the connection string. This strategy allows the connection * string to adapt to changes in DNS. All resolvable hosts in the original connection string are expanded to their IP * addresses. Hosts with multiple IP addresses (i.e., those with multiple A records) will result in multiple * corresponding servers in the expanded connection string. The servers in the expanded connection string are sorted to * produce a canonical form. *

*

* NOTE: There are two main things that could cause results that may differ from expectations. *

*

* Firstly, Java performs its own DNS caching. Cache TTLs can be configured with security properties * {@code networkaddress.cache.ttl} and {@code networkaddress.cache.negative.ttl} or corresponding system properties * {@code sun.net.inetaddr.ttl} and {@code sun.net.inetaddr.negative.ttl}. The default cache TTL is implementation * specific, but typically 30 seconds if there is no security manager installed and infinite if there is. The default * negative cache (caching nonexistence of a record) TTL is 10 seconds. *

*

* Secondly, for a consistent connection string, the DNS provider must produce all records for a hostname. Some DNS * servers will only provide a subset of the records for a given hostname - for example, tinydns returns a maximum of 8 * records in response to a query. *

*/ public class ResolvingEnsembleProvider implements EnsembleProvider { private EnsembleProvider _delegate; private static EnsembleProvider defaultDelegate(String connectString) { // ZooKeeper 3.4.13 and 3.5.5 are have the fixed HostProvider if (Info.MAJOR < 3 || (Info.MAJOR == 3 && (Info.MINOR < 4 || (Info.MINOR == 4 && Info.MICRO < 13) || (Info.MINOR == 5 && Info.MICRO < 5) ) ) ) { return new FixedEnsembleProvider(connectString); } else { return new ResolvingEnsembleProviderDelegate(connectString); } } public ResolvingEnsembleProvider(String connectString) { this(defaultDelegate(connectString)); } @VisibleForTesting ResolvingEnsembleProvider(EnsembleProvider delegate) { _delegate = delegate; } @Override public void start() throws Exception { _delegate.start(); } @Override public String getConnectionString() { return _delegate.getConnectionString(); } @Override public void close() throws IOException { _delegate.close(); } @Override public void setConnectionString(String connectString) { _delegate.setConnectionString(connectString); } @Override public boolean updateServerListEnabled() { return _delegate.updateServerListEnabled(); } @VisibleForTesting static class ResolvingEnsembleProviderDelegate implements EnsembleProvider { private ConnectStringParser _connectStringParser; private final Resolver _resolver; /** * @param connectString The original connections string. */ private ResolvingEnsembleProviderDelegate(String connectString) { this(connectString, new Resolver()); } @VisibleForTesting ResolvingEnsembleProviderDelegate(String connectString, Resolver resolver) { _resolver = resolver; _connectStringParser = new ConnectStringParser(connectString); } /** * Does nothing, as no initialization is required for this provider. * * @throws Exception Never. */ @Override public void start() throws Exception { // Do nothing. } @Override public String getConnectionString() { StringBuilder connectStringBuilder = new StringBuilder(); SortedSet addresses = new TreeSet<>(); for (InetSocketAddress hostAndPort : _connectStringParser.getServerAddresses()) { try { for (InetAddress address : _resolver.lookupAllHostAddr(hostAndPort.getHostName())) { addresses.add(HostAndPort.fromParts(address.getHostAddress(), hostAndPort.getPort()).toString()); } } catch (UnknownHostException e) { // Leave unresolvable host in connect string as-is. addresses.add(hostAndPort.toString()); } } Joiner.on(',').appendTo(connectStringBuilder, addresses); if (_connectStringParser.getChrootPath() != null) { connectStringBuilder.append(_connectStringParser.getChrootPath()); } return connectStringBuilder.toString(); } /** * Does nothing, as no cleanup is required for this provider. * * @throws IOException Never. */ @Override public void close() throws IOException { // Do nothing. } @Override public void setConnectionString(String connectString) { _connectStringParser = new ConnectStringParser(connectString); } @Override public boolean updateServerListEnabled() { return false; } @VisibleForTesting static class Resolver { InetAddress[] lookupAllHostAddr(String name) throws UnknownHostException { return InetAddress.getAllByName(name); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy