get connection timeout retry : 1

╰半橙微兮° 2023-10-06 17:55 92阅读 0赞

错误一:get connection timeout retry : 1

https://github.com/alibaba/druid/issues/4326

生产环境运行一段时间后,报错如下:

com.alibaba.druid.pool.DruidDataSource : get connection timeout retry : 1
com.alibaba.druid.pool.DruidDataSource : get connection timeout retry : 1
com.alibaba.druid.pool.DruidDataSource : create connection SQLException, url: jdbc:oracle:thin:@x.x.x.x:1521:orcl, errorCode 17002, state 08006
java.sql.SQLRecoverableException: IO Error: Connection reset
Caused by: java.net.SocketException: Connection reset
c.a.druid.pool.DruidAbstractDataSource : {dataSource-1} failContinuous is true

此时连接并没有到达最大连接数,一直复现不了问题,花了不少时间才定位到原因 :

并发获取连接的个数超过”最大并发连接数“导致。但此时连接数远远未到达最大连接数。

select count(*) from v$session where status=’ACTIVE’ —最大并发连接数

查询结果:23

还原测试:

设置获取连接超时时间为6秒

###程序向连接池中请求连接时,超时时间,毫秒
spring.datasource.druid.max-wait=6000

测试代码:

  1. int N = 50;
  2. CountDownLatch countDownLatch = new CountDownLatch(N);// 实例化一个倒计数器,N指定计数个数
  3. for (int i = 0; i < N; i++) {
  4. new Thread(() -> {
  5. Connection connection = null;
  6. try {
  7. // 执行代码
  8. countDownLatch.countDown(); // 计数减一
  9. countDownLatch.await();// 等待,当计数减到0时,所有线程并行执行
  10. connection = jdbcTemplate.getDataSource().getConnection();
  11. String sql = "select count(*) from v$process";
  12. PreparedStatement statement = connection.prepareStatement(sql);
  13. ResultSet set = statement.executeQuery();
  14. if (set.next()) {
  15. System.out.println("当前的连接数:" + set.getString(1));
  16. }
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. } finally {
  20. try {
  21. // connection.close();
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }).start();
  27. }

测试代码刚好出现 50-23=27 个错误: get connection timeout retry : 1

解决办法:

延长获取连接超时时间。

###程序向连接池中请求连接时,超时时间,毫秒
spring.datasource.druid.max-wait=180000

但是延长获取连接超时时间的办法,治标不治本。

保持连接池最小连接数,避免突然大量并发创建连接,来最终解决问题。

spring.datasource.druid.min-idle=20

补充:

无论是YGC或是FullGC,都会导致stop-the-world,即整个程序停止一些事务的处理,只有GC进程允许以进行垃圾回收,因此如果垃圾回收时间较长,部分web或socket程序,当终端连接的时候会报connetTimeOut或readTimeOut异常

错误二:java.sql.SQLRecoverableException: 无法从套接字读取更多的数据

测试:

## 配置间隔多久才进行一次检测(检测需要关闭的空闲连接),单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000

在使用连接后60秒内杀掉session ,并再次使用连接查询数据库。

  1. #登陆到oracle用户
  2. su - oracle
  3. #杀掉所有session
  4. ps -ef|grep $ORACLE_SID|grep -v ora_|grep LOCAL=NO|awk '{print $2}'|xargs kill -9

在配置的空闲连接时间 60秒内 如果发生网络异常,Oracle服务端连接已断开,但是客户端连接池并不知道,再次使用就会报错:

java.sql.SQLRecoverableException: 无法从套接字读取更多的数据

解决办法:

#程序 申请 连接时,进行连接有效性检查(低效,影响性能)
spring.datasource.druid.test-on-borrow=true

发表评论

表情:
评论列表 (有 0 条评论,92人围观)

还没有评论,来说两句吧...

相关阅读