当主服务器节点在副本集中更改时,MongoDB java客户端失败

Posted

技术标签:

【中文标题】当主服务器节点在副本集中更改时,MongoDB java客户端失败【英文标题】:Mongodb java client fails when Primary Server node changes in replicaset 【发布时间】:2016-11-24 02:28:54 【问题描述】:

问题: MongoDB 写入失败并出现错误 -

在等待匹配的服务器 30000 毫秒后超时 主服务器选择器。集群状态的客户端视图是 type=REPLICA_SET, 服务器=[address=intdb01:27017, 类型=REPLICA_SET_SECONDARY,roundTripTime=0.7 毫秒,状态=CONNECTED]

当主节点从 intdb01 切换到 intdb02 时会发生这种情况。 看起来客户端驱动程序仍在寻找 intdb01 成为主节点。

我们的设置

我们在一个名为 rs0 的副本集中有 3 个 mongoDb 节点。 当我们使用 Java 连接到它时,我们在连接字符串中给出所有 3 个服务器,如下所示: mongodb://intdb01:27017,intdb02:27017,intdb03:27017/?replicaSet=rs0

db.version --> 3.0.4

Java驱动版本:mongodb-driver-3.0.4.jar、mongodb-driver-core-3.0.4.jar

客户端连接代码:

if( mongoClient == null) 
    MongoClientURI mcu = new MongoClientURI(mongoConnect);
    mongoClient = new MongoClient(mcu);

mongoConnect 包含如上所示的连接字符串。

Mongo 副本集状态信息

> rs.status()

  "set" : "rs0",
  "date" : ISODate("2016-07-19T21:14:03.001Z"),
  "myState" : 1,
  "members" : [
        "_id" : 0,
        "name" : "intdb01",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 439786,
        "optime" : Timestamp(1468521291, 5),
        "optimeDate" : ISODate("2016-07-14T18:34:51Z"),
        "lastHeartbeat" : ISODate("2016-07-19T21:14:01.877Z"),
        "lastHeartbeatRecv" : ISODate("2016-07-19T21:14:01.611Z"),
        "pingMs" : 0,
        "configVersion" : 4
    ,
    
        "_id" : 1,
        "name" : "intdb02:27017",
        "health" : 1,
        "state" : 1,
        "stateStr" : "PRIMARY",
        "uptime" : 2948844,
        "optime" : Timestamp(1468521291, 5),
        "optimeDate" : ISODate("2016-07-14T18:34:51Z"),
        "electionTime" : Timestamp(1468523057, 1),
        "electionDate" : ISODate("2016-07-14T19:04:17Z"),
        "configVersion" : 4,
        "self" : true
    ,
    
        "_id" : 2,
        "name" : "intdb03:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 439779,
        "optime" : Timestamp(1468521291, 5),
        "optimeDate" : ISODate("2016-07-14T18:34:51Z"),
        "lastHeartbeat" : ISODate("2016-07-19T21:14:01.294Z"),
        "lastHeartbeatRecv" : ISODate("2016-07-19T21:14:01.294Z"),
        "pingMs" : 0,
        "configVersion" : 4
    
  ],
  "ok" : 1

我已经用文档检查并重新检查了代码/配置,但找不到问题所在。 我们可以通过降低主节点来模拟这一点。 辅助节点接管,但应用程序写入开始失败。 :-(

非常感谢任何指针/提示!

添加堆栈跟踪-

Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches PrimaryServerSelector. Client view of cluster state is type=REPLICA_SET, servers=[address=intdb01:27017, type=REPLICA_SET_SECONDARY, roundTripTime=0.7 ms, state=CONNECTED]
at com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:370)
at com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:75)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:71)
at com.mongodb.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:68)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:175)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:141)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:72)
at com.mongodb.Mongo.execute(Mongo.java:747)
at com.mongodb.Mongo$2.execute(Mongo.java:730)
at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:482)
at com.mongodb.MongoCollectionImpl.update(MongoCollectionImpl.java:474)
at com.mongodb.MongoCollectionImpl.updateOne(MongoCollectionImpl.java:325)
at com.grid.core.persistence.mongodb.dao.GridEventDao.save(GridEventDao.java:69)
... 6 more
2016-07-19 17:05:01,882 [pool-2-thread-2] INFO   org.mongodb.driver.cluster - No server chosen by PrimaryServerSelector from cluster description ClusterDescriptiontype=REPLICA_SET, connectionMode=SINGLE, all=[ServerDescriptionaddress=intdb01:27017, type=REPLICA_SET_SECONDARY, state=CONNECTED, ok=true, version=ServerVersionversionList=[3, 0, 4], minWireVersion=0, maxWireVersion=3, electionId=null, maxDocumentSize=16777216, roundTripTimeNanos=724681, setName='rs0', canonicalAddress=intdb01:27017, hosts=[intdb01:27017, intdb02:27017], passives=[intdb03:27017], arbiters=[], primary='intdb02:27017', tagSet=TagSet[]]. Waiting for 30000 ms before timing out

我正在尝试确定这是编码错误还是配置。 堆栈跟踪中的最后一条信息消息,说 connectionMode 是 SINGLE。怀疑它导致了这个问题,但我在开发者文档站点中找不到任何相关信息。

【问题讨论】:

如果您要对某个问题投反对票,请勇敢地写下您的担忧,以帮助改善问题。这同样适用于投票结束的人。 能否提供完整的堆栈跟踪信息。 添加了写入失败的堆栈跟踪。 那么当 intdb02:27017 为主时,是否能够连接?例如您是否只在故障转移期间遇到这些故障? 不,它一直在失败。如果我更改程序中的连接字符串并将 intdb02 移动到字符串的前面,它就会开始工作。所以它似乎只识别第一台服务器。 【参考方案1】:

所有服务器地址都应出现在错误消息中。例如,尝试使用 3 个无法解析的任意主机名:

com.mongodb.MongoTimeoutException:在等待与 PrimaryServerSelector 匹配的服务器时,在 30000 毫秒后超时。集群状态的客户端视图是 type=REPLICA_SET, servers=[address=xxx:27117, type=UNKNOWN, state=CONNECTING, exception=com.mongodb.MongoSocketException: xxx, 由 java.net.UnknownHostException: xxx, address=xxx:27118, type=UNKNOWN, state=CONNECTING, exception=com.mongodb.MongoSocketException: xxx, 由 java.net.UnknownHostException: xxx 引起,address=xxx:27119 , type=UNKNOWN, state=CONNECTING, exception=com.mongodb.MongoSocketException: xxx, 由 java.net.UnknownHostException: xxx 引起 在 com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:370) 在 com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101) 在 com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.(ClusterBinding.java:75) 在 com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.(ClusterBinding.java:71) 在 com.mongodb.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:68) 在 com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:175) 在 com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:106) 在 com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:58) 在 com.mongodb.Mongo.execute(Mongo.java:747) 在 com.mongodb.Mongo$2.execute(Mongo.java:730) 在 com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:327) 在 com.mongodb.DBCollection.insert(DBCollection.java:323) 在 com.mongodb.DBCollection.insert(DBCollection.java:314) 在 com.mongodb.DBCollection.insert(DBCollection.java:284) 在 com.mongodb.DBCollection.insert(DBCollection.java:250) 在 com.mongodb.DBCollection.insert(DBCollection.java:187) 在 InsertTest2.main(InsertTest2.java:26)

注意所有 3 个服务器地址的显示方式。我建议您创建一个像这样的简单测试程序并进行验证,然后从那里向后工作。还要验证主机名是否正确解析,您也可以尝试 IP 地址。

【讨论】:

我会试试的。 - 创建一个简单的测试并从那里开始。它不是 Host/IP 解析,因为我可以独立连接到 all ,只是在辅助服务器成为主服务器时不能。我怀疑我有连接字符串的方式。如果我取得任何进展,我会到处玩并更新。如果我能找到 org.mongodb.driver.cluster 的源代码,最后一个选项是下载源代码。

以上是关于当主服务器节点在副本集中更改时,MongoDB java客户端失败的主要内容,如果未能解决你的问题,请参考以下文章

Pymongo - 在 mongodb 副本集中查找主/主节点名称

MongoDB副本集

mongodb--选举失败

mongodb 副本集搭建

需要更改副本集的mongodb辅助节点中的存储dbpath

MongoDB更改oplog的大小