[improve] support reuse jdbc connection switch (#3101)

Signed-off-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: aias00 <rokkki@163.com>
This commit is contained in:
tomsun28
2025-03-05 21:07:06 +08:00
committed by GitHub
co-authored by aias00
parent a5f874e682
commit b7bd9eb305
13 changed files with 90 additions and 48 deletions
+9
View File
@@ -2298,6 +2298,15 @@
"contributions": [
"code"
]
},
{
"login": "yasminvo",
"name": "yasminvo",
"avatar_url": "https://avatars.githubusercontent.com/u/107528848?v=4",
"profile": "https://github.com/yasminvo",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
+1
View File
@@ -507,6 +507,7 @@ Thanks to these wonderful people, welcome to join us:
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myangle1120"><img src="https://avatars.githubusercontent.com/u/19237013?v=4?s=100" width="100px;" alt="myangle1120"/><br /><sub><b>myangle1120</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=myangle1120" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yasminvo"><img src="https://avatars.githubusercontent.com/u/107528848?v=4?s=100" width="100px;" alt="yasminvo"/><br /><sub><b>yasminvo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yasminvo" title="Code">💻</a></td>
</tr>
</tbody>
</table>
+1
View File
@@ -506,6 +506,7 @@ Thanks these wonderful people, welcome to join us:
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myangle1120"><img src="https://avatars.githubusercontent.com/u/19237013?v=4?s=100" width="100px;" alt="myangle1120"/><br /><sub><b>myangle1120</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=myangle1120" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yasminvo"><img src="https://avatars.githubusercontent.com/u/107528848?v=4?s=100" width="100px;" alt="yasminvo"/><br /><sub><b>yasminvo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yasminvo" title="Code">💻</a></td>
</tr>
</tbody>
</table>
@@ -88,6 +88,7 @@ public class JdbcCommonCollect extends AbstractCollect {
SshTunnel sshTunnel = jdbcProtocol.getSshTunnel();
int timeout = CollectUtil.getTimeout(jdbcProtocol.getTimeout());
boolean reuseConnection = Boolean.parseBoolean(jdbcProtocol.getReuseConnection());
Statement statement = null;
String databaseUrl;
try {
@@ -99,7 +100,7 @@ public class JdbcCommonCollect extends AbstractCollect {
}
statement = getConnection(jdbcProtocol.getUsername(),
jdbcProtocol.getPassword(), databaseUrl, timeout);
jdbcProtocol.getPassword(), databaseUrl, timeout, reuseConnection);
switch (jdbcProtocol.getQueryType()) {
case QUERY_TYPE_ONE_ROW -> queryOneRow(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
case QUERY_TYPE_MULTI_ROW -> queryMultiRow(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
@@ -142,11 +143,20 @@ public class JdbcCommonCollect extends AbstractCollect {
builder.setMsg("Query Error: " + errorMessage);
} finally {
if (statement != null) {
Connection connection = null;
try {
connection = statement.getConnection();
statement.close();
} catch (Exception e) {
log.error("Jdbc close statement error: {}", e.getMessage());
}
try {
if (!reuseConnection && connection != null) {
connection.close();
}
} catch (Exception e) {
log.error("Jdbc close connection error: {}", e.getMessage());
}
}
}
}
@@ -157,38 +167,40 @@ public class JdbcCommonCollect extends AbstractCollect {
}
private Statement getConnection(String username, String password, String url, Integer timeout) throws Exception {
private Statement getConnection(String username, String password, String url, Integer timeout, boolean reuseConnection) throws Exception {
CacheIdentifier identifier = CacheIdentifier.builder()
.ip(url)
.username(username).password(password).build();
Optional<AbstractConnection<?>> cacheOption = connectionCommonCache.getCache(identifier, true);
Statement statement = null;
if (cacheOption.isPresent()) {
JdbcConnect jdbcConnect = (JdbcConnect) cacheOption.get();
try {
statement = jdbcConnect.getConnection().createStatement();
// set query timeout
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
// set query max row number
statement.setMaxRows(1000);
} catch (Exception e) {
log.info("The jdbc connect from cache, create statement error: {}", e.getMessage());
if (reuseConnection) {
Optional<AbstractConnection<?>> cacheOption = connectionCommonCache.getCache(identifier, true);
if (cacheOption.isPresent()) {
JdbcConnect jdbcConnect = (JdbcConnect) cacheOption.get();
try {
if (statement != null) {
statement.close();
statement = jdbcConnect.getConnection().createStatement();
// set query timeout
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
// set query max row number
statement.setMaxRows(1000);
} catch (Exception e) {
log.info("The jdbc connect from cache, create statement error: {}", e.getMessage());
try {
if (statement != null) {
statement.close();
}
jdbcConnect.close();
} catch (Exception e2) {
log.error(e2.getMessage());
}
jdbcConnect.close();
} catch (Exception e2) {
log.error(e2.getMessage());
statement = null;
connectionCommonCache.removeCache(identifier);
}
statement = null;
connectionCommonCache.removeCache(identifier);
}
}
if (statement != null) {
return statement;
if (statement != null) {
return statement;
}
}
// renew connection when failed
Connection connection = DriverManager.getConnection(url, username, password);
@@ -198,8 +210,10 @@ public class JdbcCommonCollect extends AbstractCollect {
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
statement.setMaxRows(1000);
JdbcConnect jdbcConnect = new JdbcConnect(connection);
connectionCommonCache.addCache(identifier, jdbcConnect);
if (reuseConnection) {
JdbcConnect jdbcConnect = new JdbcConnect(connection);
connectionCommonCache.addCache(identifier, jdbcConnect);
}
return statement;
}
@@ -71,7 +71,10 @@ public class JdbcProtocol implements CommonRequestProtocol, Protocol {
* DATABASE LINK URL eg: jdbc:mysql://localhost:3306/usthe
*/
private String url;
/**
* reuse connection session
*/
private String reuseConnection = "true";
/**
* ssh tunnel
*/
@@ -64,6 +64,13 @@ params:
required: false
hide: true
defaultValue: 6000
- field: reuseConnection
name:
zh-CN: 复用连接
en-US: Reuse Connection
type: boolean
required: false
defaultValue: true
- field: database
name:
zh-CN: 服务名
@@ -158,6 +165,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
# SQL Query MethodoneRow, multiRow, columns
queryType: oneRow
# sql
@@ -213,8 +221,8 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: multiRow
sql: select file_id, file_name, tablespace_name, status, bytes / 1024 / 1024 as bytes, blocks from dba_data_files
url: ^_^url^_^
@@ -238,6 +246,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: oneRow
sql: select count(*) as count from v$session
url: ^_^url^_^
@@ -262,6 +271,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: oneRow
sql: select count(*) as count from v$session where username is not null and status = 'ACTIVE'
url: ^_^url^_^
@@ -286,6 +296,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: oneRow
sql: select count(*) as count from v$session where username is null
url: ^_^url^_^
@@ -316,6 +327,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: oneRow
sql: SELECT username, count( username ) as count FROM v$session WHERE username IS NOT NULL GROUP BY username
url: ^_^url^_^
@@ -361,6 +373,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: columns
sql: select metric_name, value from gv$sysmetric where metric_name = 'I/O Megabytes per Second' or metric_name = 'User Transaction Per Sec' or metric_name = 'I/O Requests per Second'
url: ^_^url^_^
@@ -414,6 +427,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: multiRow
# DBA_TABLESPACE_USAGE_METRICS可以查出表空间used_max值,它的大小计算单位是block1kb=8block,把block*8/1024转化为MB单位
sql: "SELECT tablespace_name,ROUND ( (TABLESPACE_SIZE * 8 / 1024), 0) AS total,ROUND ( (USED_SPACE * 8 / 1024), 0) AS used,ROUND ( ( (TABLESPACE_SIZE * 8 / 1024) - (USED_SPACE * 8 / 1024)), 0) AS free,ROUND ( (USED_PERCENT), 0) AS used_percentage,100 - ROUND ( (USED_PERCENT), 0) AS free_percentage FROM sys.dba_tablespace_usage_metrics ORDER BY used_percent DESC"
@@ -439,6 +453,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: oneRow
sql: select count(*) as process_count from v$process
url: ^_^url^_^
@@ -476,6 +491,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: columns
sql: select metric_name, value from gv$sysmetric where metric_name = 'User Commits Per Sec' or metric_name = 'User Rollbacks Per Sec'
url: ^_^url^_^
@@ -561,6 +577,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: columns
sql: select wait_class, sum(time_waited) total_wait_time from v$active_session_history where session_state = 'WAITING' GROUP BY wait_class ORDER BY total_wait_time DESC
url: ^_^url^_^
@@ -591,6 +608,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: multiRow
sql: select stat_name as type, value as num from v$osstat where stat_name like '%CPU%' or stat_name like '%TIME'
url: ^_^url^_^
@@ -621,6 +639,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: multiRow
sql: select stat_name as type, value as num from v$osstat where stat_name like '%BYTES'
url: ^_^url^_^
@@ -656,6 +675,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: columns
sql: select metric_name, value from gv$sysmetric where metric_name like '%Cache Hit Ratio' order by end_time asc
url: ^_^url^_^
@@ -733,6 +753,7 @@ metrics:
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
reuseConnection: ^_^reuseConnection^_^
queryType: multiRow
sql: SELECT * FROM (SELECT sql_id, child_number, executions, ROUND(CASE WHEN executions = 0 THEN NULL ELSE elapsed_time / (executions*1000000) END,4) AS per_secs, cpu_time / 1000000 AS cpu_secs, buffer_gets, disk_reads, fetches, parse_calls, optimizer_cost, sql_text FROM v$sql ) where rownum <= 10 ORDER BY per_secs DESC
url: ^_^url^_^
+2 -4
View File
@@ -68,11 +68,9 @@ Even small corrections to typos are very welcome :)
4. Install Dependencies: `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
5. Install angular-cli globally: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
5. After the local backend is started, start the local frontend in the web-app directory: `yarn start`
6. After the local backend is started, start the local frontend in the web-app directory: `ng serve --open`
7. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
6. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
### Find tasks
+2 -4
View File
@@ -28,11 +28,9 @@ sidebar_label: Development
4. Install Dependencies: `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
5. Install angular-cli globally: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
5. After the local backend is started, start the local frontend in the web-app directory: `yarn start`
6. After the local backend is started, start the local frontend in the web-app directory: `ng serve --open`
7. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
6. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
## Build HertzBeat binary package
@@ -72,11 +72,9 @@ limitations under the License.
4. 在前端工程目录 `web-app` 下执行: `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
5. 全局安装 `angular-cli`: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
5. 待本地后端启动后,在 web-app 目录下启动本地前端 `yarn start`
6. 待本地后端启动后,在 web-app 目录下启动本地前端 `ng serve --open`
7. 浏览器访问 localhost:4200 即可开始,默认账号密码 **admin/hertzbeat**
6. 浏览器访问 localhost:4200 即可开始,默认账号密码 **admin/hertzbeat**
### 寻找任务
@@ -31,11 +31,9 @@ sidebar_label: 运行编译
4. 在前端工程目录 `web-app` 下执行: `yarn install` 或者 `yarn install --registry=https://registry.npmmirror.com`
5. 全局安装 `angular-cli`: `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
5. 待本地后端启动后,在web-app目录下启动本地前端 `yarn start`
6. 待本地后端启动后,在web-app目录下启动本地前端 `ng serve --open`
7. 浏览器访问 localhost:4200 即可开始,默认账号密码 admin/hertzbeat
6. 浏览器访问 localhost:4200 即可开始,默认账号密码 admin/hertzbeat
## 生成二进制包
+1
View File
@@ -445,6 +445,7 @@ export default function () {
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myangle1120"><img src="https://avatars.githubusercontent.com/u/19237013?v=4?s=100" width="100px;" alt="myangle1120"/><br /><sub><b>myangle1120</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=myangle1120" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yasminvo"><img src="https://avatars.githubusercontent.com/u/107528848?v=4?s=100" width="100px;" alt="yasminvo"/><br /><sub><b>yasminvo</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=yasminvo" title="Code">💻</a></td>
</tr>
</tbody>
</table>
+1
View File
@@ -14,6 +14,7 @@
"aliveStatusCodes": [
0,
200,
400,
401,
403
]
+2 -3
View File
@@ -9,9 +9,8 @@
1. Need `Node Yarn` Environment, Make sure `Node.js >= 18`
2. Install yarn if not existed `npm install -g yarn`
3. Execute `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
4. Install angular-cli : `yarn global add @angular/cli@15` or `yarn global add @angular/cli@15 --registry=https://registry.npmmirror.com`
5. Start After Backend Server Available : `yarn start`
3. Execute `yarn install` or `yarn install --registry=https://registry.npmmirror.com` in `web-app`
4. Start After Backend Server Available : `yarn start`
### Build HertzBeat Install Package