我们的应用程序基于mongodb副本集构建。 我希望捕获副本集处于自动故障转移过程中的时间范围内抛出的所有异常。 我将使应用程序重试或等待故障转移完成。 这样故障转移不会影响用户。 我在这里找到了描述java驱动程序行为的文档:https://jira.mongodb.org/browse/DOCS-581
我编写了一个测试程序来查找所有可能的异常,它们都是MongoException但有不同的消息:
我很困惑,不确定通过错误消息确定是否安全。 此外,我不想捕捉所有MongoException。 有什么建议吗?
由于
答案 0 :(得分:1)
当Mongo故障转移时,没有处于PRIMARY状态的节点。您可以通过replSetGetStatus命令获取副本集状态,并查找主节点。如果找不到,则可以假设群集处于故障转移过渡状态,并且可以根据需要重试,检查每个失败连接上的副本集状态。
答案 1 :(得分:1)
我现在认为Java中的Mongo在这方面特别薄弱。我不认为你解释错误代码的策略可以很好地扩展或者在驱动程序演变中存活下来。当然,这是意见。
好消息是Mongo驱动程序提供了一种获取ReplicaSet状态的方法:http://api.mongodb.org/java/2.11.1/com/mongodb/ReplicaSetStatus.html。您可以直接使用它来确定应用程序是否可以看到Master。如果您只想知道,http://api.mongodb.org/java/2.11.1/com/mongodb/Mongo.html#getReplicaSetStatus()就是您所需要的。抓住那个孩子并检查一个非空主人,你就在路上。
ReplicaSetStatus rss = mongo.getReplicaSetStatus();
boolean driverInFailover = rss.getMaster() == null;
如果你真正需要的是弄清楚ReplSet是死了,只读还是读写,这就变得更加困难了。这段代码对我有用。我恨它。
@Override
public ReplSetStatus getReplSetStatus() {
ReplSetStatus rss = ReplSetStatus.DOWN;
MongoClient freshClient = null;
try {
if ( mongo != null ) {
ReplicaSetStatus replicaSetStatus = mongo.getReplicaSetStatus();
if ( replicaSetStatus != null ) {
if ( replicaSetStatus.getMaster() != null ) {
rss = ReplSetStatus.ReadWrite;
} else {
/*
* When mongo.getReplicaSetStatus().getMaster() returns null, it takes a a
* fresh client to assert whether the ReplSet is read-only or completely
* down. I freaking hate this, but take it up with 10gen.
*/
freshClient = new MongoClient( mongo.getAllAddress(), mongo.getMongoClientOptions() );
replicaSetStatus = freshClient.getReplicaSetStatus();
if ( replicaSetStatus != null ) {
rss = replicaSetStatus.getMaster() != null ? ReplSetStatus.ReadWrite : ReplSetStatus.ReadOnly;
} else {
log.warn( "freshClient.getReplicaSetStatus() is null" );
}
}
} else {
log.warn( "mongo.getReplicaSetStatus() returned null" );
}
} else {
throw new IllegalStateException( "mongo is null?!?" );
}
} catch ( Throwable t ) {
log.error( "Ingore unexpected error", t );
} finally {
if ( freshClient != null ) {
freshClient.close();
}
}
log.debug( "getReplSetStatus(): {}", rss );
return rss;
}
我讨厌它,因为它不遵循应用程序的Mongo Java Driver约定只需要一个Mongo,并通过这个单例连接到其余的Mongo数据结构(DB,Collection等)。我只能通过在检查期间新建第二个Mongo来观察这个工作,这样我就可以依赖ReplicaSetStatus null检查来区分“ReplSet-DOWN”和“read-only”。
这个驱动程序真正需要的是一些方法来询问Mongo的直接问题,看看此时是否可以预期ReplSet支持WriteConcerns或ReadPreferences。有点像...
/**
* @return true if current state of Client can support readPreference, false otherwise
*/
boolean mongo.canDoRead( ReadPreference readPreference )
/**
* @return true if current state of Client can support writeConcern; false otherwise
*/
boolean mongo.canDoWrite( WriteConcern writeConcern )
这对我有意义,因为它承认在创建Mongo时ReplSet可能很好,但现在的条件意味着特定类型的读或写操作可能会因条件的变化而失败。
无论如何,也许http://api.mongodb.org/java/2.11.1/com/mongodb/ReplicaSetStatus.html可以满足您的需求。
答案 2 :(得分:0)