开发者社区> 问答> 正文

使用单线程创建数据库连接 + 数据库连接没有配置超时 socketTimeout,造成挂起2小时11

使用单线程创建数据库连接 + 数据库连接没有配置超时 socketTimeout,造成挂起2小时11分钟无法获取新连接,系统必须重启。

挂起场景:握手阶段 "Druid-ConnectionPool-Create-664205978" #31 daemon prio=5 os_prio=0 tid=0x000000001934f000 nid=0x3930 runnable [0x000000001ecbe000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:150) at java.net.SocketInputStream.read(SocketInputStream.java:121) at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114) //挂起 at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161) at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189) - locked <0x00000000c6972650> (a com.mysql.jdbc.util.ReadAheadInputStream) at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3163) at com.mysql.jdbc.MysqlIO.readPacket(MysqlIO.java:600) at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1088) //握手请求 at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2493) at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2526) //获取单个连接 at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2311) - locked <0x00000000c69727a0> (a com.mysql.jdbc.JDBC4Connection) at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:834) at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:47) at sun.reflect.GeneratedConstructorAccessor76.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:408) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:347) at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:156) at com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:218) at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:150) at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1598) at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1662) at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2601)

https://www.codeleading.com/article/6202689267/

tcp_syn_retries 默认值:5 功能:对于一个新建的TCP连接(主动发起),内核要发送多少个SYN连接请求才决定放弃。这个值不应该超过255。默认值为5,对应180s

tcp_keepalive_time 默认值:7200(2小时)。单位-秒 功能:对于一个保活的TCP连接,该值设定了TCP多长时间发送一次keepalive消息(简单来说就是心跳检测周期)

tcp_keepalive_probes 默认值:9 功能:在内核决定放弃该连接之前,发送多少个keepalive探测

tcp_keepalive_intvl ** 默认值:75 功能:设定keepalive探测发送频率。 对于发出的keepalive探测消息没有收到响应时,则根据这个intvl值设定的间隔再次发送。 用这个intvl值probes值,得到的是发送探测共消耗的时间,默认是11分钟。9*75/60=11min。 如果在这11分钟内还没有收到探测响应,则丢弃该TCP连接。

生产环境2小时11分钟,才能从失败中重连,和上面3个参数刚好一致。

Druid连接池,是否能够提供一个后备方案在多长时间没有连接成功后, 重新发起连接?

原提问者GitHub用户GuoHuiChen

展开
收起
山海行 2023-07-05 18:04:59 115 0
3 条回答
写回答
取消 提交回答
  • 北京阿里云ACE会长

    在使用单线程创建数据库连接时,如果连接没有配置超时 socketTimeout,可能会导致连接挂起,进而导致程序长时间等待而陷入阻塞状态。

    配置 socketTimeout 的作用是设置连接的超时时间,当连接在指定的时间内没有响应时,会抛出超时异常,从而避免连接挂起的情况。建议在连接数据库时,根据实际情况设置合适的 socketTimeout 值,以避免连接挂起的风险。

    同时,在使用单线程创建数据库连接时,需要注意连接的使用和释放,以避免连接泄漏或者过多占用连接资源的情况。建议使用连接池等技术来管理数据库连接,以提高连接的重用率和效率,并避免连接资源的浪费。

    2023-07-30 20:35:13
    赞同 展开评论 打赏
  • Druid连接池支持配置一个超时时间,可以在连接池创建时传递一个超时时间参数。例如,可以使用如下代码创建一个连接池,该连接池在2小时11分钟内没有成功连接时会重新发起连接

    2023-07-09 10:11:37
    赞同 展开评论 打赏
  • 没有配置超时,tcp的keepalive就是2小时11分钟。这是正常的。

    原回答者GitHub用户kimmking

    2023-07-06 10:42:40
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
2022 DTCC-阿里云一站式数据库上云最佳实践 立即下载
云时代的数据库技术趋势 立即下载
超大型金融机构国产数据库全面迁移成功实践 立即下载