MongoDB: ReadPreferenceServerSelector 没有选择服务器
MongoDB: No server chosen by ReadPreferenceServerSelector
最近在用mongodbjava新发布的async驱动。我正在写一些简单的测试代码,它们是:
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);
但是没有调用回调函数,控制台输出为:
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
所以你可以看到没有调用回调函数。有人知道为什么吗?
简短的回答是你的回调最终会被调用。
对于长答案,让我们研究一下您的代码:
MongoClient mongoClient = MongoClients.create();
System.out.println("database has been connected!");
MongoClient
不会阻止在后台等待与 MongoDB 的连接,内部连接池正在尝试连接。从您的日志中我可以看到您的默认 serverSelectionTimeout
为 30000 毫秒。
下一步你做一个 println
立即输出所以 "database has been connected!" 不管怎样都会被打印出来。
最后,您调用了 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 =======");
现在使用锁存器 await()
直到回调被调用,现在我们应该看到以下两种情况之一发生:
没有MongoDB可用。
它最终会调用回调并打印出有错误。它将等到 serverSelectionTimeout
超时。
有一个 MongoDB 可用。
它最终会连接,对于每个数据库,它将应用 Block
并打印出数据库名称,然后最后它会调用回调信号它已完成。
我认为您每次都应该在 finally 子句中关闭 MongoClient 对象。我也遇到了同样的问题,当我在命令行中关闭连接时,我看到有很多连接是打开的。
尝试这样的事情(我使用 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) {
}
}
}
}
有了这个,我可以毫无问题地使用我的连接。
最近在用mongodbjava新发布的async驱动。我正在写一些简单的测试代码,它们是:
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);
但是没有调用回调函数,控制台输出为:
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
所以你可以看到没有调用回调函数。有人知道为什么吗?
简短的回答是你的回调最终会被调用。
对于长答案,让我们研究一下您的代码:
MongoClient mongoClient = MongoClients.create();
System.out.println("database has been connected!");
MongoClient
不会阻止在后台等待与 MongoDB 的连接,内部连接池正在尝试连接。从您的日志中我可以看到您的默认 serverSelectionTimeout
为 30000 毫秒。
下一步你做一个 println
立即输出所以 "database has been connected!" 不管怎样都会被打印出来。
最后,您调用了 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 =======");
现在使用锁存器 await()
直到回调被调用,现在我们应该看到以下两种情况之一发生:
没有MongoDB可用。 它最终会调用回调并打印出有错误。它将等到
serverSelectionTimeout
超时。有一个 MongoDB 可用。 它最终会连接,对于每个数据库,它将应用
Block
并打印出数据库名称,然后最后它会调用回调信号它已完成。
我认为您每次都应该在 finally 子句中关闭 MongoClient 对象。我也遇到了同样的问题,当我在命令行中关闭连接时,我看到有很多连接是打开的。
尝试这样的事情(我使用 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) {
}
}
}
}
有了这个,我可以毫无问题地使用我的连接。