MongoDB:ReadPreferenceServerSelector未选择任何服务器

ahw*_*100 5 mongodb mongodb-java

最近我使用的是新发布的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);
Run Code Online (Sandbox Code Playgroud)

但是,没有调用回调函数,控制台输出是:

2015年4月18日下午10:50:27 com.mongodb.diagnostics.logging.JULLogger日志消息:使用设置创建的集群{hosts = [localhost:27017],mode = SINGLE,requiredClusterType = UNKNOWN,serverSelectionTimeout ='30000 ms', maxWaitQueueSize = 500}
数据库已连接! 2015年4月18日下午10:50:28 com.mongodb.diagnostics.logging.JULLogger日志消息:ReadPreferenceServerSelector {readPreference = primary}从集群描述ClusterDescription中选择的服务器 {type = UNKNOWN,connectionMode = SINGLE,all = [ServerDescription { address = localhost:27017,type = UNKNOWN,state = CONNECTING}]}.超时前等待30000毫秒

所以你可以看到没有调用回调函数.谁知道为什么?

Ros*_*oss 7

简短的回答是你的回调最终会被调用.

对于长期答案,让我们完成您的代码:

    MongoClient mongoClient = MongoClients.create();
    System.out.println("database has been connected!");
Run Code Online (Sandbox Code Playgroud)

MongoClient不阻止在内部连接池尝试连接的后台等待与MongoDB的连接.从您的日志中我可以看到您的默认serverSelectionTimeout值为30000ms.

下一步,您println立即执行哪个输出,以便"数据库已连接!" 无论如何都要打印

最后,你调用listDatabaseNames()但不清楚是否有任何等待回调被调用.如果您添加一个锁存器然后等待响应,那么您将看到回调被调用,例如:

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

现在使用latch我们await()直到调用回调,现在我们应该看到两件事之一发生:

  1. 没有MongoDB可用.它最终将调用回调并打印出错误.它会等到serverSelectionTimeout时间结束.

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