MongoDB:ReadPreferenceServerSelector 没有选择服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29718933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:23:48  来源:igfitidea点击:

MongoDB: No server chosen by ReadPreferenceServerSelector

mongodbmongodb-java

提问by ahwyX100

Recently I am using mongodb java async driver which is newly released. I am writing some simple test codes, which are:

最近我正在使用新发布的 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);

however, the callback function is not called, the console output is:

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

April 18, 2015 10:50:27 afternoon com.mongodb.diagnostics.logging.JULLogger log message: Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
database has been connected!April 18, 2015 10:50:28 afternoon com.mongodb.diagnostics.logging.JULLogger log message: No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=localhost:27017, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out

2015 年 4 月 18 日 10:50:27 下午 com.mongodb.diagnostics.logging.JULLogger 日志消息:Cluster created with settings {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{地址=本地主机:27017,类型=未知,状态=连接}]}。超时前等待 30000 毫秒

So you can see there is no callback function called. Anyone knows why?

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

回答by Ross

The short answer is your callback will be called eventually.

简短的回答是您的回调最终会被调用。

For the long answer, lets work through your code:

对于长答案,让我们来看看你的代码:

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

MongoClientdoesn't block waiting for a connection to MongoDB in the background the internal connection pool is trying to connect. From your logs I can see you have the default serverSelectionTimeoutof 30000ms.

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

Next step you do a printlnwhich output immediately so "database has been connected!" gets printed regardless.

下一步您println立即执行which 输出,以便“数据库已连接!” 无论如何都会打印出来。

Finally, you call listDatabaseNames()but what's not clear is if any waits for the callback to be called. If you add a latch then await the response then you will see that the callback is called eg:

最后,您调用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 =======");

Now using the latch we await()until the callback has been called, now we should see one of two things happen:

现在使用锁存器,await()直到回调被调用,现在我们应该看到以下两种情况之一发生:

  1. There is no MongoDB available. It will eventually call the callback and print that there was an error. It will wait until the serverSelectionTimeouttimes out.

  2. There is a MongoDB available. It will eventually connect, for each database it will apply the Blockand print out the database name and then finally it will call the callback signalling it has finished.

  1. 没有可用的 MongoDB。它最终会调用回调并打印出有错误。它会等到serverSelectionTimeout超时。

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

回答by fegyi001

I think you should close the MongoClient object every time in a finally clause. For me the same problem occured, and when I closed the connection in the command line I saw that a LOT of connections were open.

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

Try something like this (I use mongodb 3.0.7 and mongo-java-driver 3.1.0):

尝试这样的事情(我使用 mongodb 3.0.7 和 mongo-java-driver 3.1.0):

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) {
            }
        }
    }

}

With this, I could use my connection with no problem.

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