2

我在 Java servlet 上使用 Mongo DB 时遇到问题。

我的 servlet 有许多方法(~20)可以访问数据库以检索和添加数据。一个非常简短的例子:

public static String getSomething(String s) {
  String json = "[]";
  JSONArray jsonArray = new JSONArray();
  DBCollection table;

  try {
    Mongo mongo = new Mongo("localhost", 27017);
    DB db = mongo.getDB( "myDb" );  
        BasicDBObject quoteQuery = new BasicDBObject("abc", abc);
    DBCursor cursor = table.find(quoteQuery);

    try {
      while(cursor.hasNext()) {
        jsonArray.put(cursor.next());
      }
    } finally {
      cursor.close();
    }

// ...

现在的问题是,当这个 Java servlet 部署在 linux 服务器中时,它可以正常工作 10 天左右。

之后它崩溃了。

当我转到 var/log 目录中的 mongodb.log 时,我得到以下重复输出:

“连接被拒绝,因为打开的连接太多”

我不确定现在在哪里编辑或如何处理。我试图增加服务器中打开连接的限制,但仍然有相同的结果。

有什么建议么?

4

6 回答 6

11

来自 API 文档:http ://api.mongodb.org/java/2.11.3/

公共类 Mongo 扩展对象

具有内部连接池的数据库连接。对于大多数应用程序,您应该为整个 JVM 拥有一个 Mongo 实例

于 2013-09-13T11:30:58.520 回答
3

您应该非常谨慎地创建 Mongo 对象,理想情况下,任何时候每个类加载器甚至只创建一个。要减少 Mongo 对象的数量,您可以在 servlet 的 init 方法中创建它,并在每次调用时重用该实例。

编辑:刚刚查看了我们的代码,我们使用经典的单例类管理 Mongo 实例(并且始终Mongo使用该类的getInstance()方法获取一个),因为如果您的应用程序中有多个 servlet / 入口点,仅使用init()仍然会为每个 servlet 生成一个实例,并且仍然不能满足@FredClose 引用的手册部分

于 2013-09-13T11:29:28.943 回答
1

您可以创建一次 mongo 对象,而不是在每次 getSomething 调用时创建它。

public SomeClass{
static Mongo mongo = new Mongo("localhost", 27017);
static DB db = mongo.getDB( "myDb" );  

public static String getSomething(String s) {
String json = "[]";
JSONArray jsonArray = new JSONArray();
DBCollection table;
try {

BasicDBObject quoteQuery = new BasicDBObject("abc", abc);
DBCursor cursor = table.find(quoteQuery);

while(cursor.hasNext()) {
  jsonArray.put(cursor.next());

}

}

实际上,理想的情况是根本不使用静态访问并从中央控制器注入数据库对象。

于 2013-09-13T11:31:42.520 回答
1

您正在 MongoDB 中创建连接,但您没有关闭连接。对于任何数据库来说,关闭一个连接是非常重要的,否则它会达到它的最大限制,你将无法正常执行你的程序。我希望以下代码会有所帮助:

        public static String getSomething(String s) {
    String json = "[]";
    JSONArray jsonArray = new JSONArray();

    try {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        DB db = mongoClient.getDB("myDb");
        DBCollection collection = db.getCollection("NAME OF YOUR COLLECTION");
        BasicDBObject quoteQuery = new BasicDBObject("abc", "VARIABLE THAT YOU WANT TO FIND");

        DBCursor cursor = collection.find(quoteQuery);
        try {
            while (cursor.hasNext()) {
                jsonArray.put(cursor.next());
            }
        } finally {
            cursor.close();
        }
        mongoClient.close();
    } catch (Exception e) {
    }
    return jsonArray.toString();
}

在此代码中,“MongoClient”在其目的结束后关闭。

于 2013-09-13T11:50:53.693 回答
0

阿伦·古普塔‏@arungupta

新示例展示了如何在 #JavaEE7 应用程序中使用 Mongo:新示例展示了 Mongo 在 Java EE 应用程序中的基本用法

于 2013-10-01T08:28:49.077 回答
-1

根据上述问题,就像您为每个请求创建 Mongo 对象一样。我建议在整个应用程序中使用单个对象。为此,您可以找到“MongoClient 和连接池”。MongoClient 将自动为您处理连接池。

mongoClient = new MongoClient(URI, connectionOptions);

这里的 mongoClient 对象包含您的连接池,并将根据需要为您的应用程序提供连接。您应该努力在应用程序初始化时创建一次该对象,并在整个应用程序中重新使用该对象与数据库通信。我们看到的最常见的连接池问题源于应用程序过于频繁地创建 MongoClient 对象,有时是在每个数据库请求上。如果您这样做,您将不会使用您的连接池,因为每个 MongoClient 对象都维护一个单独的池,您的应用程序不会重用该池。

于 2016-02-16T06:14:57.750 回答