Mongo打开了太多连接

Ank*_*kur 13 java connection mongodb mongo-java

我试图在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();
}
Run Code Online (Sandbox Code Playgroud)

在我的java控制台中,我收到此错误:

警告:使用0 java.net.SocketException确定maxBSON大小的异常:连接重置

并且mongodb给出了这个错误:

星期二十月二十五日22:31:39 [initandlisten]连接被拒绝,因为太多的开放连接:204中的204

处理这个问题最优雅的方法是什么?

Rem*_*iet 20

您正在为每个单独的操作创建Mongo类的实例.这不起作用,因为每个实例将创建并保持至少一个连接(但默认情况下为10),并且只有在Java GC清理Mongo实例或调用close()时才会删除这些连接.

问题是,在这两种情况下,即使使用单个线程,您创建它们的速度也比它们关闭的速度快.这将匆忙耗尽最大量的连接.正确的解决方法是使用单例模式保留一个Mongo实例(Mongo.Holder为此提供了功能,请尝试使用Mongo.Holder.connect(..)).快速"修复"是增加机器上的文件描述符限制,因此最大连接数量要高得多,但显然最终可能会达到相同的限制.您可以使用(在shell中)检查当前最大值:

db.serverStatus().connections
Run Code Online (Sandbox Code Playgroud)

TL; DR:将Mongo实例视为单例并使它们尽可能长寿,并且你是金色的.使用静态方法getInstance()实现一个MongoFactory,它返回一个延迟创建的实例就可以了.祝好运.