使用Java(Windows)连接到在Docker内部运行的MongoDB副本集

Mia*_*Mia 3 mongodb mongodb-java docker mongodb-replica-set

我想用docker设置一个MongoDB副本集。设置似乎很好,但是我无法使用Java应用程序连接到集群。我正在Windows 10上使用VirtualBox作为驱动程序运行Docker版本17.06.0-ce。

我按照本教程中的说明进行操作:http : //www.sohamkamani.com/blog/2016/06/30/docker-mongo-replica-set/

因此,我首先在docker中创建了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
Run Code Online (Sandbox Code Playgroud)

然后,我连接到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)
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常。从mongo1容器的日志中可以看出,所有容器都是相互连接的。

现在,我正在尝试从Java应用程序连接到副本集。我正在使用3.6.0版的mongodb驱动程序。这是我用来连接到在docker中运行的副本集的代码:

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);
Run Code Online (Sandbox Code Playgroud)

这是日志输出(在mongo1:27017和mongo2:27017的末尾也出现MongoSocketException):

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
Run Code Online (Sandbox Code Playgroud)

Mia*_*Mia 6

最后,我通过阅读以下内容找到了解决方案:

https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#clients-use-the-hostnames-listed-in-the-副本集配置不是种子列表

最后一句很重要: “总而言之,要支持副本集的关键功能,我们要求副本集配置中使用的主机名可从客户端访问。”

因此,这意味着配置中的主机名必须从外部可见/可访问。但是由于我在Windows上使用VirtualBox运行Docker,因此MongoClient仅能看到我的VM的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

  • 当您没有修改 etc/host 文件的管理员权限时,还有其他解决方案吗??? (2认同)

Syd*_*ney 6

将主机名添加到主机文件对我不起作用。我认为如果所有主机名都指向相同的主机 IP(例如 127.0.0.1),那么如果所有 docker 端口都相同(例如 27017),它将无法工作。副本集由mongo1:27017, mongo2:27017 and mongo3:27017内部 docker组成。在 docker 之外,它对应于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() 
Run Code Online (Sandbox Code Playgroud)

最后将主机名添加到主机文件中

127.0.0.1 mongo1 mongo2 mongo3
Run Code Online (Sandbox Code Playgroud)

  • 也救了我!我猜 `--port` 做到了这一点。我对吗?@悉尼@Marek M. (2认同)