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

如何通过DataStax Python驱动连接Docker-Compose创建的Cassandra集群

解决Docker部署Cassandra集群后Python驱动无法连接所有节点的问题

问题场景

我通过以下docker-compose.yaml部署了双节点Cassandra集群:

version: "3.3"
networks:
  cassandra:

volumes:
  cassandra_seed_data:
  cassandra_node_data:

services:
  cassandra-seed:
    image: cassandra:3.11
    restart: "no"
    logging:
      options:
        max-size: "5m"
        max-file: "3"
    container_name: cassandra-seed
    networks:
      - cassandra
    expose:
      - "7000"
    ports:
      - target: 9042
        published: 9042
        protocol: tcp
        mode: host
    volumes:
      - cassandra_seed_data:/var/lib/cassandra 
    environment:
      CASSANDRA_BROADCAST_ADDRESS: "cassandra-seed"
      CASSANDRA_NUM_TOKENS: 4
      CASSANDRA_START_RPC: true

  cassandra-node:
    image: cassandra:3.11
    restart: "no"
    logging:
      options:
        max-size: "5m"
        max-file: "1"
    container_name: cassandra-node
    hostname: cassandra-node
    networks:
      - cassandra
    expose:
      - "7000"
    ports:
      - target: 9042
        published: 9043
        protocol: tcp
        mode: host
    volumes:
      - cassandra_node_data:/var/lib/cassandra
    environment:
      CASSANDRA_SEEDS: "cassandra-seed"
      CASSANDRA_LISTEN_ADDRESS: cassandra-node
      CASSANDRA_BROADCAST_ADDRESS: cassandra-node
      CASSANDRA_START_RPC: true
      # CASSANDRA_ENDPOINT_SNITCH: SimpleSnitch
      CASSANDRA_NUM_TOKENS: 4
      # CASSANDRA_CLUSTER_NAME: cluster
      # CASSANDRA_DC: dc
      # HEAP_NEWSIZE: 32M
      # MAX_HEAP_SIZE: 4M

集群运行状态正常,通过以下命令验证:

docker exec cassandra-seed nodetool status

输出:

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns (effective)  Host ID                               Rack
UN  192.168.96.2  71.27 KiB  4            100.0%            ce5de211-63be-44c7-8f3c-bf0a18270a40  rack1
UN  192.168.96.3  71.41 KiB  4            100.0%            a6eae6e9-be77-4c34-ad0b-12333d2630a7  rack1

docker-compose ps输出:

docker-compose ps                        
NAME                COMMAND                  SERVICE             STATUS              PORTS
cassandra-node      "docker-entrypoint.s…"   cassandra-node      running             7000-7001/tcp, 7199/tcp, 9160/tcp, 0.0.0.0:9043->9042/tcp
cassandra-seed      "docker-entrypoint.s…"   cassandra-seed      running             7000-7001/tcp, 7199/tcp, 9160/tcp, 0.0.0.0:9042->9042/tcp

使用DataStax Python驱动连接时,仅配置了初始联系点0.0.0.0:9042,代码如下:

from cassandra.cluster import Cluster

cluster = Cluster(**{'contact_points': ['0.0.0.0'], 'port': 9042, 'compression': 'lz4', 'protocol_version': 4})
cluster.connect(wait_for_all_pools=True)

但出现超时报错:

INFO:cassandra.policies:Using datacenter 'datacenter1' for DCAwareRoundRobinPolicy (via host '0.0.0.0:9042'); if incorrect, please specify a local_dc to the constructor, or limit contact points to local cluster nodes

INFO:cassandra.cluster:New Cassandra host <Host: 192.168.96.3:9042 datacenter1> discovered

WARNING:cassandra.cluster:Failed to create connection pool for new host 192.168.96.3:9042:
Traceback (most recent call last):
  File "cassandra/cluster.py", line 3175, in cassandra.cluster.Session.add_or_renew_pool.run_add_or_renew_pool
  File "cassandra/pool.py", line 402, in cassandra.pool.HostConnection.__init__
  File "cassandra/cluster.py", line 1620, in cassandra.cluster.Cluster.connection_factory
  File "cassandra/connection.py", line 831, in cassandra.connection.Connection.factory
  File "/Users/ekotsal/miniconda3/envs/cbd3/lib/python3.9/site-packages/cassandra/io/libevreactor.py", line 267, in __init__
    self._connect_socket()
  File "cassandra/connection.py", line 898, in cassandra.connection.Connection._connect_socket
OSError: [Errno None] Tried connecting to [('192.168.96.3', 9042)]. Last error: timed out

WARNING:cassandra.cluster:Host 192.168.96.3:9042 has been marked down

docker-compose日志无异常,需解决该问题。


问题根源

Python驱动通过初始联系点(seed节点)发现了第二个节点的内部Docker地址192.168.96.3:9042,但这个地址是容器专属的网络地址,外部主机无法直接访问。而第二个节点对外暴露的端口是9043,但Cassandra节点广播的是内部端口9042,导致驱动尝试访问不可达的地址和端口,最终超时。

核心问题在于cassandra-node的CASSANDRA_BROADCAST_ADDRESS配置为容器内部主机名,广播的地址和端口对外部主机无效。


解决方案

1. 修改docker-compose配置

更新两个Cassandra服务的环境变量,让它们广播外部主机可访问的地址和端口:

  • 将CASSANDRA_BROADCAST_ADDRESS设置为主机的实际IP地址(例如192.168.1.100,不要用0.0.0.0,避免潜在问题)
  • 给cassandra-node添加CASSANDRA_BROADCAST_RPC_PORT,值为对外暴露的9043

修改后的关键配置片段:

services:
  cassandra-seed:
    # ... 其他配置保持不变
    environment:
      CASSANDRA_BROADCAST_ADDRESS: "你的主机IP"
      CASSANDRA_BROADCAST_RPC_ADDRESS: "你的主机IP"
      CASSANDRA_NUM_TOKENS: 4
      CASSANDRA_START_RPC: true

  cassandra-node:
    # ... 其他配置保持不变
    environment:
      CASSANDRA_SEEDS: "cassandra-seed"
      CASSANDRA_LISTEN_ADDRESS: cassandra-node
      CASSANDRA_BROADCAST_ADDRESS: "你的主机IP"
      CASSANDRA_BROADCAST_RPC_PORT: 9043
      CASSANDRA_START_RPC: true
      CASSANDRA_NUM_TOKENS: 4

2. 重启集群

执行命令清理旧容器和数据卷,重新启动集群:

docker-compose down -v
docker-compose up -d

3. 调整Python连接代码

只需将主机IP作为联系点,驱动会自动获取正确的节点广播地址和端口:

from cassandra.cluster import Cluster

# 使用主机IP作为初始联系点
cluster = Cluster(contact_points=['你的主机IP'], port=9042, compression='lz4', protocol_version=4)
session = cluster.connect(wait_for_all_pools=True)

# 验证连接状态
print("集群连接成功,节点信息:")
for host in cluster.metadata.all_hosts():
    print(f"- {host.address}:{host.native_transport_port} (状态: {host.status})")

验证步骤

  1. 重启后执行docker exec cassandra-seed nodetool status,确认两个节点状态均为UN(正常运行)
  2. 运行修改后的Python代码,控制台应输出两个节点的信息,无超时报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:50:37