1

我们有一个 Web 应用程序,它使用 C3P0 来汇集我们的连接。我们将 C3P0 作为数据源注入到 JdbcTemplate 中。你可以在这里看到我们是如何做到的:

<bean id="dataSourceDev" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${databasedev.driver}" />
    <property name="jdbcUrl" value="${databasedev.url}"/>
    <property name="user" value="${databasedev.username}"/>
    <property name="password" value="${databasedev.password}"/>

    <property name="initialPoolSize" value="5" />
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="1000" />
    <property name="acquireIncrement" value="5" />
    <property name="maxStatements" value="1000" />
    <property name="maxStatementsPerConnection" value="1000"/>
    <property name="maxIdleTime" value="10800"/> <!-- 3 hours -->
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg>
         <ref bean="dataSourceDev" />
    </constructor-arg>
</bean>

<bean id="someDaoBean" class="com.gedi.platform.dao.SomeDaoClass">
    <property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

<bean id="someResourceClass" class="com.gedi.platform.SomeResourceClass">
    <property name="someDao" ref="someDaoBean" />
</bean>

您可以看到它是一个 Java EE Web 应用程序 - 它使用 Jetty 作为其应用程序服务器。我的问题是,Jetty 如何实例化我们的 bean,这将如何影响连接池?如果我们有几十个用户在不同时间使用网站,所有这些用户会被放在同一个连接池中吗?还是每个客户端只有一个连接池,每个 HTTP 客户端都会在其中创建 Resource、DAO、JdbcTemplate 和 C3P0 的新实例?

我说清楚了吗?我想要的是一个用于所有 HTTP 请求的连接池,无论它们来自来自波士顿还是新西兰的 Web 浏览器。这样,连接池就发挥了最大的作用。但是,如果为每个 HTTP 客户端都实例化了一个新的连接池,那么池化最终不会有太大的改进。

编辑

一个重要的花絮 - 我们使用 JAX-RS 的 Jersey 参考实现来生成 RESTful 接口。因此,我们的 servlet 通过 Jersey 分派请求,Jersey 会找到合适的资源类/方法来处理它们。我想知道 Jersey 是在每个请求上重新实例化这些类,还是始终保留它们的一个实例。

4

2 回答 2

1

泽西岛和码头都与这里无关。春天在这里很重要。在 Spring 中,每个 bean(比如你的dataSourceDev,jdbcTemplatesomeDaoBean)都是单例。这意味着当 Spring 应用程序上下文启动时,它将为它们中的每一个创建一个实例。

这意味着无论您使用什么DataSource(Web 请求、后台作业等),都使用相同的实例(因此使用相同的连接池)。你是对的,如果每个请求都创建连接池,那不会有太大的改进。实际上它会慢得多。

但是在您的情况下(这就是 99% 的 Web 应用程序的工作方式),所有需要数据库访问的代码都将竞争并重用相同的连接(或者如果没有可用的连接则等待)。顺便说一句,确保您的数据库实际上可以处理 1000 个并发连接。

于 2013-02-06T20:34:18.903 回答
1

Spring 创建beans并缓存它们,因此除非您将 bean 指定为prototype作用域(为每个请求创建一个新 bean),否则默认情况下所有 bean 都是单例的。码头不干涉。

当请求进入时,DispatcherServlet捕获请求并将其交给适当的处理程序。如果未将处理程序声明为 bean,则处理程序是同一个prototypebean。

您正确理解了连接池。这正是创建这个概念的原因。无论请求来自何处,在任何时间点与数据库的最大连接数都将是您在maxPoolSize属性中定义的连接数。

于 2013-02-06T20:36:51.950 回答