分析MyBatis空闲连接探测的机制

这篇文章主要讲解了“分析MyBatis空闲连接探测的机制”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“分析MyBatis空闲连接探测的机制”吧!

在府谷等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站建设、做网站 网站设计制作按需网站建设,公司网站建设,企业网站建设,成都品牌网站建设,全网营销推广,外贸网站制作,府谷网站建设费用合理。

最近碰到个现象,某个应用,每天在21:00-23:00才会执行,连接数据库执行操作,间隔性出现连接超时的错误,

Connection timed out (Read failed)

因为应用和数据库是跨网段,咨询了下,防火墙超时时间配置的是30分钟,应用用的MyBatis连接池,相关配置如下,

分析MyBatis空闲连接探测的机制

相关参数解释,如下所示,

POOLED– 这种数据源的实现利用“池”的概念将 JDBC  连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。这种处理方式很流行,能使并发 Web 应用快速响应请求。

除了上述提到UNPOOLED下的属性外,还有更多属性用来配置POOLED的数据源:

poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10

poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。

poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20  秒)

poolTimeToWait –  这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000  毫秒(即 20 秒)。

poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置,  作用于每一个尝试从缓存池获取连接的线程。如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过  poolMaximumIdleConnections 与 poolMaximumLocalBadConnectionTolerance 之和。默认值:3(新增于  3.4.5)

poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY  SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。

poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL  语句(最好是一个速度非常快的 SQL 语句),默认值:false。

poolPingConnectionsNotUsedFor – 配置 poolPingQuery  的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为  true 时适用)。

P.S.

https://mybatis.org/mybatis-3/zh/configuration.html#environments

按照这字面意思,一开始我们理解poolPingConnectionsNotUsedFor参数控制的是连接多久没用,即处于空闲状态,在参数poolPingEnabled开启时,就会执行poolPingQuery定义的SQL主动探测。

如果按照这理解,poolPingConnectionsNotUsedFor设置了3000,即3秒,远小于30分钟防火墙超时的设置,不应该出现连接超时的现象。

我们怀疑过防火墙的配置,但从应用端看,并不是所有的请求都超时,而且防火墙端,没看到什么异常。数据库层,应该未设置过相关的配置。

原因是什么?

作为一款成熟的产品,不太可能因为bug,更多还是对他的理解存在偏差。

下载3.3.0的源码,链接如下,

https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.3.0

搜索这几个参数所在的文件,找到了PooledDataSource类,可以看到这三个参数都设置了初始值,

分析MyBatis空闲连接探测的机制

看下这个pingConnection方法,

分析MyBatis空闲连接探测的机制

如果连接未关闭,判断逻辑如下,

1. poolPingConnectionsNotUsedFor的值>=0;

2. getTimeElapsedSinceLastUse()>poolPingConnectionsNotUsedFor;

getTimeElapsedSinceLastUse()定义如下,

分析MyBatis空闲连接探测的机制

lastUsedTimestamp是在构造函数PooledConnection中定义的,

分析MyBatis空闲连接探测的机制

PooledConnection会在获取连接(popConnection)和回收连接(pushConnection)的时候调用,获取连接和回收连接则会被getConnection()和invoke()调用,因此,(2)的意思是当前这个连接空闲的时间是否大于这个参数poolPingConnectionsNotUsedFor定义的时间。

3. 如果满足条件(1)和(2),则会执行poolPingQuery的SQL,此处就是"select 1 from  dual",如果执行失败,会关闭这个连接,

分析MyBatis空闲连接探测的机制

从应用日志,能看到这些信息,

Testing connection 0000000000 ... Execution of ping query 'select 1 from dual' failed:  Connection timed out (Read failed)

这个问题的关键,就是这个pingConnection,在什么时候调用,就决定了poolPingConnectionsNotUsedFor什么时候起作用,可以看到,他是在这个isValid的方法中调用的,

分析MyBatis空闲连接探测的机制

而这个isValid是在每次获取连接和回收连接时调用的,换句话说,他是被动调用,并不是我们认为的空闲时主动调用,所以这个应用,只是晚上会跑,空闲连接超过30分钟是很正常的,

分析MyBatis空闲连接探测的机制

应用开了debug,这两段之间的间隔时间,就是得到超时连接的时间,

分析MyBatis空闲连接探测的机制

经过单线程测试,大约在15分钟,

分析MyBatis空闲连接探测的机制

因此,对这种testOnBorrow的连接探测机制,各有优缺点,优点就是会在一定程度保证应用正常的业务请求得到可用的连接,毕竟不可用的连接都已经被poolPingQuery定义的SQL测试了,一般情况下,不会让正常的业务请求出现报错,除非连接池没任何可用的连接。缺点就是如果配置的poolPingConnectionsNotUsedFor很小,某些请求都会在执行之前先进行验证,但是换个角度,如果是高并发,只要参数不是0,一般可能都不会满足需要验证的条件,如果设置为0,就可能会有很多pingQuery定义的SQL执行。而且,如果像上述单线程的操作,他会一个连接一个连接的尝试,等待一个连接出现超时错误的时间间隔是15分钟,这就很低效了。

对连接池的选择和配置,确实得结合实际场景需求来决策。

通过这个问题,至少让我明白,“自以为对的”机制正确还是错误,还是看他的实现,这才是最可靠的验证,而且,通过他的逻辑,可以让我们借鉴一些设计路径,多考虑他这么做背后的意义和影响,更有助我们将其用到正确的场景。

感谢各位的阅读,以上就是“分析MyBatis空闲连接探测的机制”的内容了,经过本文的学习后,相信大家对分析MyBatis空闲连接探测的机制这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!


网页标题:分析MyBatis空闲连接探测的机制
文章URL:http://cdiso.cn/article/jhesco.html

其他资讯