簡體   English   中英

無法連接到 MongoDB 副本集集群

[英]Cannot connect to MongoDB replicaSet cluster

我通過使用 replicaSet rs0的 Docker 設置了一個 MongoDB 集群。

檢查集群的狀態一切似乎都很好:

{
  set: 'rs0',
  date: ISODate("2022-12-20T21:00:46.972Z"),
  myState: 1,
  term: Long("1"),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long("2000"),
  majorityVoteCount: 2,
  writeMajorityCount: 2,
  votingMembersCount: 3,
  writableVotingMembersCount: 3,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
    lastCommittedWallTime: ISODate("2022-12-20T21:00:40.112Z"),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
    appliedOpTime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
    durableOpTime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
    lastAppliedWallTime: ISODate("2022-12-20T21:00:40.112Z"),
    lastDurableWallTime: ISODate("2022-12-20T21:00:40.112Z")
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1671570000, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate("2022-12-20T20:45:09.901Z"),
    electionTerm: Long("1"),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1671569099, i: 1 }), t: Long("-1") },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1671569099, i: 1 }), t: Long("-1") },
    numVotesNeeded: 2,
    priorityAtElection: 1,
    electionTimeoutMillis: Long("10000"),
    numCatchUpOps: Long("0"),
    newTermStartDate: ISODate("2022-12-20T20:45:09.999Z"),
    wMajorityWriteAvailabilityDate: ISODate("2022-12-20T20:45:10.856Z")
  },
  members: [
    {
      _id: 0,
      name: 'mongo1:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 973,
      optime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
      optimeDate: ISODate("2022-12-20T21:00:40.000Z"),
      lastAppliedWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      lastDurableWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1671569109, i: 1 }),
      electionDate: ISODate("2022-12-20T20:45:09.000Z"),
      configVersion: 1,
      configTerm: 1,
      self: true,
      lastHeartbeatMessage: ''
    },
    {
      _id: 1,
      name: 'mongo2:27017',
      health: 1,
      state: 2,
      stateStr: 'SECONDARY',
      uptime: 947,
      optime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
      optimeDurable: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
      optimeDate: ISODate("2022-12-20T21:00:40.000Z"),
      optimeDurableDate: ISODate("2022-12-20T21:00:40.000Z"),
      lastAppliedWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      lastDurableWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      lastHeartbeat: ISODate("2022-12-20T21:00:45.203Z"),
      lastHeartbeatRecv: ISODate("2022-12-20T21:00:46.101Z"),
      pingMs: Long("0"),
      lastHeartbeatMessage: '',
      syncSourceHost: 'mongo1:27017',
      syncSourceId: 0,
      infoMessage: '',
      configVersion: 1,
      configTerm: 1
    },
    {
      _id: 2,
      name: 'mongo3:27017',
      health: 1,
      state: 2,
      stateStr: 'SECONDARY',
      uptime: 947,
      optime: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
      optimeDurable: { ts: Timestamp({ t: 1671570040, i: 1 }), t: Long("1") },
      optimeDate: ISODate("2022-12-20T21:00:40.000Z"),
      optimeDurableDate: ISODate("2022-12-20T21:00:40.000Z"),
      lastAppliedWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      lastDurableWallTime: ISODate("2022-12-20T21:00:40.112Z"),
      lastHeartbeat: ISODate("2022-12-20T21:00:45.203Z"),
      lastHeartbeatRecv: ISODate("2022-12-20T21:00:46.100Z"),
      pingMs: Long("0"),
      lastHeartbeatMessage: '',
      syncSourceHost: 'mongo1:27017',
      syncSourceId: 0,
      infoMessage: '',
      configVersion: 1,
      configTerm: 1
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1671570040, i: 1 }),
    signature: {
      hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
      keyId: Long("0")
    }
  },
  operationTime: Timestamp({ t: 1671570040, i: 1 })
}

我正在使用pymongo連接到集群。 如果我只使用主節點的節點名稱並直接連接到該節點,則一切正常:

client = MongoClient("mongodb://localhost:27017")
collection = client["db"]["test"]
collection.insert_one({"abc": "def"})
print(list(collection.find()))

但是,據我所知,這不是您連接到 MongoDB 集群的方式。 與其直接選擇主節點,不如提供集群中的所有節點以及副本集:

client = MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019?replicaSet=rs0")
collection = client["db"]["test"]
collection.insert_one({"abc": "def"})  # Hangs and eventually times out

引發的錯誤:

pymongo.errors.ServerSelectionTimeoutError: 
mongo1:27017: [Errno 8] nodename nor servname provided, or not known,
mongo3:27017: [Errno 8] nodename nor servname provided, or not known,
mongo2:27017: [Errno 8] nodename nor servname provided, or not known, 
Timeout: 30s, 
Topology Description: 
    <TopologyDescription 
        id: 63a2230d721313f82429a19e, 
        topology_type: ReplicaSetNoPrimary, 
        servers: [
            <ServerDescription ('mongo1', 27017) 
                server_type: Unknown, 
                rtt: None, 
                error=AutoReconnect('mongo1:27017: [Errno 8] nodename nor servname provided, or not known')>, 
            <ServerDescription ('mongo2', 27017) 
                server_type: Unknown, 
                rtt: None, 
                error=AutoReconnect('mongo2:27017: [Errno 8] nodename nor servname provided, or not known')>, 
            <ServerDescription ('mongo3', 27017) 
                server_type: Unknown, 
                rtt: None, 
                error=AutoReconnect('mongo3:27017: [Errno 8] nodename nor servname provided, or not known')>]>

我相信這可能是因為 mongo1/2/3 不是實際的主機名,而是 docker 容器,它們只是 Docker 網絡中的有效主機名,這意味着,要訪問這些主機名,我必須在同一網絡中運行我的 Python 腳本。

我還測試了如果我使用localhost:27018是否可以訪問輔助節點,事實上,它們是。 pymongo告訴我不能直接插入輔助節點,這是有道理的。

docker-compose.yaml

version: '3'

services:
  mongo1:
    image: mongo:latest
    container_name: mongo1
    command: mongod --replSet rs0 --bind_ip localhost,mongo1
    ports:
      - "27017:27017"
    networks:
      - mongoCluster
    volumes:
      - /mnt/workspace/mongodb-cluster/node1:/data/db
  mongo2:
    image: mongo:latest
    container_name: mongo2
    command: mongod --replSet rs0 --bind_ip localhost,mongo2
    ports:
      - "27018:27017"
    networks:
      - mongoCluster
    volumes:
      - /mnt/workspace/mongodb-cluster/node2:/data/db
  mongo3:
    image: mongo:latest
    container_name: mongo3
    command: mongod --replSet rs0 --bind_ip localhost,mongo3
    ports:
      - "27019:27017"
    networks:
      - mongoCluster
    volumes:
      - /mnt/workspace/mongodb-cluster/node3:/data/db

networks:
  mongoCluster:
    driver: bridge

我還嘗試不使用專用網絡,而是讓 docker 容器訪問主機網絡,從而能夠使用localhost:<PORT>定義 replicaSet。 雖然我能夠啟動集群,但在嘗試從 Python 中使用它時,我仍然遇到同樣的錯誤。

綜上所述,我現在的問題是我需要如何更改我的 Docker 或pymongo配置,以便我可以在連接字符串中指定所有節點。

您一般不能混合使用主機名和localhost別名。 如果一個 ReplicaSet 成員是localhost那么所有成員都需要是localhost ,它們只能在端口上有所不同。

根據rs.status()成員是mongo1:27017,mongo2:27017,mongo3:27017 ,因此連接字符串必須是相應的

MongoClient("mongodb://mongo1:27017,mongo2:27017,mongo3:27017?replicaSet=rs0")

或者在啟動 ReplicaSet 時使用localhost

rs.initiate(
  {
    _id: "rs0",
    members: [
      { _id: 0, host: "localhost:27017" },
      { _id: 1, host: "localhost:27018" },
      { _id: 2, host: "localhost:27019" }
    ]
  }
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM