[英]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.