You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Cassandra多测试执行时出现NoNodeAvailableException求助

解决Cassandra NoNodeAvailableException问题(JUnit5+Docker Bitnami场景)

针对你在Spring Boot 2.7、JDK19环境下,JUnit5测试使用Docker部署的Bitnami Cassandra 3时,创建Keyspace阶段抛出NoNodeAvailableException的问题,可从以下几个方向排查解决:

1. 确保Cassandra容器完全就绪后再执行测试

Bitnami Cassandra镜像启动时会执行初始化脚本(创建超级用户、配置认证等),测试若在容器未完全就绪时发起请求,就会出现无可用节点的错误。

  • 手动验证:执行以下命令直到成功,再启动测试:
    docker exec <你的容器名> cqlsh -u cassandra -p cassandra -e "SELECT now() FROM system.local;"
    
  • 自动化等待:如果使用Testcontainers管理容器,添加健康检查等待逻辑:
    @Container
    static CassandraContainer<?> cassandra = new CassandraContainer<>("bitnami/cassandra:3")
            .withExposedPorts(9042)
            .waitingFor(Wait.forHealthcheck());
    

2. 修正负载均衡策略与数据中心配置冲突

你当前使用DcInferringLoadBalancingPolicy,同时手动指定了withLocalDatacenter("datacenter1"),可能导致驱动对数据中心的判断出现冲突:

  • 替换为明确的默认负载均衡策略并指定本地数据中心:
    var loader = DriverConfigLoader.programmaticBuilder()
            .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofMinutes(1))
            .withString(DefaultDriverOption.LOAD_BALANCING_POLICY_CLASS, DefaultLoadBalancingPolicy.class.getName())
            .withString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, "datacenter1")
            .build();
    
  • 验证容器实际数据中心名称:
    docker exec <你的容器名> cqlsh -e "SELECT data_center FROM system.local;"
    
    确保返回值与代码中配置的datacenter1一致。

3. 修复Session管理的资源泄漏或并发问题

170+测试类重复创建Session,可能导致连接数耗尽或Session状态异常:

  • 改用Spring托管Session:通过@Autowired CqlSession让Spring统一管理Session生命周期,避免手动创建的隐患。
  • 手动管理时添加清理逻辑:在每个测试类中添加@AfterAll注解关闭Session:
    @AfterAll
    static void cleanupCassandraSession() {
        if (session != null && !session.isClosed()) {
            session.close();
        }
    }
    
  • 调整驱动连接池配置:增加本地连接数上限,避免连接耗尽:
    var loader = DriverConfigLoader.programmaticBuilder()
            // 其他配置...
            .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_MAX_CONNECTIONS, 15)
            .build();
    

4. 修正认证配置逻辑

Bitnami Cassandra默认开启认证,即使本地连接也需要提供用户名密码,你当前的host判断逻辑可能导致localhost连接时未传入认证信息,被容器拒绝:

  • 去掉host判断,统一使用认证信息:
    var host = System.getenv("CASSANDRA_HOST") == null ? "localhost" : System.getenv("CASSANDRA_HOST");
    var username = System.getenv("CASSANDRA_USER") != null ? System.getenv("CASSANDRA_USER") : "cassandra";
    var password = System.getenv("CASSANDRA_PASSWORD") != null ? System.getenv("CASSANDRA_PASSWORD") : "cassandra";
    
  • 验证容器认证配置:检查容器的CASSANDRA_AUTH环境变量,若值为on则必须提供认证信息。

5. 强化驱动的连接与重试配置

增加连接超时和重试策略,提升网络波动下的连接稳定性:

var loader = DriverConfigLoader.programmaticBuilder()
        .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofMinutes(1))
        .withDuration(DefaultDriverOption.CONNECTION_CONNECT_TIMEOUT, Duration.ofSeconds(10))
        .withDuration(DefaultDriverOption.CONNECTION_INIT_QUERY_TIMEOUT, Duration.ofSeconds(10))
        .withString(DefaultDriverOption.RETRY_POLICY_CLASS, DefaultRetryPolicy.class.getName())
        // 其他负载均衡、数据中心配置...
        .build();

6. 验证网络连通性

  • 确认容器9042端口正确映射:执行docker ps查看端口映射,确保是0.0.0.0:9042->9042/tcp或指定了正确的主机端口。
  • 测试主机到容器的连通性:
    nc -zv <CASSANDRA_HOST> 9042
    
    若不通,检查防火墙、Docker网络配置是否正常。

内容的提问来源于stack exchange,提问作者Mohamed Sweelam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:50:33