我试图在Java循环中向MongoDB写入大量数据。我根据打开的连接数得到错误。
我的理论是,由于MongoDB不是事务性的,因此可以同时打开许多连接。然而,Java代码也能够非常快地循环,在一定时间之后,循环迭代的次数开始超过可用连接的数量并且Mongo碰到了墙。
我的代码看起来像这样。我已经看到它建议不要m.close()
但是你只是更快地得到错误。
public static void upsert(){
Mongo m = null;
DB db = null;
try {
m = new Mongo("localhost");
db = m.getDB("sempedia"); } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (MongoException e1) { e1.printStackTrace(); }
// create documents
// I am doing an upsert - hence the doc, doc
DBCollection triples;
try {
triples = db.getCollection("triples");
triples.update(doc,doc,true,false);
} catch (MongoException e) { e.printStackTrace(); }
m.close();
}
在我的java控制台中,我收到此错误:
警告:使用0确定maxBSON大小的异常 java.net.SocketException:连接重置
mongodb给出了这个错误:
10月25日星期二22:31:39 [initandlisten]连接被拒绝了 许多开放的联系:204 of 204
处理这个问题最优雅的方法是什么?
答案 0 :(得分:20)
您正在为每个单独的操作创建Mongo类的实例。这不起作用,因为每个实例将创建并保持至少一个连接(但默认情况下为10),并且只有在Java GC清理Mongo实例或调用close()时才会删除这些连接。
问题在于,在这两种情况下,即使使用单个线程,您创建它们的速度也比它们关闭的速度快。这将匆忙耗尽最大量的连接。正确的解决方法是使用单例模式保留一个Mongo实例(Mongo.Holder为此提供了功能,请尝试使用Mongo.Holder.connect(..))。快速“修复”是增加机器上的文件描述符限制,因此最大连接数量要高得多,但显然最终可能会达到相同的限制。您可以使用(在shell中)检查当前最大值:
db.serverStatus().connections
TL; DR:将一个Mongo实例视为一个单例并使它们尽可能长寿,你就是金色的。使用静态方法getInstance()实现一个MongoFactory,它返回一个延迟创建的实例就可以了。祝你好运。
答案 1 :(得分:4)
每次通过您的方法时,您都会制作一个新的MongoClient。
我也有这个问题,但是我解决了它制作checkConnection功能:
private static DBCollection checkConnection(String collection) throws UnknownHostException{
if(db == null){
db = (new MongoClient(host, port)).getDB(database);
}
return db.getCollection(collection);
}
在您实例化变量的顶部,请执行以下操作:
private static DB db = null;
private static String database = "<Your database>";
private static String host = "localhost"; //<--- usually localhost
private static int port = 27017; //<---- usually 27017, but you can change it.
然后当您制作方法时,请按照以下方式进行操作:
public <whatever> someFunction() throws UnknownHostException{
DBCollection dbCollection = checkConnection("triples"); //<--- can be "triples"
//or whatever collection you want
<REST OF YOUR FUNCTION HERE USING THE AMAZING COLLECTION
}
这种方法有一些优势:
- Code reusability, you won't have to write the same thing at every method
- Readability, which programmer doesn't understand this:
DBCollection dbCollection = checkConnection("triples");
- ONLY ONE CONNECTION WHICH YOU RE-USE (this doesn't affect data not being synced)
希望我帮助