Docker中4节点Cassandra集群与Spring Boot连接报错求助
问题描述
我正在用docker-compose搭建4节点Cassandra集群,docker-compose配置如下:
version: "3.8" services: cass1: image: cassandra:4 container_name: cass1 hostname: cass1 networks: cass_netwrok: ipv4_address: 172.30.0.2 expose: - 9042 ports: - "9042:9042" environment: - CASSANDRA_CLUSTER_NAME=default - CASSANDRA_SEEDS=cass1 cass2: image: cassandra:4 container_name: cass2 hostname: cass2 networks: cass_netwrok: ipv4_address: 172.30.0.3 expose: - 9042 ports: - "9043:9042" environment: - CASSANDRA_CLUSTER_NAME=default - CASSANDRA_SEEDS=cass1 depends_on: - cass1 cass3: image: cassandra:4 container_name: cass3 hostname: cass3 networks: cass_netwrok: ipv4_address: 172.30.0.4 expose: - 9042 ports: - "9044:9042" environment: - CASSANDRA_CLUSTER_NAME=default - CASSANDRA_SEEDS=cass1 depends_on: - cass1 cass4: expose: - 9042 image: cassandra:4 container_name: cass4 hostname: cass4 networks: cass_netwrok: ipv4_address: 172.30.0.5 ports: - "9045:9042" environment: - CASSANDRA_CLUSTER_NAME=default - CASSANDRA_SEEDS=cass1 depends_on: - cass1 networks: cass_netwrok: ipam: driver: default config: - subnet: 172.30.0.0/16
集群初步可用:能通过localhost:9042连接第一个节点,创建keyspace和表,且在localhost:9043能看到相同的表。但Spring Boot应用连接时出现报错,关键错误包括:
Found invalid row in system.peers_v2 for peer: /172.30.0.3. This is likely a gossip or snitch issueError while opening new channel (ConnectionInitException: ... failed to send request (java.nio.channels.NotYetConnectedException))
Spring配置:
spring: data: cassandra: keyspace-name: events contact-points: - "localhost:9042" - "localhost:9043" - "localhost:9044" - "localhost:9045"
Cassandra配置类:
@Configuration @EnableCassandraRepositories(basePackages = "com.eternal.nosqltask3.repository") public class CassandraConfig extends AbstractCassandraConfiguration { @Value("${spring.data.cassandra.keyspace-name}") private String keyspace; @Override protected String getKeyspaceName() { return keyspace; } }
请问搭建集群和Spring连接时遗漏了什么配置,如何解决这些错误?
解决方案
错误原因分析
- Cassandra地址广播问题:Cassandra节点默认会向客户端广播自己的容器内部IP(如
172.30.0.3)和默认CQL端口9042,但宿主机并未映射这些容器内部端口,导致Spring Boot驱动尝试连接172.30.0.3:9042时无法建立连接,抛出NotYetConnectedException。 - 集群节点就绪检测缺失:
depends_on仅保证容器启动顺序,不确保Cassandra服务完全就绪,可能导致后续节点未正确加入集群,引发gossip/snitch警告。
具体修复步骤
1. 修改docker-compose配置,配置Cassandra广播地址与端口
给每个Cassandra服务添加以下环境变量,让节点向外部客户端广播宿主机可访问的地址和映射端口:
# cass1的environment新增 - CASSANDRA_LISTEN_ADDRESS=cass1 - CASSANDRA_RPC_ADDRESS=0.0.0.0 - CASSANDRA_BROADCAST_ADDRESS=localhost - CASSANDRA_BROADCAST_RPC_PORT=9042 # cass2的environment新增 - CASSANDRA_LISTEN_ADDRESS=cass2 - CASSANDRA_RPC_ADDRESS=0.0.0.0 - CASSANDRA_BROADCAST_ADDRESS=localhost - CASSANDRA_BROADCAST_RPC_PORT=9043 # cass3的environment新增 - CASSANDRA_LISTEN_ADDRESS=cass3 - CASSANDRA_RPC_ADDRESS=0.0.0.0 - CASSANDRA_BROADCAST_ADDRESS=localhost - CASSANDRA_BROADCAST_RPC_PORT=9044 # cass4的environment新增 - CASSANDRA_LISTEN_ADDRESS=cass4 - CASSANDRA_RPC_ADDRESS=0.0.0.0 - CASSANDRA_BROADCAST_ADDRESS=localhost - CASSANDRA_BROADCAST_RPC_PORT=9045
参数说明:
CASSANDRA_LISTEN_ADDRESS:集群内部节点通信使用的地址(容器hostname)CASSANDRA_RPC_ADDRESS:允许Cassandra接收外部连接的地址(设为0.0.0.0允许容器外访问)CASSANDRA_BROADCAST_ADDRESS:向外部客户端广播的地址(宿主机localhost)CASSANDRA_BROADCAST_RPC_PORT:向外部客户端广播的CQL端口(对应宿主机映射的端口)
2. 添加健康检测,确保节点就绪后再启动后续容器
在每个Cassandra服务中添加健康检测配置,并修改depends_on依赖条件:
# 在cass1服务中添加 healthcheck: test: ["CMD-SHELL", "cqlsh cass1 -e 'describe keyspaces' || exit 1"] interval: 30s timeout: 10s retries: 5 # 在cass2、cass3、cass4的depends_on中修改为 depends_on: cass1: condition: service_healthy
这样能保证后续节点在cass1完全就绪后再启动,避免集群节点加入失败。
3. 优化Spring Boot配置(可选)
驱动会自动从初始连接节点获取集群拓扑信息,因此只需配置一个初始接触点即可:
spring: data: cassandra: keyspace-name: events contact-points: "localhost:9042"
验证修复
- 停止并删除原有容器:
docker-compose down -v - 重新启动集群:
docker-compose up -d - 查看集群状态:
docker exec -it cass1 nodetool status,确认所有节点状态为UN(正常) - 启动Spring Boot应用,检查日志是否无连接错误
内容的提问来源于stack exchange,提问作者eternal
相关产品推荐
相关产品推荐

