无法使用 Node.js 连接到 Mongo 3.6 副本集
Cannot connect to Mongo 3.6 replicaset using Node.js
我使用以下命令在 IP 192.168.1.175
的机器上设置了 mongo 3.6 副本集,
$ sudo mongod --port 27017 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs1 &
$ sudo mongod --port 27018 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs2 &
$ sudo mongod --port 27019 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs3
$ rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27017" },
{ _id: 2, host: "localhost:27017" }
]
})
所以我假设因为我正在使用 --bind_ip_all
,所以我也能够从远程机器连接这个副本。
现在我正在尝试从具有 IP 192.168.1.160
的机器访问 192.168.1.175
,下面是输出
emgda@ubuntu:~$ mongo 'mongodb://mongomachine:27017,mongomachine:27018,mongomachine:27019/?replicaSet=rs0' --quiet
rs0:PRIMARY> ^C
下面是连接到相同 mongo URL 的小 Node.js 代码,但我收到错误。
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect('mongodb://192.168.1.175:27018,192.168.1.175:27017,192.168.1.175:27019/emgda?replicaSet=rs0', { useUnifiedTopology: true })
.then(client => {
console.log("Connected correctly to server");
// specify db and collections
const db = client.db("emgda");
const collection = db.collection("aggregatehourly");
})
.catch(err => {
console.error(err);
});
下面是输出,
{ MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
at Timeout.waitQueueMember.timer.setTimeout [as _onTimeout] (/home/emgda/Documents/mongo-connection/node_modules/mongodb/lib/core/sdam/topology.js:448:30)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
name: 'MongoServerSelectionError',
reason:
TopologyDescription {
type: 'ReplicaSetNoPrimary',
setName: 'rs0',
maxSetVersion: 1,
maxElectionId: null,
servers:
Map {
'localhost:27017' => [ServerDescription],
'localhost:27018' => [ServerDescription],
'localhost:27019' => [ServerDescription] },
stale: false,
compatible: true,
compatibilityError: null,
logicalSessionTimeoutMinutes: null,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: 6 },
[Symbol(mongoErrorContextSymbol)]: {} }
当 运行 在本地机器上 mongo shell 上的命令时,我将其作为输出,
rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2020-01-24T06:15:26.540Z"),
"myState" : 1,
"term" : NumberLong(10),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"appliedOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"durableOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
}
},
"members" : [
{
"_id" : 0,
"name" : "localhost:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 294,
"optime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:26Z"),
"electionTime" : Timestamp(1579846244, 1),
"electionDate" : ISODate("2020-01-24T06:10:44Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "localhost:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 282,
"optime" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDurable" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:16Z"),
"optimeDurableDate" : ISODate("2020-01-24T06:15:16Z"),
"lastHeartbeat" : ISODate("2020-01-24T06:15:24.871Z"),
"lastHeartbeatRecv" : ISODate("2020-01-24T06:15:25.718Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "localhost:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 273,
"optime" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDurable" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:16Z"),
"optimeDurableDate" : ISODate("2020-01-24T06:15:16Z"),
"lastHeartbeat" : ISODate("2020-01-24T06:15:24.894Z"),
"lastHeartbeatRecv" : ISODate("2020-01-24T06:15:24.702Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27018",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1579846526, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1579846526, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
问题:
- 为什么我无法连接到具有完整 URL 的 mongo 副本集?
- 我如何能够仅提供 1 个 IP 进行连接?
任何指导将不胜感激。
终于,我得到了解决这个问题的方法,
当我们启动一个副本集时,我们需要确保我们不必在成员的配置中提及localhost
(见下面的配置)。如果这样做,即使您使用命令 --bind_ip 0.0.0.0,::
或 --bind_all_ip
.
启动 mongo 服务器,其他远程服务器也将无法访问数据库
以下是正确和错误的配置。
不正确
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27017" },
{ _id: 2, host: "localhost:27017" }
]
})
正确 [同一台机器上的所有副本]
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "192.168.1.175:27017" },
{ _id: 1, host: "192.168.1.175:27018" },
{ _id: 2, host: "192.168.1.175:27019" }
]
})
正确 [不同机器上的所有副本]
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "192.168.1.175:27017" },
{ _id: 1, host: "192.168.1.176:27018" },
{ _id: 2, host: "192.168.1.177:27019" }
]
})
我使用以下命令在 IP 192.168.1.175
的机器上设置了 mongo 3.6 副本集,
$ sudo mongod --port 27017 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs1 &
$ sudo mongod --port 27018 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs2 &
$ sudo mongod --port 27019 --replSet "rs0" --bind_ip_all --dbpath ~/data/db/rs3
$ rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27017" },
{ _id: 2, host: "localhost:27017" }
]
})
所以我假设因为我正在使用 --bind_ip_all
,所以我也能够从远程机器连接这个副本。
现在我正在尝试从具有 IP 192.168.1.160
的机器访问 192.168.1.175
,下面是输出
emgda@ubuntu:~$ mongo 'mongodb://mongomachine:27017,mongomachine:27018,mongomachine:27019/?replicaSet=rs0' --quiet
rs0:PRIMARY> ^C
下面是连接到相同 mongo URL 的小 Node.js 代码,但我收到错误。
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect('mongodb://192.168.1.175:27018,192.168.1.175:27017,192.168.1.175:27019/emgda?replicaSet=rs0', { useUnifiedTopology: true })
.then(client => {
console.log("Connected correctly to server");
// specify db and collections
const db = client.db("emgda");
const collection = db.collection("aggregatehourly");
})
.catch(err => {
console.error(err);
});
下面是输出,
{ MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
at Timeout.waitQueueMember.timer.setTimeout [as _onTimeout] (/home/emgda/Documents/mongo-connection/node_modules/mongodb/lib/core/sdam/topology.js:448:30)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
name: 'MongoServerSelectionError',
reason:
TopologyDescription {
type: 'ReplicaSetNoPrimary',
setName: 'rs0',
maxSetVersion: 1,
maxElectionId: null,
servers:
Map {
'localhost:27017' => [ServerDescription],
'localhost:27018' => [ServerDescription],
'localhost:27019' => [ServerDescription] },
stale: false,
compatible: true,
compatibilityError: null,
logicalSessionTimeoutMinutes: null,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: 6 },
[Symbol(mongoErrorContextSymbol)]: {} }
当 运行 在本地机器上 mongo shell 上的命令时,我将其作为输出,
rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2020-01-24T06:15:26.540Z"),
"myState" : 1,
"term" : NumberLong(10),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"appliedOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"durableOpTime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
}
},
"members" : [
{
"_id" : 0,
"name" : "localhost:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 294,
"optime" : {
"ts" : Timestamp(1579846526, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:26Z"),
"electionTime" : Timestamp(1579846244, 1),
"electionDate" : ISODate("2020-01-24T06:10:44Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "localhost:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 282,
"optime" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDurable" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:16Z"),
"optimeDurableDate" : ISODate("2020-01-24T06:15:16Z"),
"lastHeartbeat" : ISODate("2020-01-24T06:15:24.871Z"),
"lastHeartbeatRecv" : ISODate("2020-01-24T06:15:25.718Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "localhost:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 273,
"optime" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDurable" : {
"ts" : Timestamp(1579846516, 1),
"t" : NumberLong(10)
},
"optimeDate" : ISODate("2020-01-24T06:15:16Z"),
"optimeDurableDate" : ISODate("2020-01-24T06:15:16Z"),
"lastHeartbeat" : ISODate("2020-01-24T06:15:24.894Z"),
"lastHeartbeatRecv" : ISODate("2020-01-24T06:15:24.702Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27018",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1579846526, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1579846526, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
问题:
- 为什么我无法连接到具有完整 URL 的 mongo 副本集?
- 我如何能够仅提供 1 个 IP 进行连接?
任何指导将不胜感激。
终于,我得到了解决这个问题的方法,
当我们启动一个副本集时,我们需要确保我们不必在成员的配置中提及localhost
(见下面的配置)。如果这样做,即使您使用命令 --bind_ip 0.0.0.0,::
或 --bind_all_ip
.
以下是正确和错误的配置。
不正确
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27017" },
{ _id: 2, host: "localhost:27017" }
]
})
正确 [同一台机器上的所有副本]
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "192.168.1.175:27017" },
{ _id: 1, host: "192.168.1.175:27018" },
{ _id: 2, host: "192.168.1.175:27019" }
]
})
正确 [不同机器上的所有副本]
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "192.168.1.175:27017" },
{ _id: 1, host: "192.168.1.176:27018" },
{ _id: 2, host: "192.168.1.177:27019" }
]
})