Cassandra 3节点群群在一个节点下降后立即投掷Nohostavailable Exception



我们有一个带有RF 3的节点群集。

一旦我们从集群中排出一个节点,我们就会看到许多:

All host(s) tried for query failed (no host was tried)
com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (no host was tried)
        at com.datastax.driver.core.exceptions.NoHostAvailableException.copy(NoHostAvailableException.java:84)
        at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
        at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:214)
        at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:52)

我们所有的写作和阅读都是一个一致性级别的fulum或一个节点,因此所有内容都应该完美地工作。但是,只要节点下降,就会抛出例外。

我们使用Cassandra 2.2.4 Java Cassandra驱动程序2.1.10.2

这是我们创建群集的方式:

new Cluster.Builder()
    .addContactPoints(CONTACT_POINTS)
    .withCredentials(USERNAME, PASSWORD)
    .withRetryPolicy(new LoggingRetryPolicy(DefaultRetryPolicy.INSTANCE))
    .withReconnectionPolicy(new ExponentialReconnectionPolicy(10, 10000))
    .withLoadBalancingPolicy(new TokenAwarePolicy(new RoundRobinPolicy()))
    .withSocketOptions(new SocketOptions().setReadTimeoutMillis(12_000))
    .build();

contact_points是节点的3个公共IP的字符串阵列。

几个月前,该集群仅暂时使用2个节点,但出于未知的原因不再是这种情况,我已经用完了想法:(

非常感谢您的帮助!

解决问题。

更多的分析表明,问题来自IP问题。我们的Cassandra服务器使用私人本地IP(10.0。)一起进行交流,而我们的应用服务器将其公共IP在其配置中。

当它们在同一网络中时,它正常工作,但是当他们移动到另一个网络时,他们只能连接到群集的一台机器,而另外两个则被认为是试图连接到的机器私人本地IP而不是其他两个公共IP。

解决方案是在集群构建器中添加iptranslater:

.withAddressTranslater(new ToPublicIpAddressTranslater())

使用以下代码:

private static class ToPublicIpAddressTranslater implements AddressTranslater {
    private Map<String, String> internalToPublicIpMap = new HashMap<>();
    public ToPublicIpAddressTranslater() {
        for (int i = 0; i < CONTACT_POINT_PRIVATE_IPS.length; i++) {
            internalToPublicIpMap.put(CONTACT_POINT_PRIVATE_IPS[i], CONTACT_POINTS[i]);
        }
    }
    @Override
    public InetSocketAddress translate(InetSocketAddress address) {
        String publicIp = internalToPublicIpMap.get(address.getHostString());
        if (publicIp != null) {
            return new InetSocketAddress(publicIp, address.getPort());
        }
        return address;
    }
}

最新更新