简体   繁体   English

Tomcat JDBC连接池:testOnBorrow vs testWhileIdle

[英]Tomcat JDBC Connection Pool: testOnBorrow vs testWhileIdle

For various reasons connections in a pool can become invalid: server connection timeout, network issues... 由于各种原因,池中的连接可能变为无效:服务器连接超时,网络问题......

My understanding is that a Tomcat JDBC Connection Pool does not provide any guaranty about the validity of the connections it provides to the application. 我的理解是Tomcat JDBC连接池不保证它为应用程序提供的连接的有效性。

To prevent (actually only lower the risk) getting an invalid connection from the pool a solution seems to be the configuration of connections validation. 为了防止(实际上只降低风险)从池中获得无效连接,解决方案似乎是连接验证的配置。 Validating a connection means to run a very basic query on the database (eg SELECT 1; on MySQL). 验证连接意味着在数据库上运行非常基本的查询(例如SELECT 1;在MySQL上)。

Tomcat JDBC Connection Pool offers several options to test the connection. Tomcat JDBC连接池提供了几个测试连接的选项。 The two I find the more interesting are testOnBorrow and testWhileIdle . 我发现两个更有趣的是testOnBorrowtestWhileIdle

First I was thinking that testOnBorrow is the best option because it basically validate the connection before providing it to the application (with a max frequency defined by validationInterval ). 首先,我认为testOnBorrow是最好的选择,因为它在将连接提供给应用程序之前基本上验证了连接(具有由validationInterval定义的最大频率)。

But after a second though I realized that testing the connection right before using it might impact the responsiveness of the application. 但是经过一秒钟后我才意识到在使用它之前测试连接可能会影响应用程序的响应能力。 So I though that using testWhileIdle can be more efficient as it test connections while they are not used. 所以我虽然使用testWhileIdle可以更高效,因为它在不使用时测试连接。

No matter which option I choose it seems that they only lower the risk from getting an invalid connection but this risk still exist. 无论我选择哪个选项,它们似乎只会降低获得无效连接的风险,但这种风险仍然存在。

So I end up asking: should I use testOnBorrow or testWhileIdle or a mix of both? 所以我最后问:我应该使用testOnBorrow还是testWhileIdle或两者兼而有之?

On a side note, I'm surprised that validationInterval does not apply to testOnReturn and I don't really get the purpose of testOnConnect . 另外,我很惊讶validationInterval不适用于testOnReturn而且我没有真正达到testOnConnect的目的。

There is no 100% right answer to this. 这没有100%正确的答案。 It is a matter of trade-off and context. 这是一个权衡和背景的问题。

  • Most of the times, testOnBorrow is the least risky since it ensures (as best it can) that before a connection is returned from the pool for your use, a basic sanity check has been made that the client and db-server are on talking terms. 大多数情况下, testOnBorrow风险最小,因为它确保(尽可能最好)在从池中返回连接供您使用之前,已经进行了基本的健全性检查,客户端和数据库服务器正在谈论条款。
  • It still doesn't prevent the race condition of the server connection going down, between the time 'the sanity check' was made & the time your application used the connection. 它仍然不能防止服务器连接的竞争状态下降,在“完整性检查”和应用程序使用连接的时间之间。
  • But considering this as a corner-case, the testOnBorrow gives pretty good assurance. 但考虑到这是一个角落案例, testOnBorrow给出了相当不错的保证。

  • Now the trade-off with that is that, every time you request a connection, a query (no matter how light-weight) is made to the database-server. 现在需要权衡的是,每次请求连接时,都会对数据库服务器进行查询(无论多么轻量级)。 This maybe very fast, but the cost is still not zero. 这可能非常快,但成本仍然不是零。

And if you have a busy application, with very good database-connection-reliability, then you'll start seeing from the data, that the COST of "validity check on every connection-request from the pool" outweighs the benefits of detecting connection issues. 如果你有一个繁忙的应用程序,具有非常好的数据库连接可靠性,那么你将从数据开始看到,“对来自池的每个连接请求的有效性检查”的成本超过检测连接问题的好处。

  • On the other hand, if your application is not uniformly busy (like most real-world applications) then it is extremely beneficial to have the testOnBorrow option. 另一方面,如果您的应用程序不是一成不变的 (就像大多数真实应用程序一样),那么拥有testOnBorrow选项是非常有益的。
  • It ensures to the max, that you have a good connection before you use it. 它确保最大化,您在使用之前有良好的连接。 Especially considering the cost (retry + manual intervention + loss of workflow etc.) of "not being able to recover easily" from a failed DB operation. 特别是考虑到失败的DB操作的“无法轻松恢复”的成本(重试+手动干预+工作流程丢失等)。

  • Now imagine if you have the testOnIdle option. 现在想象一下,如果你有testOnIdle选项。 This requires that your connections go idle (dependent on the idle timeout of the connection) before a sanity check can be made. 这需要您的连接在进行健全性检查之前空闲(取决于连接的空闲超时)。

  • This is a performance improvement over testOnBorrow but it comes with its own disadvantages. 这是testOnBorrow的性能改进,但它有其自身的缺点。
    • Real world app-to-db-connections are not just idle-timeout-based breakage, they can be dropped based on firewall rules, n/w congestion, db-server-undergoing maintenance/patching etc. 真实世界的app-to-db-connections不仅仅是基于空闲超时的破坏,它们可以根据防火墙规则,n / w拥塞,db-server-正在进行维护/修补等而被删除。
    • So it goes back to the data-measurement of how many connection errors were observed in the data, when you did not have any sort of "connection validation". 因此,当您没有任何类型的“连接验证”时,它可以追溯到数据中观察到的连接错误数量的数据测量。
  • And one thing to watch out with this option is when you have your pool working the best with max connections and your app performing well, and for some reason if your db-server undergoes a restart or likewise. 使用此选项需要注意的一件事是,当您使用最大连接并且您的应用程序运行良好时,您的池工作效果最佳,并且出于某种原因,如果您的数据库服务器重启或同样如此。 All the live connections (from a client perspective) will now mostly error out, till the idle timeout kicks-off. 现在所有的实时连接(从客户端的角度来看)都会出错,直到空闲超时开始。 So your db-issue (which would have been a fire-fight) is now compounded a bit, till the app connections get well again or you restart the app as well. 所以你的db-issue(这本来就是一场激烈的争夺)现在有点复杂,直到应用程序连接恢复正常或你重启应用程序。

And one last data point is that for some applications, the critical-path is not the "validation query" time (in lower millis hopefully). 最后一个数据点是,对于某些应用程序,关键路径不是“验证查询”时间(希望以较低的毫秒数)。 The applications have bigger issues to deal with. 应用程序有更大的问题需要处理。 And of course, for some applications, that time is very significant. 当然,对于某些应用来说,那个时间非常重要。

Just to let you know, I have just tested this and it is possible to use both testOnBorrow and testOnIdle properties. 只是为了让您知道,我刚刚对此进行了测试,并且可以同时使用testOnBorrowtestOnIdle属性。

As mentioned above, however, I will be opting to testOnBorrow uniquely due to the fact that my application is not under heavy traffic and can afford to validate a connection before taking hold of it. 然而,如上所述,我将选择testOnBorrow唯一,因为我的应用程序没有大量流量,并且能够承担在连接之前验证连接。

As pointed out in comments, testOnBorrow does not require a validation query. 正如评论中指出的那样, testOnBorrow不需要验证查询。 If you do choose to keep one it can be a simple select: 如果你确实选择保留一个它可以是一个简单的选择:

jdbc.hive.testOnBorrow=true
jdbc.hive.validationQuery=SELECT 1

If you wish to use testWhileIdle , you can use the following: 如果您希望使用testWhileIdle ,则可以使用以下命令:

jdbc.testWhileIdle=true
jdbc.minEvictableIdleTimeMillis=1800000
jdbc.timeBetweenEvictionRunsMillis=1800000`

More info on DBCP: https://commons.apache.org/proper/commons-dbcp/configuration.html 有关DBCP的更多信息: https//commons.apache.org/proper/commons-dbcp/configuration.html

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

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