博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
druid之close connection error错误调整
阅读量:7208 次
发布时间:2019-06-29

本文共 4841 字,大约阅读时间需要 16 分钟。

  hot3.png

数据库:oracle

数据源:druid

现象:生产环境存在两套环境,k8s和rancher,k8s环境每隔几分钟会出现close connection error,或者close statement error或者对数据库访问Broken pipe,然而rancher不会,这种现象下我们排查的重点关注在k8s网络环境,一直没有解决这问题

问题本质看这类错误表现为tcp连接被断开,排查的对象未k8s网络情况和防火墙情况,防火墙默认会关闭一定时间不活跃的连接,具体时间半小时还是多久看运维配置,因为只发生在k8s节点,这块一直在等运维同事处理,这块一直没有太大头绪,最终折中处理方式改为客户端处理,druid配置保活、配置对连接池中连接检测、配置验证sql超时时间、配置移除不活跃连接等,测试跟踪一天,确实没有类似错误了,具体网络层面原因再看了

具体配置:

spring:  datasource:    driver-class-name: oracle.jdbc.OracleDriver    username: xx    password: xx    initialSize: 10    minIdle: 10    maxActive: 50    # 配置获取连接等待超时的时间    maxWait: 60000    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒    timeBetweenEvictionRunsMillis: 60000    # 配置一个连接在池中最小生存的时间,单位是毫秒    minEvictableIdleTimeMillis: 300000    validationQuery: SELECT 1 FROM DUAL    testWhileIdle: true    testOnBorrow: true    testOnReturn: false    # 打开PSCache,并且指定每个连接上PSCache的大小    poolPreparedStatements: true    maxPoolPreparedStatementPerConnectionSize: 30    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,wall用于防火墙    filters: stat,log4j    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=3000    #使用非公平锁    useUnfairLock: true    removeAbandoned: true    removeAbandonedTimeout: 1800    logAbandoned: false    validationQueryTimeout: 1    keepAlive: true

关键配置:

//每次获取连接后执行validationQuery,一定程度会降低性能,但为了规避上述问题,需要配置

testOnBorrow: true

//非公平锁、重要,减少竞争等待时间

useUnfairLock: true removeAbandoned: true removeAbandonedTimeout: 1800 logAbandoned: false

//validationQueryTimeout 最好配置下,不然可能出现长达15分钟的校验时间,导致整个查询超时

validationQueryTimeout: 1

//在小于minIdle连接数的时候执行保活操作,防止防火墙断开连接

keepAlive: true

druid获取连接源码

public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {    int notFullTimeoutRetryCnt = 0;    for (;;) {        // handle notFullTimeoutRetry        DruidPooledConnection poolableConnection;        try {            poolableConnection = getConnectionInternal(maxWaitMillis);        } catch (GetConnectionTimeoutException ex) {            if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {                notFullTimeoutRetryCnt++;                if (LOG.isWarnEnabled()) {                    LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);                }                continue;            }            throw ex;        }        if (testOnBorrow) {            boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);            if (!validate) {                if (LOG.isDebugEnabled()) {                    LOG.debug("skip not validate connection.");                }                Connection realConnection = poolableConnection.conn;                discardConnection(realConnection);                continue;            }        } else {            Connection realConnection = poolableConnection.conn;            if (poolableConnection.conn.isClosed()) {                discardConnection(null); // 传入null,避免重复关闭                continue;            }            if (testWhileIdle) {                long currentTimeMillis             = System.currentTimeMillis();                long lastActiveTimeMillis          = poolableConnection.holder.lastActiveTimeMillis;                long idleMillis                    = currentTimeMillis - lastActiveTimeMillis;                long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;                if (timeBetweenEvictionRunsMillis <= 0) {                    timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;                }                if (idleMillis >= timeBetweenEvictionRunsMillis                        || idleMillis < 0 // unexcepted branch                        ) {                    boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);                    if (!validate) {                        if (LOG.isDebugEnabled()) {                            LOG.debug("skip not validate connection.");                        }                        discardConnection(realConnection);                         continue;                    }                }            }        }        if (removeAbandoned) {            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();            poolableConnection.connectStackTrace = stackTrace;            poolableConnection.setConnectedTimeNano();            poolableConnection.traceEnable = true;            activeConnectionLock.lock();            try {                activeConnections.put(poolableConnection, PRESENT);            } finally {                activeConnectionLock.unlock();            }        }        if (!this.defaultAutoCommit) {            poolableConnection.setAutoCommit(false);        }        return poolableConnection;    }}

转载于:https://my.oschina.net/yugj/blog/2960782

你可能感兴趣的文章
Git show-branch显示提交信息
查看>>
秒杀 ILSpy 等反编译利器 DotNet Resolver
查看>>
SharePoint 2013 中代码创建列表查阅项字段
查看>>
2014仲秋校招之面试篇
查看>>
负载均衡研究 基础
查看>>
10.cadence.自定义焊盘的创建[原创]
查看>>
shell编程总结
查看>>
Docker源码分析(七):Docker Container网络 (上)
查看>>
一些旁门左道
查看>>
Common Pitfalls In Machine Learning Projects
查看>>
Android内存泄漏分析及调试
查看>>
todoing
查看>>
[Cocos2d-x]Cocos2d-x 3.2 学习笔记
查看>>
进程调度
查看>>
使用代码为TextView设置drawableLeft
查看>>
Android开发(十八)——头部、中部、底部布局技巧
查看>>
Egret 集成第三方库 记录
查看>>
同源策略——浏览器安全卫士
查看>>
c/c++ 基金会(七) 功能覆盖,虚函数,纯虚函数控制
查看>>
CodeForces 484B Maximum Value
查看>>