大家好
我目前正在尝试使用 docker 创建一个 mongodb 复制集,并通过 mongoose 将其连接到expressjs 应用程序。
遗憾的是,当我尝试连接时遇到一些错误,我希望你能帮助我。
我将引导您完成到达这一点所采取的每一步。
以下是我使用的软件版本:
蒙戈 v6.0.2
猫鼬 v6.9.1
码头工人 20.10.12-0ubuntu4
为了创建副本集,我遵循了this教程。
我仍然会给出创建它所采取的每一步,然后我将展示猫鼬代码。
首先我创建了 docker 网络:
docker network create mongo-cluster
然后创建 mongo 实例
docker run \
-p 30001:27017 \
--name mongo1 \
--net mongo-cluster \
mongo mongod --replSet rs0
docker run \
-p 30002:27017 \
--name mongo2 \
--net mongo-cluster \
mongo mongod --replSet rs0
docker run \
-p 30003:27017 \
--name mongo3 \
--net mongo-cluster \
mongo mongod --replSet rs0
然后我创建了一个配置来启动:
config = {
"_id" : "rs0",
"members" : [
{"_id" : 0, "host" : "mongo1:27017"},
{"_id" : 1, "host" : "mongo2:27017"},
{"_id" : 2, "host" : "mongo3:27017"}
]
}
rs.initiate(config) // result : ok: 1
最后,我将 mongo1 节点设置为主节点:
db.getMongo().setReadPref()
我尝试使用以下代码连接到副本集:
await mongoose.connect(`mongodb://mongo1:30001,mongo2:30002,mongo3:30003/chatappdb`, {
replicaSet: 'rs0',
readPreference: 'primary',
w: 'majority'
}
这给了我以下错误:
Uncaught [MongoServerSelectionError: getaddrinfo EAI_AGAIN mongo1] {
reason: TopologyDescription {
type: 'ReplicaSetNoPrimary',
servers: Map(3) {
'mongo1:27017' => [ServerDescription],
'mongo2:27017' => [ServerDescription],
'mongo3:27017' => [ServerDescription]
},
stale: false,
compatible: true,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
setName: 'rs0',
maxElectionId: new ObjectId("7fffffff0000000000000001"),
maxSetVersion: 1,
commonWireVersion: 0,
logicalSessionTimeoutMinutes: null
},
code: undefined,
[Symbol(errorLabels)]: Set(0) {}
}
首先,我使用
rs.status
检查主节点是否确实在集群中定义
结果如下:
{
set: 'rs0',
date: ISODate("2023-02-23T23:27:05.901Z"),
myState: 1,
term: Long("1"),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long("2000"),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 3,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
lastCommittedWallTime: ISODate("2023-02-23T23:26:57.517Z"),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
appliedOpTime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
durableOpTime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
lastAppliedWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastDurableWallTime: ISODate("2023-02-23T23:26:57.517Z")
},
lastStableRecoveryTimestamp: Timestamp({ t: 1677194797, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate("2023-02-23T21:40:47.293Z"),
electionTerm: Long("1"),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1677188435, i: 1 }), t: Long("-1") },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1677188435, i: 1 }), t: Long("-1") },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long("10000"),
numCatchUpOps: Long("0"),
newTermStartDate: ISODate("2023-02-23T21:40:47.337Z"),
wMajorityWriteAvailabilityDate: ISODate("2023-02-23T21:40:48.598Z")
},
members: [
{
_id: 0,
name: 'mongo1:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 6518,
optime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
optimeDate: ISODate("2023-02-23T23:26:57.000Z"),
lastAppliedWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastDurableWallTime: ISODate("2023-02-23T23:26:57.517Z"),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1677188447, i: 1 }),
electionDate: ISODate("2023-02-23T21:40:47.000Z"),
configVersion: 1,
configTerm: 1,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: 'mongo2:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 6389,
optime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
optimeDurable: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
optimeDate: ISODate("2023-02-23T23:26:57.000Z"),
optimeDurableDate: ISODate("2023-02-23T23:26:57.000Z"),
lastAppliedWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastDurableWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastHeartbeat: ISODate("2023-02-23T23:27:05.316Z"),
lastHeartbeatRecv: ISODate("2023-02-23T23:27:04.810Z"),
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: 6389,
optime: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
optimeDurable: { ts: Timestamp({ t: 1677194817, i: 1 }), t: Long("1") },
optimeDate: ISODate("2023-02-23T23:26:57.000Z"),
optimeDurableDate: ISODate("2023-02-23T23:26:57.000Z"),
lastAppliedWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastDurableWallTime: ISODate("2023-02-23T23:26:57.517Z"),
lastHeartbeat: ISODate("2023-02-23T23:27:05.309Z"),
lastHeartbeatRecv: ISODate("2023-02-23T23:27:04.811Z"),
pingMs: Long("0"),
lastHeartbeatMessage: '',
syncSourceHost: 'mongo1:27017',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 1
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1677194817, i: 1 }),
signature: {
hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: Long("0")
}
},
operationTime: Timestamp({ t: 1677194817, i: 1 })
}
由此看来主节点已经定义好了。
我也尝试过使用 MongoClient :
let newClient = new MongoClient("mongodb://mongo1:30001,mongo2:30002,mongo3:30003/chatappdb?replicaSet=rs0", { useNewUrlParser: true, useUnifiedTopology: true })
我得到了相同的结果。
我仔细查看了运行 docker 实例时给出的 mongodb 日志:
{"t":{"$date":"2023-02-23T23:40:30.888+00:00"},"s":"I", "c":"NETWORK", "id":22943, "ctx":"listener","msg":"Connection accepted","attr":{"remote":"#","uuid":"#","connectionId":92,"connectionCount":29}}
{"t":{"$date":"2023-02-23T23:40:30.890+00:00"},"s":"I", "c":"NETWORK", "id":51800, "ctx":"conn92","msg":"client metadata","attr":{"remote":"#","client":"conn92","doc":{"driver":{"name":"nodejs|Mongoose","version":"4.13.0"},"os":{"type":"Linux","name":"linux","architecture":"x64","version":"6.1.11-76060111-generic"},"platform":"Node.js v18.12.0, LE (unified)","version":"4.13.0|6.9.1"}}}
{"t":{"$date":"2023-02-23T23:40:30.893+00:00"},"s":"I", "c":"NETWORK", "id":22944, "ctx":"conn92","msg":"Connection ended","attr":{"remote":"#","uuid":"#","connectionId":92,"connectionCount":28}}
我不太明白为什么连接如此突然地结束,但你可能比我更理解这一点。
提前感谢您的回答。
祝你有美好的一天!
我第一次尝试在 mongodb 中使用副本时遇到了同样的错误
最后我想出了以下说明,现在我没有问题了
docker run --name mongodb -d -p 27027:27027 -e MONGO_REPLICA_SET_NAME=myrs -v mongo_data:/data/db -v $(PWD)/mongod.conf:/etc/mongod.conf mongodb/mongodb-community-server:4.4.2-ubuntu2004-20230912T072223Z mongod --port 27027 --bind_ip_all --replSet myrs --config /etc/mongod.conf
由于它出现在命令中,我有一个文件名
mongod.conf
,该文件仅包含以下内容:
replication:
replSetName: "myrs"
然后执行以下操作:
docker exec -it mongodb bash
mongo --port 27027
rs.initiate();
use admin;
db.createUser({user: "your_user",pwd: "your_password", roles: [{role: "userAdminAnyDatabase", db: "admin" },{ role: "readWriteAnyDatabase", db: "admin" }]});
cfg = rs.conf();
cfg.members[0].host = "127.0.0.1:27027";
rs.reconfig(cfg);
现在我可以使用以下 uri 连接到它:
mongodb://your_user:[email protected]:27027/your_db?retryWrites=true&connectTimeoutMS=2000&authSource=admin&authMechanism=SCRAM-SHA-1