druid之连接空闲超时问题FIX

彼时的少年站在成长的尽头,回首过去,一路崎岖早已繁花盛开

druid 是一个用于 Java 的高效数据库连接池,它提供了强大的监控和扩展功能。

空闲等待超时

Caused by:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:The last packet successfully received from the server was 65,699,330 milliseconds ago. The last packet sent successfully to the server was 65,699,330 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. 

mysql数据库等待超时时间(wait_timeout)是28800,也就是8小时,而druid连接池参数max-wait是30000

连接空闲超时问题的原因通常与连接池和数据库服务器之间的配置不匹配有关。当连接池中的连接长时间处于空闲状态时,数据库服务器可能会关闭这些空闲连接以节省资源。这种情况下,连接池可能仍然认为这些连接是有效的,但实际上数据库服务器已经释放了它们。

以下是引发连接空闲超时问题的一些可能原因:

  1. 服务器端的 wait_timeout 设置较低:数据库服务器会在连接空闲一段时间后关闭它们。如果服务器的 wait_timeout 参数设置得较低,连接池中的空闲连接可能在被使用前就已被服务器关闭。

  2. 连接池配置不合理:如果连接池的配置参数(例如 maxIdleminEvictableIdleTimeMillis)没有合理设置,连接池可能会保持过多的空闲连接,导致它们在被使用前被数据库服务器关闭。

  3. 连接池没有检查连接有效性:如果连接池在获取连接时没有进行有效性检查(例如没有启用 testOnBorrow 和设置 validationQuery),则可能会将已被数据库服务器关闭的连接分配给应用程序,从而导致通信问题。

解决这个问题的关键是确保连接池和数据库服务器之间的配置相互协调。可以通过调整连接池和数据库服务器的相关参数以及启用连接有效性检查来解决连接空闲超时问题。

解决方案

这个错误表明在使用数据库连接时出现了通信问题。从错误日志来看,连接在一段时间内没有收到或发送任何数据包,超过了服务器配置的 wait_timeout 值。这可能是因为连接长时间处于空闲状态,而 MySQL 服务器端的 wait_timeout 参数设置为 8 小时(28,800 秒)。

为了解决这个问题,可以尝试以下几个方法:

  1. 在 druid 连接池中配置 testOnBorrow 参数,将其设置为 true。这将在从连接池获取连接时检查连接的有效性。另外,你需要配置 validationQuery 参数,以便在获取连接时执行一个简单的 SQL 查询以测试连接的有效性。例如,对于 MySQL,可以设置 validationQuerySELECT 1
druid:
  testOnBorrow: true
  validationQuery: SELECT 1

  1. 调整 druid 连接池的 maxIdleminEvictableIdleTimeMillis 参数。maxIdle 参数用于设置连接池中允许的最大空闲连接数,minEvictableIdleTimeMillis 参数表示一个连接空闲多长时间后将被清除或回收。这可以防止长时间未使用的连接被 MySQL 服务器关闭。
druid:
  maxIdle: <设置最大空闲连接数>
  minEvictableIdleTimeMillis: <设置空闲连接的最小可驱逐时间(毫秒)>

  1. 在 MySQL 服务器端增加 wait_timeout 参数的值。这将允许连接在空闲状态下保持更长的时间。然而,需要注意的是,这可能会导致服务器资源占用较高,因此请根据实际情况进行调整。

  2. 在连接 MySQL 数据库时,使用 Connector/J 驱动的 autoReconnect=true 属性。这样在连接断开后,驱动程序会尝试自动重新连接。需要注意的是,这种方法可能会隐藏一些潜在的问题,因此在使用前要仔细权衡利弊。

jdbc:mysql://<hostname>:<port>/<database>?autoReconnect=true

尝试根据上述方法调整 druid 连接池和 MySQL 服务器的配置,以解决这个通信问题。

网上很多人都是把max-wait设置的小点, 例如 10000, 然后解决的, 这真的可以解决这个问题吗?

maxWait 参数并不是用来表示连接池持有数据库连接空闲也依旧占用多长时间的意思。实际上,maxWait 是 Druid 连接池配置中的一个参数,表示从连接池中获取连接时的最大等待时间。

当一个线程需要从连接池获取一个连接时,如果连接池中没有可用的连接,该线程会等待。maxWait 参数用于指定等待的最大时间(以毫秒为单位)。如果在 maxWait 所设置的时间内仍然无法获取到可用的连接,那么该线程将抛出一个异常。这可以防止线程因为等待连接而长时间阻塞。

另一方面,关于连接池持有数据库连接空闲依旧占用的时间,你可以查看 minEvictableIdleTimeMillis 参数。这个参数表示连接空闲多长时间后会被清除或回收。通过设置这个参数,你可以控制连接池中连接的最小空闲时间。

max-wait 设置得较小(例如 10,000 毫秒)并不能直接解决这个问题。实际上,减小 max-wait 只是减少了等待从连接池中获取连接的时间,但并不能解决连接空闲超时的根本问题。

max-wait 设置得较小可能会减轻问题的表面现象,因为在高并发场景下,等待时间较短可能会使得连接更快地被分配给其他线程,从而减少单个连接空闲的时间。然而,这并不能保证在低负载情况下连接不会长时间保持空闲状态。

为了解决这个问题,建议采用前面提到的方法,例如:

  1. 使用 testOnBorrowvalidationQuery 参数来检查从连接池获取的连接的有效性。
  2. 调整 maxIdleminEvictableIdleTimeMillis 参数,以便更好地管理连接池中的空闲连接。
  3. 调整 MySQL 服务器的 wait_timeout 参数,使其允许连接在空闲状态下保持更长的时间。
  4. 在连接字符串中添加 autoReconnect=true,以便在连接断开时尝试自动重新连接。

这些方法可以更有效地解决连接空闲超时的问题。

网上有人说testOnReturn和testOnBorrow都为false时性能最好, 是这样的吗?

testOnReturntestOnBorrow 都设置为 false 时,性能可能会有所提升。这是因为在这种情况下,连接池不会在归还或获取连接时执行额外的有效性检查。这样可以减少一些开销,从而提高性能。

然而,并非所有情况下都适合将这两个参数设置为 false。例如,在你之前提到的问题中,由于连接空闲超时导致的通信问题,这种情况下,将 testOnBorrow 设置为 true 可以帮助检查连接的有效性,从而避免因为使用无效连接而导致的问题。

在实际应用中,需要根据具体场景和需求来决定是否启用这些参数。如果数据库服务器和连接池的配置良好,并且连接稳定性较高,可以考虑将这些参数设置为 false 以提高性能。然而,如果连接稳定性存在问题,或者需要确保连接的有效性,那么启用这些参数可能是更好的选择。

总之,在实际应用中,需要权衡性能和稳定性,根据具体情况选择合适的参数配置。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>