2016-04-24 70 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;