Datastax Java Driver如果缺少一个主机,则无法连接

13
如果我没记错的话,只要知道集群中至少一个节点,就可以连接到Cassandra集群,然后可以发现其他节点。

假设我有三个节点(1、2和3),我像这样连接这些节点:

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

假如节点3出现故障,IP无法解析,那么这行代码将会按照文档中所述抛出一个IllegalArgumentException异常:

@throws IllegalArgumentException 如果{@code addresses}中至少有一个IP地址无法找到

为什么会有人想要这种行为呢?我的意思是,如果其中一个节点出现故障,我希望应用程序仍能正常运行,因为Cassandra仍然可以正常工作。

我查看了Cassandra Java driver: how many contact points is reasonable?,但它并没有回答我的问题,因为它没有提到无法到达的主机。

我该如何处理这个问题?也许在另一个版本的Java驱动程序中已经改变了这一点?我目前正在使用cassandra-driver-core-3.0.3

3个回答

12

此验证仅确保所有提供的主机都可以解析,它甚至不会检查每个主机上是否运行Cassandra服务器。因此,它基本上是为了确保您在提供主机时没有拼写错误,因为它不认为提供无法解析的主机可能是一个正常的用例。

在您的情况下(主机已从DNS条目中删除),您可以简单地调用方法addContactPoint(String address),而不是使用addContactPoints(String... addresses)(其背后只是为每个提供的地址调用addContactPoint(String address)),并自己管理异常。

代码可能类似于这样:

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:我刚刚创建了一个工单,提议改进Java驱动程序https://datastax-oss.atlassian.net/browse/JAVA-1334


1
这是一个不错的解决方法!另外,感谢您创建工单! - juan

3

正如Nick所提到的那样,它是基于DNS解析而不是Cassandra服务器健康状况。

如果您从环境中删除主机的频率比重新编译应用程序的频率更高,那么您应该考虑不将联系点嵌入代码中,而是通过其他方式提供它们(环境变量、REST服务、始终解析为一个活动种子的单个DNS名称等)。


我们的环境确实比我们的代码更频繁地发生变化,我们有一个私有云,我们的虚拟机可以动态变化。你提到的我们可以尝试从我们这边实施一个解决方案,这一点是对的,但我也认为这个验证问题应该修复,因为即使在Pablo描述的状态下集群仍然可以工作,但应用程序无法启动。 - juan
如果您不想实现解决方法,我建议您向Java驱动程序提交问题 https://datastax-oss.atlassian.net/projects/JAVA/summary。我认为只需要一个可解析的主机名并且将任何不可解析的主机名警告丢弃的行为可能是合理的。无论如何,我认为您已经得到了答案。Stack Overflow悬赏并不是为了获得代码更改,但我强烈建议您提交补丁以及一个工单,以便更快地发布修复。 - nickmbailey

0

那里的文档只是关于“解析”传递进来的联系点。因此,将主机名转换为IP地址。如果您一开始就指定了IP地址,则不会解析它们,只需检查其有效性。如果您使用主机名,则每个联系点都需要可解析。这并不意味着cassandra机器需要运行,只是DNS查找主机名返回任何IP地址。因此,如果您删除了其中一个联系点的DNS条目并重新启动应用程序,则会出现故障。


不,我认为你是错误的。文本清楚地说“至少有一个”,这意味着如果没有找到一个IP地址,那么它会抛出异常。我检查了代码并且就是这样。同时测试将“asdasd”写作另一个IP时它崩溃了。 - Pablo Matias Gomez
你应该检查一下这句话是否写成了“如果没有找到IP地址”。 - Pablo Matias Gomez
是的,我明白了,这就是为什么我在询问无法解析主机(因为IP不再存在)的情况。如果我有3个主机(1、2、3)的配置,并且编号为3的主机已经关闭(IP不再存在),那么我将无法启动我的应用程序,而我不希望出现这种情况。现在我清楚了吗?也许我在问题中没有很好地解释清楚这一点。 - Pablo Matias Gomez
是的,我现在明白了。如果使用实际的 IP 地址,事情就会正常运作。IP 地址字符串并不是“解析”的,只是验证其有效性。您可以尝试输入一个虚假的 IP,例如“1.1.1.1”来测试它。您之前提到的“asdasd”无法工作的原因是它不是一个 IP 地址,而是主机名,并且它无法被解析。因此,如果您正在为 Cassandra 节点使用主机名,并删除其中一些主机名的 DNS 条目,则驱动程序将无法启动。我认为这不是一个常见的情况,但您肯定可以针对 Java 驱动程序提交一个工单。我已经修改了我的回答。 - nickmbailey
是的,这就是我想说的。我之前在使用Hector作为连接器连接Cassandra,这没有问题。在我们当前的基础设施中,通常会有一台机器被移除,因此它的DNS也会被移除。 - Pablo Matias Gomez
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接