我现在认为 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 空检查来区分“ReplSet-DOWN”和“只读”。
这个驱动程序真正需要的是某种方式来直接询问 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 )
这对我来说很有意义,因为它承认 ReplSet 在创建 Mongo 时可能很棒,但现在的条件意味着特定类型的读取或写入操作可能会由于条件的变化而失败。
无论如何,也许http://api.mongodb.org/java/2.11.1/com/mongodb/ReplicaSetStatus.html可以满足您的需求。