Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Datastax Java Driver does not connect if one host is missing

If I am not wrong, one can connect to a Cassandra cluster knowing at least one of the nodes that is in the cluster, and then the others can be discovered.

Lets say I have three nodes (1, 2 and 3) and I connect to those nodes like this:

Cluster.builder().addContactPoints("1,2,3".split(",")).build();

Then, if node 3 for example goes down, and the IP cannot be resolved, this line of code will throw an IllegalArgumentException as stated in the docs:

@throws IllegalArgumentException if no IP address for at least one of {@code addresses} could be found

Why would anyone want this behavior? I mean, if one of the nodes is down, I want the app to be able to run, as the Cassandra is still working fine.

I have checked this Cassandra Java driver: how many contact points is reasonable? but that does not answer my question as it doesn't say anything about hosts than can't be reachable.

How should I handle this? Maybe this is changed in another version of the java driver? I am currently using cassandra-driver-core-3.0.3

like image 409
Pablo Matias Gomez Avatar asked Sep 27 '16 14:09

Pablo Matias Gomez


2 Answers

This validation is only to make sure that all the provided hosts can be resolved, it doesn't even check if a Cassandra server is running on each host. So it is basically to ensure that you did not do any typos while providing the hosts as indeed it doesn't assume that it could be a normal use case to have a provided host that cannot be resolved.

As workaround in your case (host been removed from the DNS entries), you could simply call the method addContactPoint(String address) explicitly instead of using addContactPoints(String... addresses) (which behind the scene simply call addContactPoint(String address) for each provided address) and manage the exception by yourself.

The code could be something like this:

Cluster.Builder builder = Cluster.builder();
// Boolean used to check if at least one host could be resolved
boolean found = false;
for (String address : "1,2,3".split(",")) {
    try {
        builder.addContactPoint(address);
        // One host could be resolved
        found = true;
    } catch (IllegalArgumentException e) {
        // This host could not be resolved so we log a message and keep going
        Log.log(
            Level.WARNING, 
            String.format("The host '%s' is unknown so it will be ignored", address)
        );
    }
}
if (!found) {
    // No host could be resolved so we throw an exception
    throw new IllegalStateException("All provided hosts are unknown");
}
Cluster cluster = builder.build();

FYI: I've just created a ticket to propose an improvement in the Java driver https://datastax-oss.atlassian.net/browse/JAVA-1334.

like image 142
Nicolas Filotto Avatar answered Oct 02 '22 13:10

Nicolas Filotto


As Nick mentioned, it's based on DNS resolution, not Cassandra server health.

If you remove hosts from your environment more often than you recompile your application, then you should consider not baking your contact points into the code, and instead, feed them in through some other means (environment variable, REST service, a single DNS name that always resolves to one live seed, etc).

like image 41
Jeff Jirsa Avatar answered Oct 02 '22 13:10

Jeff Jirsa