Подключение к набору реплик MongoDB, работающему внутри Docker с помощью Java (Windows)

Я хочу настроить набор реплик MongoDB с помощью docker. Кажется, с настройкой все в порядке, но я не могу подключиться к кластеру с помощью своего Java-приложения. Я запускаю Docker версии 17.06.0-ce в Windows 10 с VirtualBox в качестве драйвера.

Я выполнил инструкции из этого руководства: http://www.sohamkamani.com/blog/2016/06/30/docker-mongo-replica-set/

Итак, я сначала создал сеть my-mongo-cluster в докере и запустил 3 контейнера с помощью следующих команд:

$ docker run --name mongo1 -d --net mongo-cluster -p 9042:27017 mongo:3.6.0 mongod --replSet my-mongo-set
$ docker run --name mongo2 -d --net mongo-cluster -p 9142:27017 mongo:3.6.0 mongod --replSet my-mongo-set
$ docker run --name mongo3 -d --net mongo-cluster -p 9242:27017 mongo:3.6.0 mongod --replSet my-mongo-set

Затем я подключаюсь к контейнеру mongo1 и настраиваю набор реплик со следующей конфигурацией:

config = {"_id" : "my-mongo-set", "members" : [{"_id" : 0,"host" : "mongo1:27017"},{"_id" : 1,"host" : "mongo2:27017"},{"_id" : 2,"host" : "mongo3:27017"}]}
rs.initiate(config)

Кажется, это работает нормально. Как я могу судить из журналов контейнера mongo1, все контейнеры связаны друг с другом.

Теперь я пытаюсь подключиться из своего Java-приложения к набору реплик. Я использую mongodb-driver версии 3.6.0. Это код, который я использую для подключения к набору реплик, запущенному в докере:

List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();
serverAddresses.add(new ServerAddress(InetAddress.getByName("192.168.99.100"), 9042));
serverAddresses.add(new ServerAddress(InetAddress.getByName("192.168.99.100"), 9142));
serverAddresses.add(new ServerAddress(InetAddress.getByName("192.168.99.100"), 9242));

MongoClient client = new MongoClient(serverAddresses);

И это вывод журнала (MongoSocketException в конце также появляется для mongo1: 27017 и mongo2: 27017):

Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Cluster created with settings {hosts=[192.168.99.100:9042, 192.168.99.100:9142, 192.168.99.100:9242], mode=MULTIPLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server 192.168.99.100:9042 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server 192.168.99.100:9142 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server 192.168.99.100:9242 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Cluster description not yet available. Waiting for 30000 ms before timing out
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Opened connection [connectionId{localValue:2, serverValue:5}] to 192.168.99.100:9142
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Opened connection [connectionId{localValue:1, serverValue:14}] to 192.168.99.100:9042
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Opened connection [connectionId{localValue:3, serverValue:5}] to 192.168.99.100:9242
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Monitor thread successfully connected to server with description ServerDescription{address=192.168.99.100:9242, type=REPLICA_SET_SECONDARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=5002651, setName='my-mongo-set', canonicalAddress=mongo3:27017, hosts=[mongo3:27017, mongo2:27017, mongo1:27017], passives=[], arbiters=[], primary='mongo1:27017', tagSet=TagSet{[]}, electionId=null, setVersion=1, lastWriteDate=Wed Dec 27 21:36:00 CET 2017, lastUpdateTimeNanos=440549516217673}
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Monitor thread successfully connected to server with description ServerDescription{address=192.168.99.100:9142, type=REPLICA_SET_SECONDARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=5542139, setName='my-mongo-set', canonicalAddress=mongo2:27017, hosts=[mongo3:27017, mongo2:27017, mongo1:27017], passives=[], arbiters=[], primary='mongo1:27017', tagSet=TagSet{[]}, electionId=null, setVersion=1, lastWriteDate=Wed Dec 27 21:36:00 CET 2017, lastUpdateTimeNanos=440549516254709}
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Monitor thread successfully connected to server with description ServerDescription{address=192.168.99.100:9042, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=4113767, setName='my-mongo-set', canonicalAddress=mongo1:27017, hosts=[mongo3:27017, mongo2:27017, mongo1:27017], passives=[], arbiters=[], primary='mongo1:27017', tagSet=TagSet{[]}, electionId=7fffffff0000000000000001, setVersion=1, lastWriteDate=Wed Dec 27 21:36:00 CET 2017, lastUpdateTimeNanos=440549515190458}
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Discovered cluster type of REPLICA_SET
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server mongo3:27017 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server mongo2:27017 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Adding discovered server mongo1:27017 to client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Canonical address mongo2:27017 does not match server address.  Removing 192.168.99.100:9142 from client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Server 192.168.99.100:9242 is no longer a member of the replica set.  Removing from client view of cluster.
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Server 192.168.99.100:9042 is no longer a member of the replica set.  Removing from client view of cluster.
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Canonical address mongo1:27017 does not match server address.  Removing 192.168.99.100:9042 from client view of cluster
Dez 27, 2017 9:36:07 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: No server chosen by com.mongodb.Mongo$4@67784306 from cluster description ClusterDescription{type=REPLICA_SET, connectionMode=MULTIPLE, serverDescriptions=[ServerDescription{address=192.168.99.100:9242, type=UNKNOWN, state=CONNECTING}, ServerDescription{address=mongo3:27017, type=UNKNOWN, state=CONNECTING}, ServerDescription{address=mongo2:27017, type=UNKNOWN, state=CONNECTING}, ServerDescription{address=mongo1:27017, type=UNKNOWN, state=CONNECTING}, ServerDescription{address=192.168.99.100:9042, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out
Dez 27, 2017 9:36:09 PM com.mongodb.diagnostics.logging.JULLogger log
INFORMATION: Exception in monitor thread while connecting to server mongo3:27017
com.mongodb.MongoSocketException: mongo3
at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:188)
at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:59)
at com.mongodb.connection.SocketStream.open(SocketStream.java:57)
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:126)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:114)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.UnknownHostException: mongo3
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
at java.net.InetAddress.getAllByName(InetAddress.java:1192)
at java.net.InetAddress.getAllByName(InetAddress.java:1126)
at java.net.InetAddress.getByName(InetAddress.java:1076)
at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:186)
... 5 more

person Mia    schedule 27.12.2017    source источник
comment
не проще ли использовать docker-compose для запуска этих трех реплик в простой сети? Кроме того, не совсем уверен, но в вашей конфигурации json хост не должен указывать на порты 9042 ...?   -  person PekosoG    schedule 28.12.2017


Ответы (3)


Наконец, я нашел решение, прочитав это:

https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#clients-use-the-hostnames-listed-in-the-replica-set-config-not-the-seed-list

Последнее предложение важно: «В заключение, для поддержки ключевых функций наборов реплик мы требуем, чтобы имена хостов, используемые в конфигурации набора реплик, были доступны от клиента».

Это означает, что имена хостов в конфигурации должны быть видимыми / доступными извне. Но поскольку я запускаю Docker в Windows с VirtualBox, MongoClient может видеть только IP-адрес моей виртуальной машины и не может обрабатывать mongo1, mongo2, mongo3 (соответственно внутренние IP-адреса контейнеров).

Решением было добавить имена хостов в файл hosts (в Windows, расположенный в C: / Windows / System32 / drivers / etc / hosts):

192.168.99.100 mongo1 192.168.99.100 mongo2 192.168.99.100 mongo3

person Mia    schedule 28.12.2017
comment
Есть ли другое решение, если у вас нет прав администратора на изменение файла etc / host ??? - person ThierryC; 18.01.2021

Добавление имен хостов в файл hosts у меня не сработало. Я думаю, что если все имена хостов относятся к одному и тому же IP-адресу хоста (например, 127.0.0.1), он не будет работать, если все порты докеров одинаковы (например, 27017). Набор реплик состоит из mongo1:27017, mongo2:27017 and mongo3:27017 внутри докера. Вне докера это соответствует 127.0.0.1:27017, 127.0.0.1:27017 and 127.0.0.1:27017, который не работает. Чтобы решить эту проблему, мне пришлось установить отдельный порт для каждого узла.

docker network create mongo-cluster
docker run --name mongo1 -d --net mongo-cluster -p 9042:9042 mongo:3.6 mongod --replSet docker-rs --port 9042
docker run --name mongo2 -d --net mongo-cluster -p 9142:9142 mongo:3.6 mongod --replSet docker-rs --port 9142
docker run --name mongo3 -d --net mongo-cluster -p 9242:9242 mongo:3.6 mongod --replSet docker-rs --port 9242
docker exec -it mongo1 mongo --port 9042
config = {"_id" : "docker-rs", "members" : [{"_id" : 0,"host" : "mongo1:9042"},{"_id" : 1,"host" : "mongo2:9142"},{"_id" : 2,"host" : "mongo3:9242"}]}
rs.initiate(config)
rs.status() 

и, наконец, добавьте имена хостов в файл hosts

127.0.0.1 mongo1 mongo2 mongo3
person Sydney    schedule 15.06.2018
comment
Ты буквально спас мне жизнь. Спасибо! - person Marek M.; 10.03.2020
comment
Спас меня тоже! Думаю, --port сделал то, что нужно. Я прав? @ Сидней @ Марек М. - person Nedim; 09.12.2020
comment
Есть ли другое решение, если у вас нет прав администратора на изменение файла etc / host ??? - person ThierryC; 18.01.2021

Проблема в том, что узлы набора реплик видны снаружи на портах 9x42, но внутренние (настроенные) адреса этих узлов - 27017. Оба они должны быть одинаковыми. Итак, когда вы запускаете mongod, вы должны указать параметр --port с тем же номером порта, который используется снаружи контейнера.

person JJussi    schedule 28.12.2017
comment
Спасибо. Я все еще не могу заставить его работать. Я попытался запустить контейнеры: docker run --name mongo1 ... -p 27017:27017 mongo mongod --replSet my-mongo-set --port 27017 и `docker run --name mongo2 ... -p 27018:27018 mongo mongod --replSet my-mongo-set --port 27018, а третий - с портом 27019. Также я изменил конфигурацию на mongo1: 27017, mongo2: 27018 и mongo3: 27019, и в моем Java-приложении я создаю адреса серверов с этим 3 порта. Но все же то же исключение ... Канонический адрес mongo2: 27018 не совпадает с адресом сервера. Удаление 192.168.99.100:27018 из клиентского представления кластера - person Mia; 28.12.2017
comment
Вам нужно добавить строки в файлы / etc / hosts на каждом узле, чтобы имя узла, такое как mongo2, было преобразовано в этот IP-адрес, каким оно должно быть. Как видно из сообщения об ошибке, в нем говорится, что mongo2 не разрешает этот 192.168.99.102 - person JJussi; 28.12.2017
comment
Я уже нашел решение и самостоятельно ответил на вопрос. Спасибо за помощь :) - person Mia; 28.12.2017