【问题标题】:ServletContext attributes and static propertiesServletContext 属性和静态属性
【发布时间】:2013-05-16 16:25:35
【问题描述】:

所以,我正在尝试建立一个在应用程序的多次使用(页面访问)中保持持久的 Mongo 连接。我厌倦了在测试期间建立的所有这些连接,我想通过拥有那个单一的持久连接来使用正确的程序。最佳实践等等。

这是我所拥有的:

web.xml

<listener>
    <listener-class>com.core.tools.MyServletContextListener</listener-class>
</listener>

com.core.tools.MyServletContextListener

public class MyServletContextListener implements ServletContextListener {
    private static Logger log = org.apache.log4j.Logger.getLogger(MyServletContextListener.class);
    public void contextInitialized( ServletContextEvent sce ){
        try {
            EntityManager.setupMongoClient(sce);
        } catch (UnknownHostException e) {
            log.error("Error setting up Servlet Context");
        }
    }

    public void contextDestroyed( ServletContextEvent sce ){
        EntityManager.closeMongoClient(sce);
    }
}

实体管理器

public class EntityManager {
    private static MongoClient      mongoConnection = null;
    private static Jongo            jongoDatasource = null;

    public static void setupMongoClient( ServletContextEvent sce ) throws UnknownHostException{
        if( sce.getServletContext().getAttribute("mongo") == null ){
            mongoConnection = new MongoClient("localhost");
            sce.getServletContext().setAttribute("mongo", mongoConnection );
        }else if (mongoConnection == null) {
            mongoConnection = (MongoClient) sce.getServletContext().getAttribute("mongo");
        }
    }

    public static Jongo getJongoDatasource(){
        if( jongoDatasource == null ){
            jongoDatasource = new Jongo(mongoConnection.getDB("coreTest"));
        }
        return jongoDatasource;
    }

    public static void closeMongoClient( ServletContextEvent sce ){
        if( sce.getServletContext().getAttribute("mongo") != null ){
            mongoConnection = (MongoClient) sce.getServletContext().getAttribute("mongo");
            mongoConnection.close();
        }
    }
}

会发生什么:

好消息 - 现在我的连接会在服务器关闭时得到清理。

坏消息 - 我仍然不断获得大量的连接被创建。每次我按下按钮时,它都会建立一个新的连接……但只有大约 4 或 5 个连接。然后它突然停止添加新连接一段时间。然后它会再增加3个。然后等待。然后另一个2。然后什么都没有。然后几分钟后,它突然又增加了 5 个连接。

令人困惑:我什至不知道它是如何建立这些连接的。跟踪方法调用 - setupMongoClient 仅调用一次 - 当 apache 服务器启动时。它是整个系统中唯一设置mongoConnection的地方。

每当我按下按钮时,mongoConnection 都不会被设置。然而,数据是从 mongo 数据库中提取的,测试 mongoConnection 显示它不为空。

mongoConnection 怎么不为空?为什么偶尔会建立新的联系?

【问题讨论】:

    标签: java mongodb servlet-listeners


    【解决方案1】:

    MongoClient 是一个连接池;它维护许多与数据库的开放连接以提高性能(创建新连接的成本很高)。

    当您调用 mongoConnection.getDB("DB") 时,MongoClient 将从连接池中检索数据库连接。如果连接池中没有可用的连接,它将创建一个新连接并将其添加到池中。

    当您调用 mongoConnection.close() 时,连接不会断开。它只是简单地返回到连接池以供重用。

    默认情况下,池大小为 5。这解释了为什么即使您关闭了它们,最终仍会有 5 个打开的连接(请记住,“关闭”的连接会返回到池中)。你可以改变这个尺寸

    【讨论】:

    • 人力资源部。 (返回并查看历史记录)我一次打开了多达 11 个连接......我在哪里可以找到池大小设置的值?它们并非同时生成,它们具有那种零星的模式。 mongoConnection.close() 只调用一次 - 当 apache 关闭时。然后所有这些额外的连接都消失了。我应该更频繁地关门吗?
    • 另外 - 关于其他问题的任何想法?为什么mongoConnection 不为空?我很高兴它可以工作......但我只是在运行一个本不应该工作的测试。并且当它发生时感到惊讶。我很想知道为什么。
    • 有一个 MongoClient 构造函数,它有一个 MongoClientOptions 作为第二个参数。您可以在选项中设置connectionsPerHost。您应该在使用后立即关闭连接,而不仅仅是在关机期间。我不确定你是如何达到 11 个并发连接的。
    • 我没有在您的代码中看到您将 mongoConnection 设置为 null。它是一个静态变量,所以它会保持它的值,直到重新赋值。
    • 即使您再次运行该程序第二次、第三次、第十五次或第 73 次?我没有意识到这一点。谢谢!
    猜你喜欢
    • 2013-01-14
    • 2018-04-18
    • 2011-04-16
    • 1970-01-01
    • 2011-06-11
    • 2021-07-22
    • 2016-10-10
    • 2013-03-28
    相关资源
    最近更新 更多