简体   繁体   English

不活动期后连接超时问题

[英]Connection time out issues after inactivity period

We have an api which uses hibernate as ORM tool and we use c3p0 as the connection pool handler. 我们有一个使用hibernate作为ORM工具的api,我们使用c3p0作为连接池处理程序。 We have no problems when we are under load. 我们在负载下没有问题。 However, we are running out into "unable to obtain a connection" exceptions when the api has been inactive for a day or so. 但是,当api处于非活动状态一天左右时,我们正在用尽“无法获取连接”异常。 So, if no body uses the api over the weekend, we get connection errors on monday morning. 因此,如果周末没有人使用api,我们会在周一早上收到连接错误。

Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out. 引发者:java.sql.SQLException:客户端尝试签出Connection的尝试已超时。

We use mysql as the database. 我们使用mysql作为数据库。 On my research, i got to know that mySQL makes connections stale after 8 hours or so. 在我的研究中,我知道mySQL在8小时左右后连接失效。 It might be possible that the connection pool is giving out a stale connection to the client and hence the connection timeout exceptions for the client. 连接池可能会向客户端发出过时的连接,从而导致客户端的连接超时异常。

At present, we do not have any connection testing configured in C3Po. 目前,我们没有在C3Po中配置任何连接测试。 Lets say, if I use IdleTestPeriod to test the connection before they are given to the client by the pool. 可以说,如果我在池中将它们提供给客户端之前使用IdleTestPeriod来测试连接。 Then what happens if all my connections fail the test at a point of time? 那么如果我的所有连接在某个时间点都未通过测试会发生什么? Will those failed connections be removed from the pool and new active connections be generated again? 是否会从池中删除这些失败的连接并再次生成新的活动连接?

Currently, this is the c3p0 settings that we are using. 目前,这是我们正在使用的c3p0设置。 Any other reasons possible for this problem? 这个问题可能有其他原因吗?

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${----}"/>
        <property name="jdbcUrl" value="${----}"/>
        <property name="user" value="${----}"/>
        <property name="password" value="${------}"/>
        <property name="minPoolSize" value="5"/>
        <property name="acquireIncrement" value="5" />
        <property name="maxPoolSize" value="125" />
        <property name="maxStatements" value="10" />
        <property name="maxIdleTime" value="180" />
        <property name="maxIdleTimeExcessConnections" value="30" />
        <property name="checkoutTimeout" value="3000" />
        <property name="preferredTestQuery" value="SELECT 1" />
    </bean>

So you have a checkoutTimeout of 3 secs (3000 msecs) set. 所以你有一个3秒(3000毫秒)的checkoutTimeout。 That's the Exception you're seeing. 这就是你所看到的例外情况。 Clients are only permitted to wait for three seconds to checkout a Connection from the pool; 客户端只允许等待三秒钟从池中检出连接; if three seconds isn't enough, they see your Exception. 如果三秒钟还不够,他们会看到你的例外情况。

The question is, why are clients taking so long to get a Connection? 问题是,为什么客户需要这么长时间才能获得连接? Normally checking out a Connection is a pretty fast operation. 通常检查一个连接是一个非常快速的操作。 But if all Connections are checked out, then clients have to wait for (slow) Connection acquisition from the database. 但是如果检出所有连接,则客户端必须等待(缓慢)从数据库获取连接。

You have your pool configured to pretty aggressively cull Connections. 您已将池配置为非常积极地剔除连接。 Any number of Connections above minPoolSize=5 will be destroyed if they are idle for more than maxIdleTimeExcessConnections=30 seconds. minPoolSize = 5以上的任何数量的连接如果空闲超过maxIdleTimeExcessConnections = 30秒,将被销毁。 Yet your pool is configured for large-scale bursts: maxPoolSize=125. 然而,您的池配置为大规模突发:maxPoolSize = 125。 Suppose that your app is quiet for a while, and then gets a burst of Connection requests from clients. 假设您的应用程序安静了一段时间,然后从客户端获取一连串请求。 The pool will quickly run out of Connections and start to acquire, in bursts of acquireIncrement=5. 池将快速耗尽连接并开始获取,以winsIncrement = 5的突发。 But if there are suddenly 25 clients and the pool has only 5 Connections, it's not improbable that the 25th client might time out before acquiring a Connection. 但是如果突然有25个客户端并且池只有5个连接,那么第25个客户端在获取连接之前可能会超时是不可能的。

There's lots you can do. 你可以做很多事情。 These tweaks are separable, you can mix or match as you see fit. 这些调整是可分离的,您可以根据需要混合或匹配。

  1. Cull idle "excess" Connections less aggressively, so that in general, your pool has some capacity to service bursts of requests. 剔除空闲的“多余”连接不那么积极,因此通常,您的池有一定的容量来服务突发请求。 You might drop maxIdleTimeExcessConnections entirely, and let Connections slowly wither after maxIdleTime=180 seconds of disuse. 您可能完全丢弃maxIdleTimeExcessConnections,并且在maxIdleTime = 180秒不使用后让Connections慢慢消失。 (Downside? A larger resource footprint for longer during periods of inactivity.) (下行?在不活动期间更长的资源占用时间。)

  2. Set minPoolSize to a higher value, so that it's unlikely that the pool will see a burst of activity for which it has way too few Connections. 将minPoolSize设置为更高的值,以便池不太可能看到一连串的活动,其连接的连接太少。 (Downside? Larger permanent resource footprint.) (下行?更大的永久资源足迹。)

  3. Drop checkoutTimeout from your config. 从配置中删除checkoutTimeout。 c3p0's default is to allow clients to wait indefinitely for a Connection. c3p0的默认设置是允许客户端无限期地等待连接。 (Downside? Maybe you prefer clients to quickly report a failure rather than wait for possible success.) (下行?也许你更喜欢客户快速报告失败而不是等待可能的成功。)

I don't think that the problem that you are observing has much to do with Connection testing or MySQL timeouts per se, but that doesn't mean you should not deal with those issues. 我不认为您所观察到的问题与连接测试或MySQL超时本身有很大关系,但这并不意味着您不应该处理这些问题。 I'll defer to nobeh's advice on the MySQL reconnect issue. 我将遵循nobeh关于MySQL重新连接问题的建议。 (I'm not a big MySQL user.) You should consider implementing Connection testing. (我不是一个很大的MySQL用户。)你应该考虑实现连接测试。 You have a preferredTestQuery, so tests should be reasonably fast. 你有一个preferredTestQuery,所以测试应该相当快。 My usual choice is to use testConnectionOnCheckin and idleConnectionTestPeriod. 我通常的选择是使用testConnectionOnCheckin和idleConnectionTestPeriod。 See http://www.mchange.com/projects/c3p0/#configuring_connection_testing 请参阅http://www.mchange.com/projects/c3p0/#configuring_connection_testing

Good luck! 祝好运!

In the section of High availability and clustering in MySQL Java Connector , take a look at the properties; MySQL Java Connector高可用性和集群部分中,查看属性; specifically autoReconnect and autoReconnetForPools . 特别是autoReconnectautoReconnetForPools Use the properties in your JDBC connection URL. 使用JDBC连接URL中的属性。 They have helped me before when using MySQL, Hibernate, and C3P0. 在使用MySQL,Hibernate和C3P0之前,他们帮助了我。 Hope that this helps. 希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM