我正在使用datastax cassandra驱动核心3.1.0,并开始学习cassandra我已经设置了一个3节点集群(我的笔记本电脑中运行了3个VM)。
群集连接以这种方式完成(传递联系点列表):
public static Cluster createCassandraRockSolidCluster(String... contactPoints) {
// Connect to the cluster
Cluster cluster = Cluster.builder().addContactPoints(contactPoints).withRetryPolicy(DefaultRetryPolicy.INSTANCE)
.withLoadBalancingPolicy(new TokenAwarePolicy(DCAwareRoundRobinPolicy.builder().build())).build();
return cluster;
}
我已经创建了一个测试,它定期对集群执行相同的查询,并设置了ConsistencyLevel.ONE。
我的期望是,如果一个或甚至两个节点发生故障,查询仍然可以获得结果(由于ConsistencyLevel.ONE和DefaultRetryPolicy)。
发生的事情是:
如果我关闭一个节点甚至其中两个节点,通过停止cassandra服务,客户端的查询就像我期望的那样工作:它检索结果没有任何问题。
但是,如果我真的"断开电缆"从一个服务器的网络适配器使其无法访问,然后引发一个超时异常,一个查询丢失(下一个查询能够检索数据)。
这不是我所期待的,我想知道这是我的错误还是java客户端库中的错误。
另一方面,如果我抓住了Exception,并且"重新执行"超时查询,它可以工作,但我希望这个重试将由DefaultRetryPolicy管理。
因此,为了给我的客户提供额外的健壮性,我创建了这个方法:
protected static ResultSet executeRockSolid(Session session, BoundStatement boundStatement) {
ResultSet results = null;
try {
results = session.execute(boundStatement);
} catch (OperationTimedOutException e) {
System.err.format("Retrying. Caused by: %s", e.toString());
results = session.execute(boundStatement);
} catch (TransportException e) {
System.err.format("Retrying. Caused by: %s", e.toString());
results = session.execute(boundStatement);
} catch (ReadTimeoutException e) {
System.err.format("Retrying. Caused by: %s", e.toString());
results = session.execute(boundStatement);
} catch (Exception e) {
System.err.println(e);
}
return results;
}
但是,我真的不喜欢将自己的代码用于我认为应由客户提供的内容。
所以,问题是:
我观察的行为是正常行为还是错误?
如果是正常的,那么最好的选择是让客户端支持"服务器与网络的连接断开"透明?
如果最佳选择是创建自定义重试策略,那么参数/实现是什么?