diff --git a/report-core/pom.xml b/report-core/pom.xml index a4fe0012..90ec8873 100644 --- a/report-core/pom.xml +++ b/report-core/pom.xml @@ -111,6 +111,11 @@ mysql-connector-java 8.0.28 + + com.alibaba + druid + 1.2.0 + org.flywaydb flyway-core diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java new file mode 100644 index 00000000..edbeafe8 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java @@ -0,0 +1,129 @@ +package com.anjiplus.template.gaea.business.config; + +import com.alibaba.druid.pool.DruidDataSource; +import com.anji.plus.gaea.exception.BusinessExceptionBuilder; +import lombok.Data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * Created by raod on 2024/10/21. + */ +@Component +@ConfigurationProperties(prefix = "spring.druid") +@Data +public class DruidProperties { + private static final Logger log = LoggerFactory.getLogger(DruidProperties.class); + /** + * 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 + */ + private int initialSize; + + /** + * 最小连接池数量 + */ + private int minIdle; + + /** + * 最大连接池数量 + */ + private int maxActive; + + /** + * 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置 + */ + private int maxWait; + + /** + * 关闭空闲连接的检测时间间隔.Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 + */ + private int timeBetweenEvictionRunsMillis; + + /** + * 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间 + */ + private int minEvictableIdleTimeMillis; + + private String validationQuery; + + /** + * 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRun + */ + private boolean testWhileIdle; + + private boolean testOnBorrow; + private boolean testOnReturn; + + /** + * 开启PSCache + */ + private boolean poolPreparedStatements; + + /** + * 设置PSCache值 + */ + private int maxPoolPreparedStatementPerConnectionSize; + + private String filters; + + private String connectionProperties; + private boolean useGlobalDataSourceStat; + private boolean statViewServletEnabled; + + /** + * 连接出错后再尝试连接三次 + */ + private int connectionErrorRetryAttempts; + + /** + * 数据库服务宕机自动重连机制 + */ + private boolean breakAfterAcquireFailure; + + /** + * 连接出错后重试时间间隔 + */ + private int timeBetweenConnectErrorMillis; + + public DruidDataSource dataSource(String url, String username, String password, String driverClassName){ + try { + DruidDataSource datasource = new DruidDataSource(); + datasource.setUrl(url); + datasource.setUsername(username); + datasource.setPassword(password); + datasource.setDriverClassName(driverClassName); + //configuration + datasource.setInitialSize(initialSize); + datasource.setMinIdle(minIdle); + datasource.setMaxActive(maxActive); + datasource.setMaxWait(maxWait); + + datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + if (driverClassName.contains("oracle")) { + datasource.setValidationQuery(validationQuery + " FROM DUAL"); + }else { + datasource.setValidationQuery(validationQuery); + } + datasource.setTestWhileIdle(testWhileIdle); + datasource.setTestOnBorrow(testOnBorrow); + datasource.setTestOnReturn(testOnReturn); + + datasource.setPoolPreparedStatements(poolPreparedStatements); + datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); + datasource.setFilters(filters); + datasource.setConnectionProperties(connectionProperties); + datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat); + + datasource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts); + datasource.setBreakAfterAcquireFailure(breakAfterAcquireFailure); + datasource.setTimeBetweenConnectErrorMillis(timeBetweenConnectErrorMillis); + return datasource; + } catch (Exception e) { + log.error("初始化数据源失败:", e); + throw BusinessExceptionBuilder.build("初始化数据源失败:" + e.getMessage()); + } + } +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasource/service/impl/JdbcServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasource/service/impl/JdbcServiceImpl.java index c9c7f98b..016bad3f 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasource/service/impl/JdbcServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasource/service/impl/JdbcServiceImpl.java @@ -1,9 +1,9 @@ package com.anjiplus.template.gaea.business.modules.datasource.service.impl; -import com.anjiplus.template.gaea.business.config.HikariPoolProperties; +import com.alibaba.druid.pool.DruidDataSource; +import com.anjiplus.template.gaea.business.config.DruidProperties; import com.anjiplus.template.gaea.business.modules.datasource.controller.dto.DataSourceDto; import com.anjiplus.template.gaea.business.modules.datasource.service.JdbcService; -import com.zaxxer.hikari.pool.HikariPool; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -21,22 +21,22 @@ import java.util.concurrent.ConcurrentHashMap; public class JdbcServiceImpl implements JdbcService { @Autowired - private HikariPoolProperties hikariPoolProperties; + private DruidProperties druidProperties; /** * 所有数据源的连接池存在map里 */ - private Map map = new ConcurrentHashMap<>(); + private Map map = new ConcurrentHashMap<>(); private Object lock = new Object(); - public HikariPool getJdbcConnectionPool(DataSourceDto dataSource) { + public DruidDataSource getJdbcConnectionPool(DataSourceDto dataSource) { if (map.containsKey(dataSource.getId())) { return map.get(dataSource.getId()); } else { try { synchronized (lock) { if (!map.containsKey(dataSource.getId())) { - HikariPool pool = hikariPoolProperties.dataSource(dataSource.getJdbcUrl(), + DruidDataSource pool = druidProperties.dataSource(dataSource.getJdbcUrl(), dataSource.getUsername(), dataSource.getPassword(), dataSource.getDriverName()); map.put(dataSource.getId(), pool); log.info("创建连接池成功:{}", dataSource.getJdbcUrl()); @@ -57,7 +57,7 @@ public class JdbcServiceImpl implements JdbcService { @Override public void removeJdbcConnectionPool(Long id) { try { - HikariPool pool = map.get(id); + DruidDataSource pool = map.get(id); if (pool != null) { log.info("remove pool success, datasourceId:{}", id); map.remove(id); @@ -77,7 +77,7 @@ public class JdbcServiceImpl implements JdbcService { */ @Override public Connection getPooledConnection(DataSourceDto dataSource) throws SQLException{ - HikariPool pool = getJdbcConnectionPool(dataSource); + DruidDataSource pool = getJdbcConnectionPool(dataSource); return pool.getConnection(); } @@ -91,7 +91,7 @@ public class JdbcServiceImpl implements JdbcService { */ @Override public Connection getUnPooledConnection(DataSourceDto dataSource) throws SQLException { - HikariPool druidDataSource = hikariPoolProperties.dataSource(dataSource.getJdbcUrl(), + DruidDataSource druidDataSource = druidProperties.dataSource(dataSource.getJdbcUrl(), dataSource.getUsername(), dataSource.getPassword(), dataSource.getDriverName()); return druidDataSource.getConnection(); } diff --git a/report-core/src/main/resources/bootstrap.yml b/report-core/src/main/resources/bootstrap.yml index 1d3e55bd..99f7baab 100644 --- a/report-core/src/main/resources/bootstrap.yml +++ b/report-core/src/main/resources/bootstrap.yml @@ -23,14 +23,39 @@ spring: url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: appuser@anji - type: com.zaxxer.hikari.HikariDataSource - hikari: - connection-timeout: 300000 # 连接超时时间 - 默认值:30秒。 - validation-timeout: 5000 # 连接被测试活动的最长时间 - 默认值:5秒。 - idle-timeout: 60000 # 连接池中允许闲置的最长时间 - 默认值:10分钟 - max-lifetime: 1800000 # 一个连接生命时长(毫秒),超时而没被使用则被释放 - 默认值:30分钟 - maximum-pool-size: 10 #连接池中允许的最大连接数,包括闲置和使用中的连接 - 默认值:10 - minimum-idle: 5 # 连接池中允许的最小空闲连接数 - 默认值:10。 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + #数据源连接池配置 + druid: + initial-size: 50 + min-idle: 50 + max-active: 100 + # 获取连接等待超时的时间 + max-wait: 5000 + # 配置间隔多久才进行一次检测 + time-between-eviction-runs-millis: 60000 + # 配置一个连接在池中最小生存时间 + min-evictable-idle-time-millis: 300000 + validation-query: select 1 + # 获取连接时执行检测,每次检测timeBetweenEvictionRunsMillis,空闲时间超过了minEvictableIdleTimeMillis则会直接剔除 + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭 + pool-prepared-statements: false + max-pool-prepared-statement-per-connection-size: 50 + filters: stat,wall + connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 + use-global-data-source-stat: true + #StatViewServlet配置 + stat-view-servlet.enabled: false + #注意:账号密码需修改 + stat-view-servlet.login-username: admin + stat-view-servlet.login-password: admin + stat-view-servlet.allow: "" + connectionErrorRetryAttempts: 3 # 连接出错后再尝试连接三次 + breakAfterAcquireFailure: true # 数据库服务宕机自动重连机制 + timeBetweenConnectErrorMillis: 300000 # 连接出错后重试时间间隔 #如果要使用redis,请参考report-core目录下的README.md文件中写的进行调整 # redis: @@ -39,7 +64,7 @@ spring: # password: root # database: 1 flyway: - enabled: true #是否开启flyway,默认true. + enabled: false #是否开启flyway(自动执行sql脚本),默认false baseline-on-migrate: true #数据库连接配置 url: ${spring.datasource.url}