应用程序停留在从c3p0检索连接?

时间:2013-09-19 03:52:00

标签: c3p0

我们最近发生了一次中断事件,其中应用程序线程在从c3p0检索连接时卡住了。配置集如下:

使用的c3p0版本:0.9.1.2

  • c3p0.acquireRetryDelay = 10000;
  • c3p0.acquireRetryAttempts = 0;
  • c3p0.breakAfterAcquireFailure = false;
  • c3p0.numHelperThreads = 8;
  • c3p0.idleConnectionTestPeriod = 3;
  • c3p0.preferredTestQuery =“从双重选择1”;
  • c3p0.checkoutTimeout = 3000;
  • c3p0.user =“XYZ”; //在发布
  • 时更改为XYZ
  • c3p0.password =“XYZ”; //发布时更改为XYZ

在正常情况下,一切正常,c3p0一直在为我们服务。但是,在最近的网络事件(网络分区 - 应用程序主机无法与数据库通信)中,我们看到应用程序无限期地试图从c3p0获取连接。

在日志中看到的Stacktrace:

Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:527)
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
    at amazon.identity.connection.WrappedDataSource.getConnectionWithOptionalCredentials(WrappedDataSource.java:42)
    at amazon.identity.connection.LoggingDataSource.getConnectionWithOptionalCredentials(LoggingDataSource.java:55)
    at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
    at amazon.identity.connection.WrappedDataSource.getConnectionWithOptionalCredentials(WrappedDataSource.java:42)
    at amazon.identity.connection.ConnectionProfilingDataSource.profileGetConnectionWithOptionalCredentials(ConnectionProfilingDataSource.java:118)
    at amazon.identity.connection.ConnectionProfilingDataSource.getConnectionWithOptionalCredentials(ConnectionProfilingDataSource.java:99)
    at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
    at amazon.identity.connection.CallCountTrackingDataSource.getConnectionWithOptionalCredentials(CallCountTrackingDataSource.java:82)
    at amazon.identity.connection.WrappedDataSource.getConnection(WrappedDataSource.java:30)
    at com.amazon.jdbc.FailoverDataSource.doGetConnection(FailoverDataSource.java:133)
    at com.amazon.jdbc.FailoverDataSource.getConnection(FailoverDataSource.java:109)
    at com.amazon.identity.accessmanager.WrappedConnection$1.call(WrappedConnection.java:84)
    at com.amazon.identity.accessmanager.WrappedConnection$1.call(WrappedConnection.java:82)
    at com.amazon.identity.accessmanager.WrappedConnection.getConnection(WrappedConnection.java:110)
    ... 40 more
    Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@185e5c6b -- timeout at
 awaitAvailable()
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1317)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:584)
....... (total of 317 such instances of prelimCheckoutResource):

我从c3p0 documentation

中提取的一些摘录

当c3p0数据源尝试并且无法获取连接时,它将重试到acquireRetryAttempts次,每次尝试之间都会延迟acquireRetryDelay。如果所有尝试都失败,则从DataSource等待Connections的任何客户端都将看到异常,指示无法获取Connection。请注意,在完整的尝试失败之前,客户端看不到任何异常,这可能是在初始连接尝试之后的某个时间。 如果acquireRetryAttempts设置为0,则c3p0将尝试无限期地获取新的Connections,并且对getConnection()的调用可能会无限期地阻止等待成功获取

checkoutTimeout限制客户端等待连接的时间长度,如果所有连接都已签出且无法立即提供

所以这是关于为什么会发生这种情况的理论:

网络分区存在几分钟。我假设到那时,空闲连接测试会使池中的所有活动连接无效。这意味着c3p0现在将参与获取新连接。如果任何应用程序主机尝试从池获取连接,则必须无限期地等待,直到获取连接为止(请参阅c3p0文档的摘录)。此外,checkout超时参数在这种情况下也没有帮助,因为只有在检出所有连接时才执行超时(事实并非如此)。

我的问题如下:

  1. 我对系统的理解是否正确?
  2. 如果是,应该checkoutTimeout(或其他一些参数存在)会超时这样的应用程序连接请求而不是永久挂起?
  3. 如果有更好的方法来配置c3p0以避免再次面临此问题。我可以尝试包装从c3p0强制超时(基于线程的超时)获取连接,但如果可能有更好的c3p0配置或应用c3p0补丁,这是我想要避免的。
  4. 谢谢

2 个答案:

答案 0 :(得分:2)

  

网络分区存在几分钟。我假设到那时,空闲连接测试会使池中的所有活动连接无效。这意味着c3p0现在将参与获取新连接。如果任何应用程序主机尝试从池获取连接,则必须无限期地等待,直到获取连接为止(请参阅c3p0文档的摘录)。

  1. 这是不正确的。 checkoutTimeout 应该控制这种情况以及系统过载的情况(池被最大化并且使用了所有连接)。
  2.   

    在这种情况下,checkout timeout参数也没有帮助,因为只有在检出所有连接时才会强制执行超时(事实并非如此)。

    1. 根据c3p0文档:在结账时#34;强制执行此超时,而不是在已经签出连接时。所以它应该对你有帮助。

    2. checkoutTimeout 可以帮助您解决客户端超时问题,因此无需执行任何其他操作;但是我会说尝试无限期地获得连接是一个错误。我实际上使用默认的30 x 1000 ms = 30秒超时。

    3. 我还会说checkoutTimeout应该大于或等于aquire timeout(acquireRetryAttempts * acquireRetryDelay),否则第二个将适用。

答案 1 :(得分:0)

根据文档,这就是问题所在。

c3p0.acquireRetryAttempts = 0;

如果acquireRetryAttempts 为0,则C3P0 会在失败时不断尝试获取连接,每次迭代都等待10 秒(如您所配置)。

将acquireRetryAttempts 更改为一个有限值,例如10,您的等待时间将在100 秒左右,然后出现异常。