在Sping Boot + Cassandra中运行多个测试时出现NoNodeAvailableException异常

vql8enpb  于 2023-01-20  发布在  Cassandra
关注(0)|答案(1)|浏览(281)

我刚刚使用jdk 19升级到Sping Boot 2.7,并决定使用在docker中运行的Cassandra bitnami 3进行测试“Junit-5”,我得到的错误是No node was available to execute the query,而且每次都发生在相同的测试用例中。

No node was available to execute the query; nested exception is \
  com.datastax.oss.driver.api.core.NoNodeAvailableException: \
    No node was available to execute the query

这是我用来连接的代码

var loader = DriverConfigLoader.programmaticBuilder()
        .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofMinutes(1))
        .withString(DefaultDriverOption.LOAD_BALANCING_POLICY_CLASS,
                DcInferringLoadBalancingPolicy.class.getName())
        .build();

if (session == null || session.isClosed()) {
  var host = System.getenv("CASSANDRA_HOST") == null ? "localhost" : System.getenv("CASSANDRA_HOST");
  var username = "localhost".equals(host)? "": "cassandra";
  var password = "localhost".equals(host)? "": "cassandra";

  LOG.info("Cassandra host '{}'.", host);
  LOG.info("Cassandra username '{}'.", username);
  LOG.info("Cassandra password '{}'.", password);

  var sessionBuilder = new CqlSessionBuilder()
          .addContactPoint(new InetSocketAddress(host, 9042))
          .withLocalDatacenter("datacenter1")
          .withConfigLoader(loader);

  if (!username.isEmpty()) {
    sessionBuilder.withAuthCredentials(username, password);
  }

  session = sessionBuilder.build();

同样重要的是要提到,我有很多170多个测试用例分布在不同的文件中,并且在每次执行文件时,我都尝试使用此代码再次清理和填充DB

session.execute("create keyspace if not exists \"schema_x\" WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};");

  for (final String stmt : getCassaandraStatementsFromFile(CASSANDRA_SCHEMA_FILE)) {
    session.execute(stmt);
    LOG.info("Cassandra. Executed statement: '{}'.", stmt.replaceAll("\n", ""));
  }

并且错误恰好发生在创建keyspace行上,我尝试从我这边进行一些调整

  • 调整连接加载器并使用节流,但没有任何帮助
  • 我还检查了docker本身内部的本地数据中心值,并与我的值相匹配。

最后,完整的错误堆栈跟踪(如果需要)

org.springframework.data.cassandra.CassandraConnectionFailureException: \
  Query; CQL [com.datastax.oss.driver.internal.core.cql.DefaultSimpleStatement@65b70f9e]; \
  No node was available to execute the query; nested exception is \
  com.datastax.oss.driver.api.core.NoNodeAvailableException: \
  No node was available to execute the query
    at org.springframework.data.cassandra.core.cql.CassandraExceptionTranslator.translate(CassandraExceptionTranslator.java:137)
    at org.springframework.data.cassandra.core.cql.CassandraAccessor.translate(CassandraAccessor.java:422)
    at org.springframework.data.cassandra.core.cql.CqlTemplate.translateException(CqlTemplate.java:764)
    at org.springframework.data.cassandra.core.cql.CqlTemplate.query(CqlTemplate.java:300)
    at org.springframework.data.cassandra.core.cql.CqlTemplate.query(CqlTemplate.java:320)
    at org.springframework.data.cassandra.core.CassandraTemplate.select(CassandraTemplate.java:337)
    at org.springframework.data.cassandra.repository.query.CassandraQueryExecution$CollectionExecution.execute(CassandraQueryExecution.java:136)
    at 
    ...
Caused by: com.datastax.oss.driver.api.core.NoNodeAvailableException: \
No node was available to execute the query
    at com.datastax.oss.driver.api.core.NoNodeAvailableException.copy(NoNodeAvailableException.java:40)
    at com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures.getUninterruptibly(CompletableFutures.java:149)
    at com.datastax.oss.driver.internal.core.cql.CqlRequestSyncProcessor.process(CqlRequestSyncProcessor.java:53)
    at com.datastax.oss.driver.internal.core.cql.CqlRequestSyncProcessor.process(CqlRequestSyncProcessor.java:30)
    at com.datastax.oss.driver.internal.core.session.DefaultSession.execute(DefaultSession.java:230)
    at com.datastax.oss.driver.api.core.cql.SyncCqlSession.execute(SyncCqlSession.java:54)
    at org.springframework.data.cassandra.core.cql.CqlTemplate.query(CqlTemplate.java:298)
    ... 39 common frames omitted

我将感谢您对此的支持,并提前表示感谢

wbgh16ku

wbgh16ku1#

Spring使用Cassandra Java driver连接到Cassandra集群。
对于每个查询执行,Java驱动程序生成查询计划,其中包含要连接以执行查询的节点列表。配置的负载平衡策略(在您的情况下为DcInferringLoadBalancingPolicy)确定要包含在查询计划中的节点。查询计划将仅包含已知可用的节点,这意味着策略将不包含已知关闭或忽略的节点(有关详细信息,请参见Load balancing with the Java driver)。
在所有节点都被标记为“down”或“ignored”的情况下,驱动程序没有选择,因为没有节点可供连接到the driver throws NoNodeAvailableException。正如您在上面发布的错误消息所指出的,* 确实 * 没有节点available to execute the query--正如它所说的那样。
驱动程序将节点标记为“down”或“ignored”,因为它们在一段时间内没有响应,通常是因为它们过载。请考虑进一步限制负载,以便节点不会过载。
此外,架构更改不遵循与常规写入(INSERTUPDATEDELETE)相同的路径。每个DDL更改(CREATEALTERDROP)都通过gossip协议传播到其他节点,因此群集中的所有节点可能需要一些时间才能达成架构协议,具体取决于群集的大小。
以编程方式执行架构更改时,不要快速连续地执行更改,否则节点可能会失去同步。应用程序应在每次架构更改后暂停,并在执行下一个架构更改之前检查所有节点是否已达成架构协议,例如,调用isSchemaInAgreement()或与checkSchemaAgreementAsync()异步。有关详细信息,请参阅与Java驱动程序的架构协议。
顺便说一句,默认的cassandra超级用户不是为一般用途而设计的,它只应该用于配置另一个超级用户帐户,然后将其删除。
使用默认的cassandra超级用户帐户是昂贵的,因为它需要QUORUM个节点来进行身份验证。相比之下,除cassandra之外的所有其他帐户都以ONE的一致性进行身份验证。干杯!
👉 请将鼠标悬停在cassandra标签上,然后单击Watch tag按钮,以支持Apache Cassandra社区。🙏谢谢!

相关问题