Когда основной сервер моего набора репликации дает сбой, в настоящее время открытые соединения также перестают работать (!) MongoConnectionException
(No candidate servers found
) или с MongoCursorException
(mongoUbuntu:8004: Remote server has closed the connection
) когда я использую GridFS.
Это ошибка или мне нужно изменить настройки, чтобы заставить работать автоматический переход на другой ресурс?
mongoUbuntu
Процессы mongodb были запущены на одном компьютере со следующей командной строкой Я использую 4 сервера на портах 8001, 8002, 8003 и 8004, а также один арбитр на 8010. Командная строка для 8001 выглядит следующим образом:
mongod --replSet rs1 --dbpath /var/lib/mongodb1 --port 8001 --smallfiles --oplogSize 200 --httpinterface --rest
{
"set" : "rs1",
"date" : ISODate("2015-04-08T14:48:57Z"),
"myState" : 3,
"members" : [
{
"_id" : 0,
"name" : "mongoUbuntu:8004",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 467,
"optime" : Timestamp(1428501340, 1),
"optimeDate" : ISODate("2015-04-08T13:55:40Z"),
"lastHeartbeat" : ISODate("2015-04-08T14:48:56Z"),
"lastHeartbeatRecv" : ISODate("2015-04-08T14:48:55Z"),
"pingMs" : 0,
"syncingTo" : "mongoUbuntu:8001"},
{
"_id" : 1,
"name" : "mongoUbuntu:8003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 987,
"optime" : Timestamp(1428501340, 1),
"optimeDate" : ISODate("2015-04-08T13:55:40Z"),
"lastHeartbeat" : ISODate("2015-04-08T14:48:56Z"),
"lastHeartbeatRecv" : ISODate("2015-04-08T14:48:56Z"),
"pingMs" : 0,
"syncingTo" : "mongoUbuntu:8001"},
{
"_id" : 2,
"name" : "mongoUbuntu:8002",
"health" : 1,
"state" : 3,
"stateStr" : "RECOVERING",
"uptime" : 3142,
"optime" : Timestamp(1428498901, 1),
"optimeDate" : ISODate("2015-04-08T13:15:01Z"),
"infoMessage" : "still syncing, not yet to minValid optime 55252e9b:37",
"self" : true
},
{
"_id" : 3,
"name" : "mongoUbuntu:8001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 3139,
"optime" : Timestamp(1428501340, 1),
"optimeDate" : ISODate("2015-04-08T13:55:40Z"),
"lastHeartbeat" : ISODate("2015-04-08T14:48:56Z"),
"lastHeartbeatRecv" : ISODate("2015-04-08T14:48:56Z"),
"pingMs" : 0,
"electionTime" : Timestamp(1428503596, 1),
"electionDate" : ISODate("2015-04-08T14:33:16Z")
},
{
"_id" : 4,
"name" : "mongoUbuntu:8010",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 3139,
"lastHeartbeat" : ISODate("2015-04-08T14:48:56Z"),
"lastHeartbeatRecv" : ISODate("2015-04-08T14:48:55Z"),
"pingMs" : 0
}
],
"ok" : 1
}
Следующий скрипт выполняется, когда я завершаю текущий первичный (Пример без реального использования GridFS, но непосредственно выполняющий запрос.)
<?php
$conn = new \MongoClient(
'mongodb://mongoUbuntu:8001,mongoUbuntu:8002,mongoUbuntu:8003',
array('replicaSet' => 'rs1', 'readPreference' => \MongoClient::RP_PRIMARY_PREFERRED)
);
$db = $conn->bat; //db name: bat
$gridfs = $this->_db->getGridFS();
while(true) {
$documents = $db->execute('db.getCollection(\'fs.files\').count()');
echo $documents['retval']."\n";
sleep(1);
}
Пока я не завершу текущее первичное задание, скрипт печатает количество документов в командной строке. Когда я завершаю текущий основной (нажав Ctrl + C в командной строке Respectiv Mongod) сценарий php сразу, потому что исключение, в данном случае MongoConnectionException
No candidate servers found
,
Я использовал скрипт GitHub для создания полный журнал отладки, и сохранил его как Gist mongo-php-log-automaticfailover-fails.
Нужно ли добавлять другой параметр для создания соединения или конфигурации набора репликации? Если это описано в документации mongodb или документации драйвера mongodb php, где я могу найти его?
Да, водитель выдает исключение. Технически это правильно, особенно если вы хотите знать, когда происходит сбой. Что вам нужно сделать, это поймать исключение и повторить попытку.
Ваша самая большая проблема здесь заключается в том, что по какой-то причине вы повышаете. Eval требует запуска ТОЛЬКО на ведущем устройстве, поэтому при сбое набора необходимо ждать выбранного мастера, что может занять до 10 секунд.
Тем не менее, кажется, что этот аспект eval на самом деле не задокументирован, хотя признается: https://dba.stackexchange.com/questions/75852/mongodb-replicaset-reconfig-when-primary-and-majority-dont-exist поскольку ответчиком по этому вопросу на самом деле является 10gen (MongoDB Inc), и он, похоже, не отрицает, что eval не работает на вторичных серверах. Я вполне уверен, что это было в документации, хотя, где я впервые увидел это.
Это довольно хорошо объяснено в курсе MongoDB 101 для Python. То же самое относится к большинству языков. Лично я просто запрещаю соединение до тех пор, пока не будет найден новый первичный файл (но тогда я не проверяю материал), но если вы только читаете, вы можете удалить eval и сделать это через PHP. Это должно позволить вам читать без помех.
Других решений пока нет …