【问题标题】:Tomcat JDBC Connection Pool: testOnBorrow vs testWhileIdleTomcat JDBC 连接池:testOnBorrow 与 testWhileIdle
【发布时间】:2017-06-19 07:18:27
【问题描述】:

由于各种原因,池中的连接可能会失效:服务器连接超时、网络问题...

我的理解是,Tomcat JDBC 连接池不保证它提供给应用程序的连接的有效性。

为了防止(实际上只是降低风险)从池中获取无效连接,解决方案似乎是连接验证的配置。验证连接意味着在数据库上运行一个非常基本的查询(例如,SELECT 1; 在 MySQL 上)。

Tomcat JDBC 连接池提供了几个选项来测试连接。我觉得比较有趣的两个是testOnBorrowtestWhileIdle

首先我认为testOnBorrow 是最好的选择,因为它基本上在将连接提供给应用程序之前验证连接(最大频率由validationInterval 定义)。

但过了一秒钟,我意识到在使用连接之前测试连接可能会影响应用程序的响应能力。所以我认为使用testWhileIdle 会更有效,因为它会在不使用时测试连接。

无论我选择哪个选项,似乎它们只会降低获得无效连接的风险,但这种风险仍然存在。

所以我最终问:我应该使用testOnBorrow 还是testWhileIdle 还是两者兼而有之?

顺便说一句,我很惊讶validationInterval 不适用于testOnReturn,而且我真的不明白testOnConnect 的用途。

【问题讨论】:

    标签: tomcat jdbc connection-pooling


    【解决方案1】:

    对此没有 100% 正确的答案。这是一个权衡和上下文的问题。

    • 在大多数情况下,testOnBorrow 是风险最小的,因为它确保(尽其所能)确保在从池中返回连接供您使用之前,已经进行了基本的健全性检查客户端和数据库服务器正在交谈。
    • 在进行“健全性检查”和您的应用程序使用连接的时间之间,它仍然不能阻止服务器连接的竞争状况。
    • 但考虑到这是一个极端情况,testOnBorrow 提供了很好的保证。

    • 现在的权衡是,每次请求连接时,都会对数据库服务器进行查询(无论多么轻量级)。这可能非常快,但成本仍然不为零。

    如果您有一个繁忙的应用程序,具有非常好的数据库连接可靠性,那么您将从数据中开始看到,“对池中的每个连接请求进行有效性检查”的成本超过了检测连接问题。

    • 另一方面,如果您的应用程序不是一直很忙(像大多数实际应用程序一样),那么使用 testOnBorrow 选项非常有益。
    • 它可以最大限度地确保您在使用之前有良好的连接。特别是考虑到从失败的数据库操作中“无法轻松恢复”的成本(重试 + 人工干预 + 工作流丢失等)。

    • 现在想象一下,如果您有 testOnIdle 选项。这要求您的连接处于空闲状态(取决于连接的空闲超时),然后才能进行完整性检查。

    • 这是对 testOnBorrow 的性能改进,但它也有其自身的缺点。
      • 现实世界的应用程序到数据库连接不仅仅是基于空闲超时的中断,它们可以根据防火墙规则、n/w 拥塞、数据库服务器正在进行维护/修补等被丢弃。
      • 因此,当您没有任何类型的“连接验证”时,它会回到数据中观察到多少连接错误的数据测量。
    • 使用此选项要注意的一件事是,当您的池在最大连接数的情况下工作得最好并且您的应用程序运行良好时,并且由于某种原因,如果您的 db-server 经历了重新启动或类似情况。所有活动连接(从客户端的角度来看)现在大部分都会出错,直到空闲超时开始。因此,您的 db-issue(本来是一场交火)现在有点复杂,直到应用连接再次恢复正常或您也重新启动应用。

    最后一个数据点是,对于某些应用程序,关键路径不是“验证查询”时间(希望以更低的毫秒为单位)。应用程序有更大的问题需要处理。当然,对于某些应用程序来说,这段时间非常重要。

    【讨论】:

      【解决方案2】:

      只是让你知道,我刚刚对此进行了测试,可以同时使用 testOnBorrowtestOnIdle 属性。

      不过,如上所述,我将唯一选择 testOnBorrow,因为我的应用程序流量并不大,并且有能力在获取连接之前验证连接。

      正如 cmets 中所指出的,testOnBorrow 不需要验证查询。如果您确实选择保留一个,它可以是一个简单的选择:

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

      如果你想使用testWhileIdle,你可以使用以下:

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

      更多关于 DBCP 的信息:https://commons.apache.org/proper/commons-dbcp/configuration.html

      【讨论】:

      • 其实验证查询不是必须的。如果未提供验证查询,则在连接上使用 isValid 方法。我认为将连接验证留给 JDBC 驱动程序是个好主意。
      • 哦,看来你是对的。只需阅读文档。将编辑帖子。
      猜你喜欢
      • 2012-03-02
      • 2020-08-22
      • 2013-05-01
      • 2014-12-26
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多