Druid 获取连接死循环

1
2
3
if (breakAfterAcquireFailure) {
break;
}
1
2
3
if (physicalConnection == null) {
continue;
}

原因

breakAfterAcquireFailur默认为false

且配置文件或代码中未设置 breakAfterAcquireFailur 属性和maxWait属性,

且因为循环为for(;;),从而导致死循环重试。

解决

在配置文件或代码中设置 breakAfterAcquireFailur 属性和maxWait属性即可。

完整源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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))
&& !isFailContinuous()
) {
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();
} 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

if (closing || closed) {
break;
}
}
}
}

Druid 获取连接死循环
https://blog.josway.cc/2022/04/25/yuque/Druid 获取连接死循环/
作者
JOSWAY
发布于
2022年4月25日
许可协议