在docker容器内使用容器外的mongodb的复制集

复制集配置:

1
2
3
4
5
6
7
8
9
config = {
_id: "mike",
members: [
{_id:1, host:"127.0.0.1:30001"},
{_id:2, host:"127.0.0.1:30002"},
{_id:3, host:"127.0.0.1:30003",arbiterOnly:true}
]
}
rs.initiate(config);

使用PHP测试mongodb复制集和读写分离,以下是测试的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$dsn = 'mongodb://192.168.222.107:30001/mike';
$options = [
'replicaSet' => 'mike',
'readPreference' => 'primary',
'w' => 1,
'wtimeout' => 2000,
'connectTimeoutMS' => 5000,
];

$manager = new MongoDB\Driver\Manager($dsn, $options);
$readPreference = $manager->getReadPreference();
$server = $manager->selectServer($readPreference)

使用docker环境下的PHP中执行,出现错误:

1
No suitable servers found (`serverselectiontryonce` set): [connection timeout calling ismaster on '127.0.0.1:3306']

为了确定数据库运行正常,不使用复制集配置,去掉了options中的replicaSet配置,发现正常连接,基本确认数据库运行正常. 那么问题就出现在复制集的使用上。

分析错误,问题出在确认masterconnection refused. 于是我单独使用mongo shell发送命令确认:

1
mongo 192.168.222.107:30001 --eval 'printjson(db.runCommand({"isMaster": 1}))'

也显示连接正常.

分析场景,PHP代码的执行是在docker容器内,mongodb实例是运行是在宿主机,虽然PHP代码中的连接配置是192.168.222.107:30001,宿主机的IP地址,但是发送isMaster命令的时候却是使用的127.0.0.1:30001,这样是连接的docker容器内的,因为容器内没有mongodb实例,所有以肯定connection refused.

为什么发送isMaster的时候使用的是127.0.0.1:30001呢

因为复制集的config中指定的host就是127.0.0.1

更改复制集配置:

1
2
3
4
5
6
7
8
9
config = {
_id: "mike",
members: [
{_id:1, host:"192.168.222.107:30001"},
{_id:2, host:"192.168.222.107:30002"},
{_id:3, host:"192.168.222.107:30003",arbiterOnly:true}
]
}
rs.reconfig(config);

重新运行代码,一切OK. oops!!!