2016-04-24 69 views
1

我遇到了我的MongoDB Java驱动程序3.0版的问题。在对几个集合(updateOne,find)执行几个操作之后,我得到一个Command failed with error 8: '24: Too many open files'错误。我在我的代码oftenly执行的典型操作是下列之一:MongoDB Java API 3.0关闭游标

private Document findFirst(int i) { 
    FindIterable<Document> cursor = collection.find(new Document("_id", i)).limit(1); 
    Document exists = null; 
    for (Document doc : cursor) { 
     exists = doc; 
     break; 
    } 
    return exists; 
} 

Document exists = findFirst(integer); 
return exists != null ? new MongoDBDocument(collection,exists) : null; 

,当我查找了的ID,“会话”未关闭:

Set<Integer> s = new HashSet<>(); 
for (Document k : collection.find().projection(new Document("_id",1))) { //Fully scan the collection 
    s.add(Integer.valueOf((String)k.get("_id"))); 
} 
return s; 

于是,我看到了在老版API中,查找操作的结果返回了必须关闭的DBCursor。在我看来,在当前的实现中,没有光标被关闭。我看到要实现这个功能的唯一方法是每次关闭MongoClient,但最有可能的是我没有以正确的方式完成任何事情。也许,当我用db.getCollection(name)检索集合时,必须在对它进行一些操作后以某种方式关闭它:我尝试阅读文档,但没有任何帮助。

服务器的日志返回详细的错误是以下之一:

2016-04-24T13:20:32.839+0200 E STORAGE [conn721] WiredTiger (24) [1461496832:839907][968:0x700000934000], WT_SESSION.create: /data/db/index-1232-7182838846905439482.wt: Too many open files 
2016-04-24T13:20:32.840+0200 I COMMAND [conn721] command alledges.$cmd command: createIndexes { createIndexes: "2071853587", indexes: [ { key: { _id: 2071853587 }, name: "_id_2071853587", ns: "alledges.2071853587" } ] } keyUpdates:0 writeConflicts:0 exception: 24: Too many open files code:8 numYields:0 reslen:83 locks:{ Global: { acquireCount: { r: 1, w: 1 } }, Database: { acquireCount: { W: 1 } } } protocol:op_query 539ms 

我在哪里错了?提前致谢。

回答

0

问题是目前的WiredTiger实施。使用此配置运行服务器可解决此问题:

mongodb --storageEngine mmapv1 
1

此错误通常与具有太多打开的文件描述符有关。请参阅ulimit references以查看和推荐设置。您还需要检查过程本身的限制(不一定是您的系统范围设置)。请参阅proc-file-system

关于WiredTiger,有一个“扫描”线程可以定期关闭空闲了一段时间的开放表。由于扫描线程基于空闲时间而不是打开文件描述符的数量,因此WiredTiger将不会响应在特定时间打开大量文件。

另一件要检查的是如何利用MongoClient实例。请注意,MongoClient透明地执行连接池,并且通常每个JVM进程只应有一个实例。如果你大量创建这个类的实例,你可能会获得太多的连接,然后才能释放(空闲连接)。

关于游标,虽然服务器最终会超时,但自己关闭游标会更有效率。特别是如果光标未完全耗尽且不再需要。举一个例子,你可以关闭光标:

MongoCursor<Document> cursor = collection.find().iterator(); 
try { 
    while (cursor.hasNext()) { 
     System.out.println(cursor.next().toJson()); 
    } 
} finally { 
    cursor.close(); 
} 

对于一个额外的小费,你还可以利用.first(),以取代findFirst()方法,例如:

FindIterable<Document> cursor = collection.find(new Document("_id", i); 
return cursor.first()!=null;