How to preinitialize DBCP connection pool on startup?

血红的双手。 提交于 2019-12-21 17:29:12

问题


The setup of my project is -

  1. Spring JDBC for persistence
  2. Apache DBCP 1.4 for connection pooling
  3. Mysql 5 on Linux

Here is the log of my application that captures the interactions with the database.

2013-01-29 15:52:21,549 DEBUG http-bio-8080-exec-3 org.springframework.jdbc.core.JdbcTemplate - Executing SQL query [SELECT id from emp]
2013-01-29 15:52:21,558 DEBUG http-bio-8080-exec-3 org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
2013-01-29 15:52:31,878  INFO http-bio-8080-exec-3 jdbc.connection - 1. Connection opened  org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
2013-01-29 15:52:31,878 DEBUG http-bio-8080-exec-3 jdbc.connection - open connections:  1 (1)
2013-01-29 15:52:31,895  INFO http-bio-8080-exec-3 jdbc.connection - 1. Connection closed  org.apache.commons.dbcp.DelegatingConnection.close(DelegatingConnection.java:247)
2013-01-29 15:52:31,895 DEBUG http-bio-8080-exec-3 jdbc.connection - open connections:  none
2013-01-29 15:52:41,950  INFO http-bio-8080-exec-3 jdbc.connection - 2. Connection opened  org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
2013-01-29 15:52:41,950 DEBUG http-bio-8080-exec-3 jdbc.connection - open connections:  2 (1)
2013-01-29 15:52:52,001  INFO http-bio-8080-exec-3 jdbc.connection - 3. Connection opened  org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
2013-01-29 15:52:52,002 DEBUG http-bio-8080-exec-3 jdbc.connection - open connections:  2 3 (2)
2013-01-29 15:53:02,058  INFO http-bio-8080-exec-3 jdbc.connection - 4. Connection opened  org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
2013-01-29 15:53:02,058 DEBUG http-bio-8080-exec-3 jdbc.connection - open connections:  2 3 4 (3)
2013-01-29 15:53:03,403 DEBUG http-bio-8080-exec-3 org.springframework.jdbc.core.BeanPropertyRowMapper - Mapping column 'id' to property 'id' of type int
2013-01-29 15:53:04,494 DEBUG http-bio-8080-exec-3 org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource

Two things are clear from the log -

  1. The connection pool only starts creating connections when the first request to execute a query is received.
  2. A pool of 4 connections takes nearly 30 seconds to initialize.

My questions are -

  1. How should one configure DBCP to initialize on startup automatically?
  2. Should it really take that long to create connections?

Note: Please don't suggest switching to C3P0 or Tomcat connection pool. I'm aware of those solutions. I'm more interested in understanding the problem at hand than just a quick fix. Besides I'm sure something so basic should be possible with DBCP as well.

Contents of dbcontext -

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.jdbc.url}" />
    <property name="username" value="${db.user}" />
    <property name="password" value="${db.password}" />
    <property name="maxActive" value="20" />
    <property name="initialSize" value="4" />
    <property name="testOnBorrow" value="true" />
    <property name="validationQuery" value="SELECT 1" />
</bean>

回答1:


The initialSize doesn't take effect until you first request a connection. From the java docs to BasicDataSource#setInitialSize

Sets the initial size of the connection pool.

Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is invoked: getConnection, setLogwriter, setLoginTimeout, getLoginTimeout, getLogWriter.

Try adding init-method="getLoginTimeout" to your bean to confirm this.




回答2:


For a web application, you can implement ServletContextListener.contextInitialized() method and fire a test query (e.g. Select ID From Emp Limit 1) using your DataAccess layer. This should initialize your connection pool and make it ready before your application starts serving real user from web.




回答3:


Have a look at the initialSize property -especially the part about when the pool is initialized. As sbridges points out, you can use the init-method property on beans to call one of the methods to trigger pool creation.

Also, you should look into why it takes 7.5 seconds on average to create a connection...

Cheers,



来源:https://stackoverflow.com/questions/14581201/how-to-preinitialize-dbcp-connection-pool-on-startup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!