springboot druid 数据库连接池连接失败后一直重连
在使用个人阿里云测试机,在查询实时输出日志时,看到数据库连接失败后,服务器一直在重连服务器。开始以为是遭受重复攻击,后面把服务重启后,就没有出现一直重连的情况。看以下输出日志:
2022-02-09 11:04:58.896 ERROR 16876 --- [eate-1550991149] com.alibaba.druid.pool.DruidDataSource : create connection SQLException, url: jdbc:mysql://47.98.67,98:1234/test?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC, errorCode 1045, state 28000
java.sql.SQLException: Access denied for user 'root'@'113.90.123.76' (using password: YES)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:156) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:218) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:150) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1560) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1623) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2468) ~[druid-1.1.10.jar:1.1.10]
注意上面一直有 druid 数据库连接池的提示,这里就想到可能是 druid 连接池的问题,然后去掉 druid maven 依赖后在请求接口就不会出现重连的问题。
druid 重连原因
在上图源码找到最后一行 DruidDataSource.java:2468 定位到源码上,CreateConnectionThread 创建连接线程,看一下 CreateConnectionThread 源码:
public class CreateConnectionThread extends Thread {
public CreateConnectionThread(String name){
super(name);
this.setDaemon(true);
}
public void run() {
initedLatch.countDown();
long lastDiscardCount = 0;
int errorCount = 0;
for (;;) {
// addLast
try {
lock.lockInterruptibly();
} catch (InterruptedException e2) {
break;
}
long discardCount = DruidDataSource.this.discardCount;
boolean discardChanged = discardCount - lastDiscardCount > 0;
lastDiscardCount = discardCount;
try {
boolean emptyWait = true;
if (createError != null
&& poolingCount == 0
&& !discardChanged) {
emptyWait = false;
}
if (emptyWait
&& asyncInit && createCount < initialSize) {
emptyWait = false;
}
if (emptyWait) {
// 必须存在线程等待,才创建连接
if (poolingCount >= notEmptyWaitThreadCount //
&& !(keepAlive && activeCount + poolingCount < minIdle)) {
empty.await();
}
// 防止创建超过maxActive数量的连接
if (activeCount + poolingCount >= maxActive) {
empty.await();
continue;
}
}
} catch (InterruptedException e) {
lastCreateError = e;
lastErrorTimeMillis = System.currentTimeMillis();
if (!closing) {
LOG.error("create connection Thread Interrupted, url: " + jdbcUrl, e);
}
break;
} finally {
lock.unlock();
}
PhysicalConnectionInfo connection = null;
try {
connection = createPhysicalConnection();
setFailContinuous(false);
} catch (SQLException e) {
LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode()
+ ", state " + e.getSQLState(), e);
errorCount++;
if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {
// fail over retry attempts
setFailContinuous(true);
if (failFast) {
lock.lock();
try {
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
if (breakAfterAcquireFailure) {
break;
}
try {
Thread.sleep(timeBetweenConnectErrorMillis);
} catch (InterruptedException interruptEx) {
break;
}
}
} catch (RuntimeException e) {
LOG.error("create connection RuntimeException", e);
setFailContinuous(true);
continue;
} catch (Error e) {
LOG.error("create connection Error", e);
setFailContinuous(true);
break;
}
if (connection == null) {
continue;
}
boolean result = put(connection);
if (!result) {
JdbcUtils.close(connection.getPhysicalConnection());
LOG.info("put physical connection to pool failed.");
}
errorCount = 0; // reset errorCount
}
}
}
这是一个多线程的类,而 run 方法里面设置了没有限制的 for 循环 for (;;) {}, 而日志报错定位的信息:
connection = createPhysicalConnection();
如果符合条件 errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0 会再次尝试重连,先看一下这几个参数的含义:
errorCount 错误次数
在 run 方法初始化时为零,每次连接失败,会自动加1
connectionErrorRetryAttempts
连接错误重试次数,默认值为 1。
protected int connectionErrorRetryAttempts = 1;
timeBetweenConnectErrorMillis
连接间隔时间,单位毫秒。默认值为 500。
protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS;
public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 500;
我们在连接数据库失败后,要不在里面 break 中断,其中有
if (breakAfterAcquireFailure) {
break;
}
将改 break-after-acquire-failure 设置成 true,在 application.properties 文件如下配置:
spring.datasource.druid.break-after-acquire-failure=true
如果想多尝试连接几次,需要设置 connection-error-retry-attempts ,当 errorCount 大于 connectionErrorRetryAttempts 才会进入到 条件内,才会中断循环。在 application.properties 文件如下配置:
spring.datasource.druid.connection-error-retry-attempts=3
总结
druid 数据库连接失败,是因为在使用多线程连接数据时使用了无限制循环连接,需要在连接失败中断连接,需要设置 break-after-acquire-failure 为 true。设置之后数据库连接不成功也不会不断的重试。如果要设置重连次数要设置 connection-error-retry-attempts。
如果觉得文章对你有帮助的话,请点个推荐吧!
springboot druid 数据库连接池连接失败后一直重连的更多相关文章
- springboot项目整合druid数据库连接池
Druid连接池是阿里巴巴开源的数据库连接池项目,后来贡献给Apache开源: Druid的作用是负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个: D ...
- Druid数据库连接池源码分析
上一篇文章重点介绍了一下Java的Future模式,最后意淫了一个数据库连接池的场景.本想通过Future模式来防止,当多个线程同时获取数据库连接时各自都生成一个,造成资源浪费.但是忽略了一个根本的功 ...
- Druid数据库连接池就这么简单
前言 本章节主要讲解Druid数据库连接池,为什么要学Druid数据库连接池呢?? 我的知识储备数据库连接池有两种->C3P0,DBCP,可是现在看起来并不够用阿~当时学习C3P0的时候,觉得这 ...
- 【spring boot】15.spring boot项目 采用Druid数据库连接池,并启用druid监控功能
在http://www.cnblogs.com/sxdcgaq8080/p/9039442.html的基础上,来看看spring boot项目中采用Druid连接池. GitHub地址:示例代码 == ...
- Druid数据库连接池配置
DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0.DBCP.PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB ...
- Spring Boot [使用 Druid 数据库连接池]
导读 最近一段时间比较忙,以至于很久没有更新Spring Boot系列文章,恰好最近用到Druid, 就将Spring Boot 使用 Druid作为数据源做一个简单的介绍. Druid介绍: Dru ...
- Spring Boot集成Druid数据库连接池
1. 前言 Druid数据库连接池由阿里巴巴开源,号称是java语言中最好的数据库连接池,是为监控而生的.Druid的官方地址是:https://github.com/alibaba/druid 通过 ...
- spring boot:配置druid数据库连接池(开启sql防火墙/使用log4j2做异步日志/spring boot 2.3.2)
一,druid数据库连接池的功能? 1,Druid是阿里巴巴开发的号称为监控而生的数据库连接池 它的优点包括: 可以监控数据库访问性能 SQL执行日志 SQL防火墙 2,druid的官方站: http ...
- Druid 数据库连接池
druid 数据库连接池 由阿里提供 步骤 1 导包 durid1.0.9 jar 包 2 定义配置文件 必须是 properties文件 名字任意 位置也任意 3 获得数据库连接池对象 通过 Dur ...
随机推荐
- Exponential family of distributions
目录 定义 性质 极大似然估计 最大熵 例子 Bernoulli 指数分布 正态分布 Choi H. I. Lecture 4: Exponential family of distributions ...
- pycharm遇到的小问题
1. Pycharm编写的代码出现满屏的波浪线,如何去除>>>点击右下角的小人图标将箭头移到中间syntax处即可. 2. 运行时报错: UserWarning: No parser ...
- Java初学者作业——为某超市设计管理系统,需要在控制台展示系统菜单,菜单之间可以完成跳转。
返回本章节 返回作业目录 需求说明: 为某超市设计管理系统,需要在控制台展示系统菜单,菜单之间可以完成跳转. 实现思路: 定义mainMenu方法,用于显示主菜单. 主菜单主要负责显示4个选项,分别是 ...
- 编写Java程序,方法练习题__构建英雄类,定义一个int类型的变量output,表示英雄的血量
返回本章节 返回作业目录 需求说明: 定义一个int类型的变量output,表示英雄的血量,当battle()方法执行一次,output变量值减少10.在控制台随机输入一个小于100的整数,将该整数值 ...
- 2.spring系列之404异常的捕获
回顾 我在之前发布了一篇spring统一返回的文章,最后提到是无法捕获404异常的,这里我们先来测试一下 @RestController public class TestController { @ ...
- 把rocksdb配置成leveldb
将rocksdb配置成leveldb 1.配置方法 配置方式有三种: 第一种适合进行性能测试对比:是以参数形式在运行db_bench或ycsb-c的时候以参数形式将rocksdb将其配置成leveld ...
- Shell中 heredoc 内容转义
1.在$符号前面加反斜杠,如: cat > test.sh <<EOF \$test EOF 如果不加,将转成实际的值. 2.给EOF加个双引号,如: cat > test.s ...
- js获取设备内网ip
可以直接使用,不需要导入其他配置 看代码 1 <script> 2 //获取内网ip 3 var RTCPeerConnection = window.RTCPeerConnection ...
- 为什么char类型输入遇空格会结束,int类型必须要空格才能输出
char类型与int类型输入时的区别: 在C语言的规则中,规定了scanf函数在接收字符串时--遇到空格或回车就认为前面的输入已经完成且有效! 而对于int类型:表示整数,输入时需要用空格隔开,以确认 ...
- JSP页面使用EL表达式不显示实际数据
今天在学习有关jsp的相关知识内容时,遇到了el表达式只是显示括号里面的内容 代码如下: <%@ page contentType="text/html;charset=UTF-8&q ...