关于 servlet 应用程序中的连接池的一些问题

Posted

技术标签:

【中文标题】关于 servlet 应用程序中的连接池的一些问题【英文标题】:Some questions about connection pooling in a servlet application 【发布时间】:2014-03-20 01:30:04 【问题描述】:

我是 Java 新手,是 Web 应用程序设计方面的新手,我很惊讶有多少东西我现在不会。 特别是我在理解 servlet 容器如何管理连接池类等资源方面遇到了问题。

假设我选择了一个池库(比如 c3p0),我了解到有很多方法可以使用和管理连接池类。

例如,在许多示例中,我看到某个类(比如 ComboPooledDataSource)在 servlet 的 init() 方法中被实例化,这让我有点困惑。我的意思是,我认为连接池系统必须存在,并且对于需要连接的所有 servlet 具有独立的生命,否则它没有任何意义。所以我认为下面的类可能是一个线程,它从调用 init 方法的第一个 servlet 启动一次,然后它继续存在,直到有人不中断它。那是对的吗?如果不是,它是如何工作的?

无论如何,一旦我开始这个类,它是否在上下文中的所有 servlet 之间共享(我的意思是在 init 方法中调用它的所有 servlet)?

其他示例将连接池系统设置为资源,例如在 context.xml 中定义它,然后任何想要连接的 servlet 只需通过 JNDI 访问它(JNDI 是否正确?)。我的理解(或我认为)是,在这种情况下,将在应用程序启动时启动将执行池系统的线程,并且每个 servlet 都可以在需要时访问它。那是对的吗?

在这种情况下,我可以通过 servlet 或后台线程运行时修改连接池系统属性吗? (例如,如果我想根据请求数等统计信息更改连接数)

如果我想创建不同的池(例如,我想将数据库访问细分到 N 个不同的数据库,或者我想使用不同的用户名进行访问),我是否需要创建与我想要的不同类型的连接一样多的资源?

这两者之间是否有“更好”的方式或者它们是等效的?

【问题讨论】:

我认为您对object pool 的用途有点困惑,连接池通常没有线程 是的,那是因为我在问问题 始终使用您正在使用的应用程序服务器中内置的连接池。 感谢 Jarrod,但我为什么要这样做? Java servlets and database connection pooling的可能重复 【参考方案1】:

您是否使用 Tomcat 来运行您的 servlet? Tomcat 7 有一个新的池化解决方案,您可以对其进行研究。 Tomcat 还包括 dbcp 库,您可以通过设置 factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" 来使用它们。 DBCP 池是自我管理的,您可以在 context.xml 文件中定义配置值我不知道如何动态更改这些值。我相信 Tomcat 7 池使用与 DBCP 相同的配置,并添加了几个选项以使两者之间的转换变得简单。我们在所有应用程序中都使用 DBCP,并且没有遇到问题,所以我没有使用 Tomcat 7 池。我认为您需要创建许多池来满足您的大部分需求。

【讨论】:

是的,我是。我听说过,这是最可能的解决方案,但我想知道它是如何工作的。谢谢 ps。我读到了关于 dbcp 的坏事。人们建议使用 c3p0 或 tomcat 解决方案 dbcp 工作得很好,直到你能证明它没有。不要只接受你在网上读到的东西,有太多不实的东西四处流传。反正我从来没有遇到过任何问题。【参考方案2】:

归结为 webapp 和 (Tomcat) 服务器维护的易用性。 您描述了 2 个用例:

    一个 webapp 使用的连接池 webapps 之间共享的连接池

第一种情况适合“易用性”:您可以将 war-file 放在任何 Tomcat 服务器中,它会工作(例如 Jenkins 提供这样一个 war-file),因为 webapp 包含所需的所有代码访问数据库。无需更改 Tomcat 服务器的配置并重新启动它。 如果可以的话,我喜欢提供这类战争文件,因为出错的可能性较小(例如,不会与其他 web 应用程序的配置发生冲突)。您可以通过交付嵌入应用程序的 Tomcat 更进一步(因此您不需要 Tomcat 服务器一开始,示例项目是 here)。

请注意,打开数据库连接池(最好通过ServletContextListener.contextInitialized,而不是servlet)和关闭它(通过contextDestroyed)并不涉及启动和停止线程。池实现可以决定启动一个后台线程(例如,删除空闲和/或放弃的连接),但它不是必须的。

第二种情况适用于几个有共同点的 web 应用。例如,如果在同一个 Tomcat 服务器上运行的多个 webapps 都使用同一个数据库,那么如果 Tomcat 服务器已经有一个可用于不同 webapps 的连接池(通过 JNDI),则可以节省时间和精力。 Tomcat服务器可以在“lib”目录中包含JDBC驱动软件和连接池软件,并且在服务器的context.xml中配置一次。如果数据库发生变化或需要不同的(打补丁的)软件组件,只需要更新 tomcat 服务器,所有的 webapps 可以保持不变。在这种情况下,更新 Tomcat 服务器而不是每个 webapp 会容易得多。

第二种情况也更适合监控:很有可能你可以通过 JMX 监控连接池。这种监控在第一种情况下可能不可用。

连接池不需要更改“连接数作为请求数统计的函数”:您可以设置要使用的最大连接数和删除空闲连接的超时时间。然后连接池会随着请求的数量而增长和缩小。

细分对 N 个不同数据库的数据库访问将需要为每个数据库使用不同的连接池,除非这是“只读”,在这种情况下您也可以使用负载平衡器。

使用不同的用户名访问有点棘手。我读到另一个问题(我再也找不到了,抱歉)您可以在运行时更改架构,但更改用户名/密码可能需要一个新连接,在这种情况下连接池不可用。

【讨论】:

以上是关于关于 servlet 应用程序中的连接池的一些问题的主要内容,如果未能解决你的问题,请参考以下文章

关于sqlserve2000和sqlserver2005以后版本配置连接池的一些思路

关于Binder连接池的跨应用使用方法

关于JavaWeb项目中Servlet中无法创建数据库连接池问题

关于JavaWeb项目中Servlet中无法创建数据库连接池问题

聊聊 SQLAlchemy 连接池中的连接失效问题

java servlet在java servlet中配置数据库连接池的配置(在server.xml)