Skip to content

Commit fb55ede

Browse files
authored
Implement internal connection pools for the read-write plugin (#359)
Add functionality to use internal connection pools to establish connections. The motivation for using pools comes from the read-write plugin's need to regularly establish new connections. Using pools will increase performance and decrease demands on the database by allowing connections to be re-used.
1 parent a76d187 commit fb55ede

File tree

61 files changed

+2269
-436
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2269
-436
lines changed

.editorconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ ij_any_spaces_around_relational_operators = true
4242
ij_any_spaces_around_shift_operators = true
4343
ij_continuation_indent_size = 4
4444
ij_java_align_multiline_parameters = false
45+
ij_java_doc_indent_on_continuation = true
4546
ij_java_if_brace_force = always
46-
ij_java_indent_case_from_switch = false
47+
ij_java_indent_case_from_switch = true
4748
ij_java_line_comment_add_space = true
4849
ij_java_space_after_colon = true
4950
ij_java_space_before_colon = true

benchmarks/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dependencies {
2323
implementation("org.postgresql:postgresql:42.5.0")
2424
implementation("mysql:mysql-connector-java:8.0.31")
2525
implementation("org.mariadb.jdbc:mariadb-java-client:3.1.0")
26+
implementation("com.zaxxer:HikariCP:4.0.3")
2627

2728
testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0")
2829
testImplementation("org.mockito:mockito-inline:4.8.0")

benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/ConnectionPluginManagerBenchmarks.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public class ConnectionPluginManagerBenchmarks {
7777
private static final String WRITER_SESSION_ID = "MASTER_SESSION_ID";
7878
private static final String FIELD_SERVER_ID = "SERVER_ID";
7979
private static final String FIELD_SESSION_ID = "SESSION_ID";
80-
private final Properties emptyProperties = new Properties();
80+
private Properties propertiesWithoutPlugins;
8181
private Properties propertiesWithPlugins;
8282
private ConnectionPluginManager pluginManager;
8383
private ConnectionPluginManager pluginManagerWithNoPlugins;
@@ -125,14 +125,17 @@ public void setUpIteration() throws Exception {
125125
DriverConfigurationProfiles.addOrReplaceProfile(
126126
"benchmark",
127127
pluginFactories);
128+
propertiesWithoutPlugins = new Properties();
129+
propertiesWithoutPlugins.setProperty(PropertyDefinition.PLUGINS.name, "");
130+
128131
propertiesWithPlugins = new Properties();
129132
propertiesWithPlugins.setProperty(PropertyDefinition.PROFILE_NAME.name, "benchmark");
130133

131134
pluginManager = new ConnectionPluginManager(mockConnectionProvider, mockConnectionWrapper);
132135
pluginManager.init(mockPluginService, propertiesWithPlugins, mockPluginManagerService);
133136

134137
pluginManagerWithNoPlugins = new ConnectionPluginManager(mockConnectionProvider, mockConnectionWrapper);
135-
pluginManagerWithNoPlugins.init(mockPluginService, emptyProperties, mockPluginManagerService);
138+
pluginManagerWithNoPlugins.init(mockPluginService, propertiesWithoutPlugins, mockPluginManagerService);
136139
}
137140

138141
@TearDown(Level.Iteration)
@@ -143,7 +146,7 @@ public void tearDownIteration() throws Exception {
143146
@Benchmark
144147
public ConnectionPluginManager initConnectionPluginManagerWithNoPlugins() throws SQLException {
145148
final ConnectionPluginManager manager = new ConnectionPluginManager(mockConnectionProvider, mockConnectionWrapper);
146-
manager.init(mockPluginService, emptyProperties, mockPluginManagerService);
149+
manager.init(mockPluginService, propertiesWithoutPlugins, mockPluginManagerService);
147150
return manager;
148151
}
149152

@@ -168,7 +171,7 @@ public Connection connectWithNoPlugins() throws SQLException {
168171
return pluginManagerWithNoPlugins.connect(
169172
"driverProtocol",
170173
new HostSpec("host"),
171-
emptyProperties,
174+
propertiesWithoutPlugins,
172175
true);
173176
}
174177

@@ -211,7 +214,7 @@ public ConnectionPluginManager initHostProvidersWithNoPlugins() throws SQLExcept
211214
pluginManagerWithNoPlugins.initHostProvider(
212215
"protocol",
213216
"url",
214-
emptyProperties,
217+
propertiesWithoutPlugins,
215218
mockHostListProvider);
216219
return pluginManager;
217220
}

benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
package software.amazon.jdbc.benchmarks;
1818

1919
import static org.mockito.ArgumentMatchers.any;
20+
import static org.mockito.ArgumentMatchers.anyBoolean;
2021
import static org.mockito.ArgumentMatchers.anyString;
2122
import static org.mockito.ArgumentMatchers.eq;
2223
import static org.mockito.Mockito.when;
2324

25+
import com.zaxxer.hikari.HikariConfig;
2426
import java.sql.Connection;
2527
import java.sql.ResultSet;
2628
import java.sql.SQLException;
@@ -46,9 +48,15 @@
4648
import org.openjdk.jmh.runner.RunnerException;
4749
import org.openjdk.jmh.runner.options.Options;
4850
import org.openjdk.jmh.runner.options.OptionsBuilder;
51+
import software.amazon.jdbc.ConnectionPluginManager;
4952
import software.amazon.jdbc.ConnectionProvider;
53+
import software.amazon.jdbc.ConnectionProviderManager;
54+
import software.amazon.jdbc.HikariPooledConnectionProvider;
55+
import software.amazon.jdbc.HostListProviderService;
5056
import software.amazon.jdbc.HostSpec;
57+
import software.amazon.jdbc.PluginManagerService;
5158
import software.amazon.jdbc.PluginService;
59+
import software.amazon.jdbc.benchmarks.testplugin.TestConnectionWrapper;
5260
import software.amazon.jdbc.dialect.Dialect;
5361
import software.amazon.jdbc.wrapper.ConnectionWrapper;
5462

@@ -63,13 +71,16 @@ public class PluginBenchmarks {
6371
private static final String WRITER_SESSION_ID = "MASTER_SESSION_ID";
6472
private static final String FIELD_SERVER_ID = "SERVER_ID";
6573
private static final String FIELD_SESSION_ID = "SESSION_ID";
66-
private static final String CONNECTION_STRING = "driverProtocol://my.domain.com";
74+
private static final String CONNECTION_STRING = "jdbc:postgresql://my.domain.com";
6775
private static final String PG_CONNECTION_STRING =
6876
"jdbc:aws-wrapper:postgresql://instance-0.XYZ.us-east-2.rds.amazonaws.com";
6977
private static final int TEST_PORT = 5432;
7078
private final HostSpec writerHostSpec = new HostSpec("instance-0", TEST_PORT);
7179

7280
@Mock private PluginService mockPluginService;
81+
@Mock private ConnectionPluginManager mockConnectionPluginManager;
82+
@Mock private HostListProviderService mockHostListProviderService;
83+
@Mock private PluginManagerService mockPluginManagerService;
7384
@Mock ConnectionProvider mockConnectionProvider;
7485
@Mock Connection mockConnection;
7586
@Mock Statement mockStatement;
@@ -89,6 +100,11 @@ public static void main(String[] args) throws RunnerException {
89100
@Setup(Level.Iteration)
90101
public void setUpIteration() throws Exception {
91102
closeable = MockitoAnnotations.openMocks(this);
103+
when(mockConnectionPluginManager.connect(any(), any(), any(Properties.class), anyBoolean()))
104+
.thenReturn(mockConnection);
105+
when(mockConnectionPluginManager.execute(
106+
any(), any(), any(), eq("Connection.createStatement"), any(), any()))
107+
.thenReturn(mockStatement);
92108
when(mockConnectionProvider.connect(anyString(), any(Properties.class))).thenReturn(
93109
mockConnection);
94110
when(mockConnectionProvider.connect(anyString(), any(Dialect.class), any(HostSpec.class), any(Properties.class)))
@@ -101,6 +117,7 @@ public void setUpIteration() throws Exception {
101117
.thenReturn("instance-0", "instance-1");
102118
when(mockResultSet.getStatement()).thenReturn(mockStatement);
103119
when(mockStatement.getConnection()).thenReturn(mockConnection);
120+
when(this.mockPluginService.acceptsStrategy(any(), eq("random"))).thenReturn(true);
104121
when(this.mockPluginService.getCurrentHostSpec()).thenReturn(writerHostSpec);
105122
}
106123

@@ -110,48 +127,60 @@ public void tearDownIteration() throws Exception {
110127
}
111128

112129
@Benchmark
113-
public void initAndReleaseBaseLine() throws SQLException {
130+
public void initAndReleaseBaseLine() {
114131
}
115132

116133
@Benchmark
117134
public ConnectionWrapper initAndReleaseWithExecutionTimePlugin() throws SQLException {
118-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
135+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
119136
useExecutionTimePlugin(),
120137
CONNECTION_STRING,
121-
mockConnectionProvider)) {
138+
mockConnectionPluginManager,
139+
mockPluginService,
140+
mockHostListProviderService,
141+
mockPluginManagerService)) {
122142
wrapper.releaseResources();
123143
return wrapper;
124144
}
125145
}
126146

127147
@Benchmark
128148
public ConnectionWrapper initAndReleaseWithAuroraHostListPlugin() throws SQLException {
129-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
149+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
130150
useAuroraHostListPlugin(),
131151
CONNECTION_STRING,
132-
mockConnectionProvider)) {
152+
mockConnectionPluginManager,
153+
mockPluginService,
154+
mockHostListProviderService,
155+
mockPluginManagerService)) {
133156
wrapper.releaseResources();
134157
return wrapper;
135158
}
136159
}
137160

138161
@Benchmark
139162
public ConnectionWrapper initAndReleaseWithExecutionTimeAndAuroraHostListPlugins() throws SQLException {
140-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
163+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
141164
useExecutionTimeAndAuroraHostListPlugins(),
142165
CONNECTION_STRING,
143-
mockConnectionProvider)) {
166+
mockConnectionPluginManager,
167+
mockPluginService,
168+
mockHostListProviderService,
169+
mockPluginManagerService)) {
144170
wrapper.releaseResources();
145171
return wrapper;
146172
}
147173
}
148174

149175
@Benchmark
150176
public ConnectionWrapper initAndReleaseWithReadWriteSplittingPlugin() throws SQLException {
151-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
177+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
152178
useReadWriteSplittingPlugin(),
153179
CONNECTION_STRING,
154-
mockConnectionProvider)) {
180+
mockConnectionPluginManager,
181+
mockPluginService,
182+
mockHostListProviderService,
183+
mockPluginManagerService)) {
155184
wrapper.releaseResources();
156185
return wrapper;
157186
}
@@ -160,46 +189,66 @@ public ConnectionWrapper initAndReleaseWithReadWriteSplittingPlugin() throws SQL
160189
@Benchmark
161190
public ConnectionWrapper initAndReleaseWithAuroraHostListAndReadWriteSplittingPlugin()
162191
throws SQLException {
163-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
192+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
164193
useAuroraHostListAndReadWriteSplittingPlugin(),
165194
PG_CONNECTION_STRING,
166-
mockConnectionProvider)) {
195+
mockConnectionPluginManager,
196+
mockPluginService,
197+
mockHostListProviderService,
198+
mockPluginManagerService)) {
167199
wrapper.releaseResources();
168200
return wrapper;
169201
}
170202
}
171203

172204
@Benchmark
173-
public ConnectionWrapper initAndReleaseWithReadWriteSplittingPluginWithReaderLoadBalancing()
174-
throws SQLException {
175-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
176-
useReadWriteSplittingPluginWithReaderLoadBalancing(),
205+
public ConnectionWrapper initAndReleaseWithReadWriteSplittingPlugin_internalConnectionPools() throws SQLException {
206+
HikariPooledConnectionProvider provider =
207+
new HikariPooledConnectionProvider((hostSpec, props) -> new HikariConfig());
208+
ConnectionProviderManager.setConnectionProvider(provider);
209+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
210+
useReadWriteSplittingPlugin(),
177211
CONNECTION_STRING,
178-
mockConnectionProvider)) {
212+
mockConnectionPluginManager,
213+
mockPluginService,
214+
mockHostListProviderService,
215+
mockPluginManagerService)) {
179216
wrapper.releaseResources();
217+
ConnectionProviderManager.releaseResources();
218+
ConnectionProviderManager.resetProvider();
180219
return wrapper;
181220
}
182221
}
183222

184223
@Benchmark
185-
public ConnectionWrapper
186-
initAndReleaseWithAuroraHostListAndReadWriteSplittingPluginWithReaderLoadBalancing()
224+
public ConnectionWrapper initAndReleaseWithAuroraHostListAndReadWriteSplittingPlugin_internalConnectionPools()
187225
throws SQLException {
188-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
189-
useAuroraHostListAndReadWriteSplittingPluginWithReaderLoadBalancing(),
226+
HikariPooledConnectionProvider provider =
227+
new HikariPooledConnectionProvider((hostSpec, props) -> new HikariConfig());
228+
ConnectionProviderManager.setConnectionProvider(provider);
229+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
230+
useAuroraHostListAndReadWriteSplittingPlugin(),
190231
PG_CONNECTION_STRING,
191-
mockConnectionProvider)) {
232+
mockConnectionPluginManager,
233+
mockPluginService,
234+
mockHostListProviderService,
235+
mockPluginManagerService)) {
192236
wrapper.releaseResources();
237+
ConnectionProviderManager.releaseResources();
238+
ConnectionProviderManager.resetProvider();
193239
return wrapper;
194240
}
195241
}
196242

197243
@Benchmark
198244
public Statement executeStatementBaseline() throws SQLException {
199-
try (ConnectionWrapper wrapper = new ConnectionWrapper(
245+
try (ConnectionWrapper wrapper = new TestConnectionWrapper(
200246
useExecutionTimePlugin(),
201247
CONNECTION_STRING,
202-
mockConnectionProvider);
248+
mockConnectionPluginManager,
249+
mockPluginService,
250+
mockHostListProviderService,
251+
mockPluginManagerService);
203252
Statement statement = wrapper.createStatement()) {
204253
return statement;
205254
}
@@ -208,10 +257,13 @@ public Statement executeStatementBaseline() throws SQLException {
208257
@Benchmark
209258
public ResultSet executeStatementWithExecutionTimePlugin() throws SQLException {
210259
try (
211-
ConnectionWrapper wrapper = new ConnectionWrapper(
260+
ConnectionWrapper wrapper = new TestConnectionWrapper(
212261
useExecutionTimePlugin(),
213262
CONNECTION_STRING,
214-
mockConnectionProvider);
263+
mockConnectionPluginManager,
264+
mockPluginService,
265+
mockHostListProviderService,
266+
mockPluginManagerService);
215267
Statement statement = wrapper.createStatement();
216268
ResultSet resultSet = statement.executeQuery("some sql")) {
217269
return resultSet;
@@ -247,18 +299,4 @@ Properties useAuroraHostListAndReadWriteSplittingPlugin() {
247299
properties.setProperty("wrapperPlugins", "auroraHostList,readWriteSplitting");
248300
return properties;
249301
}
250-
251-
Properties useReadWriteSplittingPluginWithReaderLoadBalancing() {
252-
final Properties properties = new Properties();
253-
properties.setProperty("wrapperPlugins", "readWriteSplitting");
254-
properties.setProperty("loadBalanceReadOnlyTraffic", "true");
255-
return properties;
256-
}
257-
258-
Properties useAuroraHostListAndReadWriteSplittingPluginWithReaderLoadBalancing() {
259-
final Properties properties = new Properties();
260-
properties.setProperty("wrapperPlugins", "auroraHostList,readWriteSplitting");
261-
properties.setProperty("loadBalanceReadOnlyTraffic", "true");
262-
return properties;
263-
}
264302
}

benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/BenchmarkPlugin.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@
2626
import java.util.Map;
2727
import java.util.Properties;
2828
import java.util.Set;
29-
import java.util.logging.Level;
3029
import java.util.logging.Logger;
31-
3230
import software.amazon.jdbc.ConnectionPlugin;
3331
import software.amazon.jdbc.HostListProviderService;
32+
import software.amazon.jdbc.HostRole;
3433
import software.amazon.jdbc.HostSpec;
3534
import software.amazon.jdbc.JdbcCallable;
3635
import software.amazon.jdbc.NodeChangeOptions;
@@ -60,11 +59,32 @@ public <T, E extends Exception> T execute(Class<T> resultClass, Class<E> excepti
6059
public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props,
6160
boolean isInitialConnection, JdbcCallable<Connection, SQLException> connectFunc)
6261
throws SQLException {
63-
LOGGER.finer(() -> String.format("connect=''%s''", driverProtocol));
62+
LOGGER.finer(() -> String.format("connect=''%s''", hostSpec.getHost()));
6463
resources.add("connect");
6564
return connectFunc.call();
6665
}
6766

67+
@Override
68+
public Connection forceConnect(String driverProtocol, HostSpec hostSpec, Properties props,
69+
boolean isInitialConnection, JdbcCallable<Connection, SQLException> forceConnectFunc)
70+
throws SQLException {
71+
LOGGER.finer(() -> String.format("forceConnect=''%s''", hostSpec.getHost()));
72+
resources.add("forceConnect");
73+
return forceConnectFunc.call();
74+
}
75+
76+
@Override
77+
public boolean acceptsStrategy(HostRole role, String strategy) {
78+
return false;
79+
}
80+
81+
@Override
82+
public HostSpec getHostSpecByStrategy(HostRole role, String strategy) {
83+
LOGGER.finer(() -> String.format("getHostSpecByStrategy=''%s''", strategy));
84+
resources.add("getHostSpecByStrategy");
85+
return new HostSpec("host", 1234, role);
86+
}
87+
6888
@Override
6989
public void initHostProvider(String driverProtocol, String initialUrl, Properties props,
7090
HostListProviderService hostListProviderService,

0 commit comments

Comments
 (0)