Skip to content

Commit e824d25

Browse files
committed
Fix for Bug#23143279, CLIENT HANG WHEN LOADBALANCESTRATEGY IS BESTRESPONSETIME.
1 parent d8fb5f0 commit e824d25

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 5.1.49
55

6+
- Fix for Bug#23143279, CLIENT HANG WHEN LOADBALANCESTRATEGY IS BESTRESPONSETIME.
7+
68
- WL#14007, Remove third-party libraries from sources and bundles.
79

810
- Fix for Bug#98237 (30911870), PREPAREDSTATEMENT.SETOBJECT(I, "FALSE", TYPES.BOOLEAN) ALWAYS SETS TRUE OR 1.

src/com/mysql/jdbc/BestResponseTimeBalanceStrategy.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
33
44
The MySQL Connector/J is licensed under the terms of the GPLv2
55
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
@@ -24,6 +24,7 @@
2424
package com.mysql.jdbc;
2525

2626
import java.sql.SQLException;
27+
import java.util.ArrayList;
2728
import java.util.List;
2829
import java.util.Map;
2930
import java.util.Properties;
@@ -44,8 +45,13 @@ public void init(Connection conn, Properties props) throws SQLException {
4445
public ConnectionImpl pickConnection(LoadBalancedConnectionProxy proxy, List<String> configuredHosts, Map<String, ConnectionImpl> liveConnections,
4546
long[] responseTimes, int numRetries) throws SQLException {
4647

48+
List<String> whiteList = new ArrayList<String>(configuredHosts.size());
49+
whiteList.addAll(configuredHosts);
50+
4751
Map<String, Long> blackList = proxy.getGlobalBlacklist();
4852

53+
whiteList.removeAll(blackList.keySet());
54+
4955
SQLException ex = null;
5056

5157
for (int attempts = 0; attempts < numRetries;) {
@@ -61,7 +67,7 @@ public ConnectionImpl pickConnection(LoadBalancedConnectionProxy proxy, List<Str
6167
for (int i = 0; i < responseTimes.length; i++) {
6268
long candidateResponseTime = responseTimes[i];
6369

64-
if (candidateResponseTime < minResponseTime && !blackList.containsKey(configuredHosts.get(i))) {
70+
if (candidateResponseTime < minResponseTime && !blackList.containsKey(whiteList.get(i))) {
6571
if (candidateResponseTime == 0) {
6672
bestHostIndex = i;
6773

@@ -73,7 +79,7 @@ public ConnectionImpl pickConnection(LoadBalancedConnectionProxy proxy, List<Str
7379
}
7480
}
7581

76-
String bestHost = configuredHosts.get(bestHostIndex);
82+
String bestHost = whiteList.get(bestHostIndex);
7783

7884
ConnectionImpl conn = liveConnections.get(bestHost);
7985

src/testsuite/regression/ConnectionRegressionTest.java

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11204,4 +11204,127 @@ public void testBug70677() throws Exception {
1120411204
}
1120511205
}
1120611206
}
11207+
11208+
/**
11209+
* Test fix for Bug#23143279, CLIENT HANG WHEN LOADBALANCESTRATEGY IS BESTRESPONSETIME.
11210+
*
11211+
* @throws Exception
11212+
*/
11213+
public void testBug23143279() throws Exception {
11214+
testBug23143279RunTest("random");
11215+
testBug23143279RunTest("bestResponseTime");
11216+
testBug23143279RunTest("serverAffinity");
11217+
testBug23143279RunTest("com.mysql.jdbc.SequentialBalanceStrategy");
11218+
}
11219+
11220+
private void testBug23143279RunTest(String lbStrategy) throws Exception {
11221+
final String defaultHost = getPropertiesFromTestsuiteUrl().getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY);
11222+
final String defaultPort = getPropertiesFromTestsuiteUrl().getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY);
11223+
11224+
final String host1 = "first";
11225+
final String host2 = "second";
11226+
final String host3 = "third";
11227+
final String host4 = "fourth";
11228+
final String hostPort4 = host4 + ":" + defaultPort;
11229+
11230+
final String uniqueId = String.valueOf(lbStrategy.substring(lbStrategy.lastIndexOf('.') + 1, lbStrategy.lastIndexOf('.') + 4)).toUpperCase();
11231+
final String connGroupName = "testBug23143279" + uniqueId;
11232+
11233+
final Properties props = new Properties();
11234+
props.setProperty("useSSL", "false");
11235+
props.setProperty("loadBalanceHostRemovalGracePeriod", "0");
11236+
props.setProperty("loadBalanceConnectionGroup", connGroupName);
11237+
props.setProperty("loadBalanceStrategy", lbStrategy);
11238+
11239+
System.out.println("\n\nTEST: " + lbStrategy);
11240+
System.out.println("********************************************************************************");
11241+
System.out.println("\tHosts group: " + connGroupName);
11242+
11243+
final MySQLConnection testConn = (MySQLConnection) getUnreliableLoadBalancedConnection(new String[] { host1, host2, host3 }, props,
11244+
new HashSet<String>(Arrays.asList(host2, host3)));
11245+
UnreliableSocketFactory.mapHost(host4, defaultHost);
11246+
11247+
System.out.println("\nStep 1: initial connection");
11248+
System.out.println("********************************************************************************");
11249+
System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName));
11250+
System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName));
11251+
System.out.println("\tConnected to: " + testConn.getHostPortPair());
11252+
System.out.println("\tConnection id: " + testConn.getId());
11253+
11254+
assertEquals(host1 + ":" + defaultPort, testConn.getHostPortPair());
11255+
11256+
this.stmt.execute("KILL CONNECTION " + testConn.getId());
11257+
try {
11258+
testConn.createStatement().executeQuery("SELECT 1");
11259+
fail("Should have thrown an exception here.");
11260+
} catch (SQLException e) {
11261+
System.out.println(e.getMessage());
11262+
// Should be reconnected by now.
11263+
}
11264+
11265+
System.out.println("\nStep 2: after killing the active connection and having reconnected");
11266+
System.out.println("********************************************************************************");
11267+
System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName));
11268+
System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName));
11269+
System.out.println("\tConnected to: " + testConn.getHostPortPair());
11270+
System.out.println("\tConnection id: " + testConn.getId());
11271+
11272+
assertEquals(host1 + ":" + defaultPort, testConn.getHostPortPair());
11273+
11274+
ConnectionGroupManager.addHost(connGroupName, hostPort4, true);
11275+
11276+
System.out.println("\nStep 3: after adding a new host");
11277+
System.out.println("********************************************************************************");
11278+
System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName));
11279+
System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName));
11280+
System.out.println("\tConnected to: " + testConn.getHostPortPair());
11281+
System.out.println("\tConnection id: " + testConn.getId());
11282+
11283+
this.stmt.execute("KILL CONNECTION " + testConn.getId());
11284+
try {
11285+
testConn.createStatement().executeQuery("SELECT 1");
11286+
} catch (SQLException e) {
11287+
System.out.println(e.getMessage());
11288+
// Should be reconnected by now.
11289+
}
11290+
11291+
boolean connectedToHost1 = testConn.getHostPortPair().startsWith(host1);
11292+
assertEquals((connectedToHost1 ? host1 : host4) + ":" + defaultPort, testConn.getHostPortPair());
11293+
11294+
System.out.println("\nStep 4: after killing the active connection and having reconnected");
11295+
System.out.println("********************************************************************************");
11296+
System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName));
11297+
System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName));
11298+
System.out.println("\tConnected to: " + testConn.getHostPortPair());
11299+
System.out.println("\tConnection id: " + testConn.getId());
11300+
11301+
final String hostToRemove = testConn.getHostPortPair();
11302+
ExecutorService executor = Executors.newSingleThreadExecutor();
11303+
Future<?> future = executor.submit(new Callable<Void>() {
11304+
public Void call() throws Exception {
11305+
ConnectionGroupManager.removeHost(connGroupName, hostToRemove, true);
11306+
return null;
11307+
}
11308+
});
11309+
11310+
try {
11311+
future.get(10, TimeUnit.SECONDS);
11312+
} catch (TimeoutException e) {
11313+
executor.shutdownNow();
11314+
fail("Failed to remove host and connect to a new one.\n"
11315+
+ "WARNING: A ConcurrentModificationException on UnreliableSocketFactory can happen from now on.");
11316+
}
11317+
executor.shutdownNow();
11318+
11319+
System.out.println("\nStep 5: after removing the connected host [" + hostToRemove + "]");
11320+
System.out.println("********************************************************************************");
11321+
System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName));
11322+
System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName));
11323+
System.out.println("\tConnected to: " + testConn.getHostPortPair());
11324+
System.out.println("\tConnection id: " + testConn.getId());
11325+
11326+
assertEquals((connectedToHost1 ? host4 : host1) + ":" + defaultPort, testConn.getHostPortPair());
11327+
11328+
testConn.close();
11329+
}
1120711330
}

0 commit comments

Comments
 (0)