MongoDB:ReadPreferenceServerSelector未选择服务器

MongoDB:ReadPreferenceServerSelector未选择服务器,mongodb,mongodb-java,Mongodb,Mongodb Java,最近我正在使用新发布的mongodb java异步驱动程序。我正在编写一些简单的测试代码,它们是: MongoClient mongoClient = MongoClients.create(); System.out.println("database has been connected!"); SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Vo

最近我正在使用新发布的mongodb java异步驱动程序。我正在编写一些简单的测试代码,它们是:

    MongoClient mongoClient = MongoClients.create();
    System.out.println("database has been connected!");

    SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
        @Override
        public void onResult(final Void result, final Throwable t) {
            System.out.println("Operation Finished!");
        }
    };

    mongoClient.listDatabaseNames().forEach(new Block<String>() {
        @Override
        public void apply(final String s) {
            System.out.println(s);
        }
    }, callbackWhenFinished);
MongoClient-MongoClient=MongoClients.create();
System.out.println(“数据库已连接!”);
SingleResultCallback callbackWhenFinished=新建SingleResultCallback(){
@凌驾
公开作废结果(最终作废结果、最终可丢弃结果){
System.out.println(“操作完成!”);
}
};
mongoClient.listDatabaseNames().forEach(新块(){
@凌驾
公共无效应用(最终字符串s){
系统输出打印项次;
}
},完成时回调);
但是,不会调用回调函数,控制台输出为:

2015年4月18日10:50:27下午 com.mongodb.diagnostics.logging.JULLogger日志消息:已创建群集 设置为{hosts=[localhost:27017],mode=SINGLE, requiredClusterType=未知,服务器选择超时='30000毫秒', maxWaitQueueSize=500}
数据库已连接2015年4月18日10:50:28下午com.mongodb.diagnostics.logging.JULLogger日志消息:否 选择的服务器 ReadPreferenceServerSelector{readPreference=primary}来自集群 description ClusterDescription{type=UNKNOWN,connectionMode=SINGLE, all=[ServerDescription{address=localhost:27017,type=UNKNOWN, 状态=正在连接}]}。在超时之前等待30000毫秒


因此,您可以看到没有调用回调函数。有人知道为什么吗?

简单的回答是,您的回拨最终会被调用

对于详细的答案,让我们来研究一下您的代码:

    MongoClient mongoClient = MongoClients.create();
    System.out.println("database has been connected!");
MongoClient
不会阻止在内部连接池尝试连接的后台等待与MongoDB的连接。从您的日志中,我可以看到您的默认
serverSelectionTimeout
为30000ms

下一步,您将执行一个
println
,该输出将立即打印,以便“数据库已连接!”

最后,调用
listDatabaseNames()
,但不清楚的是是否有任何函数等待调用回调。如果您添加一个闩锁,然后等待响应,那么您将看到回调被称为eg:

  System.out.println("======= Start =======");

  MongoClient mongoClient = MongoClients.create();

  final CountDownLatch latch = new CountDownLatch(1);

  SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
      @Override
      public void onResult(final Void result, final Throwable t) {
          System.out.println("Operation Finished!");
          if (t != null) {
              System.out.println("listDatabaseNames() errored: " + t.getMessage());
          }
          latch.countDown();
      }
  };

  mongoClient.listDatabaseNames().forEach(new Block<String>() {
      @Override
      public void apply(final String s) {
          System.out.println(s);
      }
  }, callbackWhenFinished);

  latch.await();

  // close resources
  mongoClient.close();
  System.out.println("======= Finish =======");
System.out.println(“=============Start==========”;
MongoClient MongoClient=MongoClients.create();
最终倒计时闩锁=新倒计时闩锁(1);
SingleResultCallback callbackWhenFinished=新建SingleResultCallback(){
@凌驾
公开作废结果(最终作废结果、最终可丢弃结果){
System.out.println(“操作完成!”);
如果(t!=null){
System.out.println(“listDatabaseNames()出错:+t.getMessage());
}
倒计时();
}
};
mongoClient.listDatabaseNames().forEach(新块(){
@凌驾
公共无效应用(最终字符串s){
系统输出打印项次;
}
},完成时回调);
satch.wait();
//密切资源
mongoClient.close();
System.out.println(“==========完成========”);
现在,在调用回调之前,使用闩锁we
await()
,我们应该看到两种情况之一:

  • 没有可用的MongoDB。 它最终将调用回调并打印出有错误。它将等待
    serverSelectionTimeout
    超时

  • 有一个MongoDB可用。 它将最终连接,对于每个数据库,它将应用
    ,并打印出数据库名称,最后它将调用已完成的回调信号


  • 我认为您应该在finally子句中每次都关闭MongoClient对象。对我来说,同样的问题也发生了,当我在命令行中关闭连接时,我看到很多连接都打开了

    试试这样(我使用mongodb 3.0.7和mongo java驱动程序3.1.0):

    package com.mkyong.core;
    导入org.bson.Document;
    导入org.junit.Test;
    导入com.mongodb.Block;
    导入com.mongodb.MongoClient;
    导入com.mongodb.client.FindIterable;
    导入com.mongodb.client.MongoDatabase;
    /**
    *简单应用程序的单元测试。
    */
    公共类应用程序测试{
    @试验
    public void firstTest()引发异常{
    MongoClient MongoClient=null;
    试一试{
    mongoClient=新的mongoClient(“127.0.0.1”,27017);
    MongoDatabase db=mongoClient.getDatabase(“普查”);
    FindItemerable-iterable=db.getCollection(“states”).find();
    iterable.forEach(新块(){
    @凌驾
    公开作废申请(最终文件){
    系统输出打印项次(文件);
    }
    });
    }捕获(例外e){
    e、 printStackTrace();
    }最后{
    试一试{
    mongoClient.close();
    }捕获(异常e2){
    }
    }
    }
    }
    

    有了这个,我可以毫无问题地使用连接。

    为什么我要显式调用wait,程序不应该等到所有用户线程都完成了吗?
    package com.mkyong.core;
    
    import org.bson.Document;
    import org.junit.Test;
    
    import com.mongodb.Block;
    import com.mongodb.MongoClient;
    import com.mongodb.client.FindIterable;
    import com.mongodb.client.MongoDatabase;
    
    /**
     * Unit test for simple App.
     */
    public class AppTest {
    
        @Test
        public void firstTest() throws Exception {
            MongoClient mongoClient = null;
            try {
                mongoClient = new MongoClient("127.0.0.1", 27017);
                MongoDatabase db = mongoClient.getDatabase("census");
                FindIterable<Document> iterable = db.getCollection("states").find();
                iterable.forEach(new Block<Document>() {
                    @Override
                    public void apply(final Document document) {
                        System.out.println(document);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    mongoClient.close();
                } catch (Exception e2) {
                }
            }
        }
    
    }