java - leakdetectionthreshold - ¿Cómo configuro HikariCP en mi aplicación Spring Boot en mis archivos application.properties?
spring boot jdbctemplate mysql (12)
Aquí están las buenas noticias. HikariCP es el grupo de conexiones predeterminado ahora con Spring Boot 2.0.0.
Notas de la versión de Spring Boot 2.0.0
La tecnología de agrupación de base de datos predeterminada en Spring Boot 2.0 se ha cambiado de Tomcat Pool a HikariCP. Descubrimos que Hakari ofrece un rendimiento superior, y muchos de nuestros usuarios lo prefieren a Tomcat Pool.
Estoy intentando configurar HikariCP en mi aplicación Spring Boot (1.2.0.M1) para que pueda probar su uso en lugar de Tomcat DBCP. Me gustaría configurar el grupo de conexiones en mi archivo application.properties como lo estaba haciendo con Tomcat, pero no puedo entender cómo debería hacerlo. Todos los ejemplos que he encontrado muestran el estilo JavaConfig o el uso de un archivo de propiedades HikariCP separado. ¿Alguien puede ayudarme a descubrir los nombres de las propiedades para configurarlo en application.properties? También me gustaría cambiar el uso del enfoque driverClassName al enfoque DataSourceClassName, ya que se ve más limpio y se recomienda. ¿Esto también es posible en mi archivo application.properties?
Esto es lo que tenía para Tomcat DBCP (solo algunas configuraciones básicas, no completamente descartadas)
spring.datasource.validation-query=SELECT 1
spring.datasource.max-active=10
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=5
spring.datasource.test-on-borrow=true
spring.datasource.test-on-return=true
Y actualmente estoy usando driverClassName y jdbc url para configurar la conexión:
spring.datasource.url=jdbc:mysql://localhost:3306/myDb
spring.datasource.driverClassName=com.mysql.jdbc.Driver
Así que resulta que casi todas las configuraciones predeterminadas para HikariCP funcionan para mí, excepto el número de conexiones de base de datos. Establecí esa propiedad en mi application.properties:
spring.datasource.maximumPoolSize=20
Y Andy Wilkinson tiene razón en lo que puedo decir, ya que no se puede usar el enfoque de configuración dataSourceClassName para HikariCP con Spring Boot.
Con las últimas versiones de arranque de primavera, cambiarse a Hikari puede hacerse completamente en configuración. Estoy usando 1.5.6.RELEASE
y este enfoque funciona.
build.gradle:
compile "com.zaxxer:HikariCP:2.7.3"
aplicación YAML
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
hikari:
idleTimeout: 60000
minimumIdle: 2
maximumPoolSize: 20
connectionTimeout: 30000
poolName: MyPoolName
connectionTestQuery: SELECT 1
Cambie connectionTestQuery
para adaptarse a su base de datos subyacente. Eso es todo, no se requiere código.
De acuerdo con la documentación, se cambia,
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html
Ejemplo:
spring:
datasource:
url: ''jdbc:mysql://localhost/db?useSSL=false''
username: root
password: pass
driver: com.mysql.jdbc.Driver
hikari:
minIdle: 10
idle-timeout: 10000
maximumPoolSize: 30
Estos son los siguientes cambios de configuración que podemos hacer en hikari, por favor agregue / actualice de acuerdo a su necesidad.
autoCommit
connectionTimeout
idleTimeout
maxLifetime
connectionTestQuery
connectionInitSql
validationTimeout
maximumPoolSize
poolName
allowPoolSuspension
readOnly
transactionIsolation
leakDetectionThreshold
Esto funciona para mi aplicación de arranque en caso de que ayude. Esta clase le dice qué propiedades está buscando el objeto de configuración:
Creo que varias fuentes de datos podrían ser compatibles al agregar datasource_whatever
a las claves de propiedad en el archivo de configuración de origen. ¡Aclamaciones!
@Configuration
class DataSourceConfig {
@Value(''${spring.datasource.username}'')
private String user;
@Value(''${spring.datasource.password}'')
private String password;
@Value(''${spring.datasource.url}'')
private String dataSourceUrl;
@Value(''${spring.datasource.dataSourceClassName}'')
private String dataSourceClassName;
@Value(''${spring.datasource.connectionTimeout}'')
private int connectionTimeout;
@Value(''${spring.datasource.maxLifetime}'')
private int maxLifetime;
@Bean
public DataSource primaryDataSource() {
Properties dsProps = [url: dataSourceUrl, user: user, password: password]
Properties configProps = [
connectionTestQuery: ''select 1 from dual'',
connectionTimeout: connectionTimeout,
dataSourceClassName: dataSourceClassName,
dataSourceProperties: dsProps,
maxLifetime: maxLifetime
]
// A default max pool size of 10 seems reasonable for now, so no need to configure for now.
HikariConfig hc = new HikariConfig(configProps)
HikariDataSource ds = new HikariDataSource(hc)
ds
}
}
Me encontré con HikariCP
y me sorprendieron los puntos de referencia y quería probarlo en lugar de mi opción predeterminada C3P0
y, para mi sorpresa, tuve problemas para obtener las configurations
correctas, probablemente porque las configuraciones difieren según la combinación de tecnología que estés utilizando.
He configurado Spring Boot
proyecto Spring Boot
con JPA, Web, Security
starters (usando Spring Initializer ) para usar PostgreSQL
como una base de datos con HikariCP
como pooling de conexiones.
He utilizado Gradle
como herramienta de desarrollo y me gustaría compartir lo que funcionó para mí para las siguientes suposiciones:
- Spring Boot Starter JPA (web y seguridad - opcional)
- La construcción de Gradle también
- PostgreSQL se ejecuta y configura con una base de datos (es decir, esquema, usuario, db)
Necesita el siguiente build.gradle
si está usando Gradle
o su equivalente pom.xml
si está utilizando maven
buildscript {
ext {
springBootVersion = ''1.5.8.RELEASE''
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: ''java''
apply plugin: ''eclipse''
apply plugin: ''org.springframework.boot''
apply plugin: ''war''
group = ''com''
version = ''1.0''
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile(''org.springframework.boot:spring-boot-starter-aop'')
// Exclude the tomcat-jdbc since it''s used as default for connection pooling
// This can also be achieved by setting the spring.datasource.type to HikariCP
// datasource see application.properties below
compile(''org.springframework.boot:spring-boot-starter-data-jpa'') {
exclude group: ''org.apache.tomcat'', module: ''tomcat-jdbc''
}
compile(''org.springframework.boot:spring-boot-starter-security'')
compile(''org.springframework.boot:spring-boot-starter-web'')
runtime(''org.postgresql:postgresql'')
testCompile(''org.springframework.boot:spring-boot-starter-test'')
testCompile(''org.springframework.security:spring-security-test'')
// Download HikariCP but, exclude hibernate-core to avoid version conflicts
compile(''com.zaxxer:HikariCP:2.5.1'') {
exclude group: ''org.hibernate'', module: ''hibernate-core''
}
// Need this in order to get the HikariCPConnectionProvider
compile(''org.hibernate:hibernate-hikaricp:5.2.11.Final'') {
exclude group: ''com.zaxxer'', module: ''HikariCP''
exclude group: ''org.hibernate'', module: ''hibernate-core''
}
}
Hay un montón de build.gradle
en el build.gradle
anterior y eso es porque
- Primero excluya, instruye a gradle que excluye el grupo de conexiones
jdbc-tomcat
al descargar las dependenciasspring-boot-starter-data-jpa
. Esto se puede lograr configurandospring.datasource.type=com.zaxxer.hikari.HikariDataSource
también, pero no quiero una dependencia adicional si no lo necesito - La segunda exclusión, indica a Gradle que excluya
hibernate-core
al descargar la dependencia decom.zaxxer
y eso es porquehibernate-core
ya se ha descargado conSpring Boot
y no queremos terminar con versiones diferentes. - Third exclude, indica a gradle que excluya
hibernate-core
al descargar el módulohibernate-hikaricp
, que es necesario para hacer que HikariCP useorg.hibernate.hikaricp.internal.HikariCPConnectionProvider
como proveedor de conexión en lugar de obsoletocom.zaxxer.hikari.hibernate.HikariConnectionProvider
Una vez que descubrí build.gradle
y qué conservar y qué no, estaba listo para copiar / pegar una configuración de datasource
en mis application.properties
y esperaba que todo funcionara a la build.gradle
, pero no realmente, y tropecé con lo siguiente cuestiones
- Spring boot falla al descubrir los detalles de la base de datos (es decir, url, driver), por lo tanto, no es capaz de configurar jpa e hibernate (porque no nombré correctamente los valores de la clave de propiedad)
- HikariCP vuelve a caer en
com.zaxxer.hikari.hibernate.HikariConnectionProvider
- Después de indicarle a Spring que usara un nuevo proveedor de conexión para la configuración automática de hibernate / jpa, HikariCP falló porque estaba buscando alguna
key/value
enapplication.properties
y se quejaba dedataSource, dataSourceClassName, jdbcUrl
. Tuve que depurar enHikariConfig, HikariConfigurationUtil, HikariCPConnectionProvider
y descubrí queHikariCP
no podía encontrar las propiedades deapplication.properties
porque tenía un nombre diferente.
De todos modos, aquí es donde tuve que confiar en prueba y error y asegurarme de que HikariCP
pueda elegir las propiedades (es decir, el origen de datos que es datos de DB, así como las propiedades de agrupamiento), así como Sping Boot se comportó como se esperaba y terminé con el siguiente archivo application.properties
.
server.contextPath=/
debug=true
# Spring data source needed for Spring boot to behave
# Pre Spring Boot v2.0.0.M6 without below Spring Boot defaults to tomcat-jdbc connection pool included
# in spring-boot-starter-jdbc and as compiled dependency under spring-boot-starter-data-jpa
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:postgresql://localhost:5432/somedb
spring.datasource.username=dbuser
spring.datasource.password=dbpassword
# Hikari will use the above plus the following to setup connection pooling
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.poolName=SpringBootJPAHikariCP
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.connectionTimeout=30000
# Without below HikariCP uses deprecated com.zaxxer.hikari.hibernate.HikariConnectionProvider
# Surprisingly enough below ConnectionProvider is in hibernate-hikaricp dependency and not hibernate-core
# So you need to pull that dependency but, make sure to exclude it''s transitive dependencies or you will end up
# with different versions of hibernate-core
spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
# JPA specific configs
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql=true
spring.jpa.properties.hibernate.id.new_generator_mappings=false
spring.jpa.properties.hibernate.default_schema=dbschema
spring.jpa.properties.hibernate.search.autoregister_listeners=false
spring.jpa.properties.hibernate.bytecode.use_reflection_optimizer=false
# Enable logging to verify that HikariCP is used, the second entry is specific to HikariCP
logging.level.org.hibernate.SQL=DEBUG
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
Como se muestra arriba, las configuraciones se dividen en categorías basadas en los siguientes patrones de nombres
- spring.datasource.x (Spring auto-configure elegirá estos, también lo hará HikariCP)
- spring.datasource.hikari.x (HikariCP los selecciona para configurar el grupo, anota los nombres de los campos camelCase)
- spring.jpa.hibernate.connection.provider_class ( indica a Spring que use el nuevo HibernateConnectionProvider)
- spring.jpa.properties.hibernate.x (Utilizado por Spring para autoconfigurar JPA, tome nota de los nombres de campo con guiones bajos)
Es difícil encontrar un tutorial o publicación o algún recurso que muestre cómo se usa el archivo de propiedades anterior y cómo deben nombrarse las propiedades. Bueno, ahí lo tienes.
Lanzar las application.properties
anteriores con build.gradle
(o al menos similar) en una versión del proyecto Spring Boot JPA (1.5.8) debería funcionar como un amuleto y conectarse a su base de datos preconfigurada (es decir, en mi caso es PostgreSQL que ambas HikariCP & Spring
cuenta de spring.datasource.url
sobre qué controlador de base de datos usar).
No vi la necesidad de crear un bean DataSource
y eso es porque Spring Boot es capaz de hacer todo por mí con tan solo mirar en application.properties
y eso está bien.
El article en la wiki GitHub de HikariCP muestra cómo configurar Spring Boot con JPA, pero carece de explicación y detalles.
Los dos archivos anteriores también están disponibles como una idea pública https://gist.github.com/rhamedy/b3cb936061cc03acdfe21358b86a5bc6
Mi configuración:
Spring Boot v1.5.10
Hikari v.3.2.x (para evaluación)
Para comprender realmente la configuración de Hikari Data Source, recomiendo deshabilitar la configuración automática de Spring Boot para el origen de datos.
Agregue lo siguiente a application.properties:-
spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Esto deshabilitará la capacidad de Spring Boot para configurar DataSource por sí mismo.
Ahora tiene la oportunidad de definir su propia configuración personalizada para crear bean HikariDataSource y llenarlo con las propiedades deseadas.
NOTA :::
la clase pública HikariDataSource extiende HikariConfig
Necesitas
- rellene el objeto HikariConfig utilizando las propiedades de Hikari deseadas
- Inicialice el objeto HikariDataSource con el objeto HikariConfig pasado como argumento al constructor.
Creo en la definición de mi propia clase de configuración personalizada (@Configuration) para crear la fuente de datos por mi cuenta y llenarla con las propiedades de fuente de datos definidas en un archivo separado (que tradicional: application.properties)
De esta manera puedo definir mi propia sessionFactory Bean usando la clase Hibernate recomendada: "LocalSessionFactoryBean" y rellenarla con su Hikari Data Source> y otras propiedades basadas en Hiberante-JPA.
Resumen de las propiedades de Hikari DataSource basadas en Spring Boot: -
spring.datasource.hikari.allow-pool-suspension = true
spring.datasource.hikari.auto-commit = false
spring.datasource.hikari.catalog =
spring.datasource.hikari.connection-init-sql =
spring.datasource.hikari.connection-test-query =
spring.datasource.hikari.connection-timeout = 100
spring.datasource.hikari.data-source-class-name =
spring.datasource.hikari.data-source-jndi =
spring.datasource.hikari.driver-class-name =
spring.datasource.hikari.idle-timeout = 50
spring.datasource.hikari.initialization-fail-fast = true
spring.datasource.hikari.isolate-internal-queries = true
spring.datasource.hikari.jdbc-url =
spring.datasource.hikari.leak-detection-threshold =
spring.datasource.hikari.login-timeout = 60
spring.datasource.hikari.max-lifetime =
spring.datasource.hikari.maximum-pool-size = 500
spring.datasource.hikari.minimum-idle = 30
spring.datasource.hikari.password =
spring.datasource.hikari.pool-name =
spring.datasource.hikari.read-only = true
spring.datasource.hikari.register-mbeans = true
spring.datasource.hikari.transaction-isolation =
spring.datasource.hikari.username =
spring.datasource.hikari.validation-timeout =
No necesita código redundante para poner valores de propiedad a variables. Puede establecer propiedades directamente con un archivo de propiedades.
Coloque el archivo hikari.properties
en classpath.
driverClassName=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/myDb
connectionTestQuery=SELECT 1
maximumPoolSize=20
username=...
password=...
Y crea un bean fuente de datos como este.
@Bean(destroyMethod = "close")
public DataSource dataSource() throws SQLException {
HikariConfig config = new HikariConfig("/hikari.properties");
HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
}
Puede usar el enfoque dataSourceClassName, aquí hay un ejemplo con MySQL. (Probado con arranque de primavera 1.3 y 1.4)
Primero, debe excluir tomcat-jdbc del classpath, ya que se seleccionará a favor de hikaricp.
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
application.properties
spring.datasource.dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
spring.datasource.dataSourceProperties.serverName=localhost
spring.datasource.dataSourceProperties.portNumber=3311
spring.datasource.dataSourceProperties.databaseName=mydb
spring.datasource.username=root
spring.datasource.password=root
Entonces solo agrega
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Creé un proyecto de prueba aquí: https://github.com/ydemartino/spring-boot-hikaricp
Simplemente puede hacer uso de application.yml / application.properties solamente. No es necesario crear explícitamente ningún DataSource
Bean
Necesita excluir tomcat-jdbc como lo menciona ydemartino
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
Como no creará DataSource
, debe especificar explícitamente el uso de Hikari a través de spring.datasource.type
con el valor com.zaxxer.hikari.HikariDataSource
en application.yml / application.properties
spring:
datasource:
hikari:
connection-test-query: SELECT 1 FROM DUAL
minimum-idle: 1
maximum-pool-size: 5
pool-name: yourPoolName
auto-commit: false
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/myDb
username: login
password: password
type: com.zaxxer.hikari.HikariDataSource
En su application.yml / application.properties, puede configurar los parámetros específicos de Hikari, como el tamaño de la agrupación, etc. en spring.datasource.hikari.*
no se puede usar el método dataSourceClassName en las configuraciones de application.properties como dice @Andy Wilkinson. si desea tener dataSourceClassName de todos modos, puede usar Java Config como:
@Configuration
@ComponentScan
class DataSourceConfig {
@Value("${spring.datasource.username}")
private String user;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.url}")
private String dataSourceUrl;
@Value("${spring.datasource.dataSourceClassName}")
private String dataSourceClassName;
@Value("${spring.datasource.poolName}")
private String poolName;
@Value("${spring.datasource.connectionTimeout}")
private int connectionTimeout;
@Value("${spring.datasource.maxLifetime}")
private int maxLifetime;
@Value("${spring.datasource.maximumPoolSize}")
private int maximumPoolSize;
@Value("${spring.datasource.minimumIdle}")
private int minimumIdle;
@Value("${spring.datasource.idleTimeout}")
private int idleTimeout;
@Bean
public DataSource primaryDataSource() {
Properties dsProps = new Properties();
dsProps.put("url", dataSourceUrl);
dsProps.put("user", user);
dsProps.put("password", password);
dsProps.put("prepStmtCacheSize",250);
dsProps.put("prepStmtCacheSqlLimit",2048);
dsProps.put("cachePrepStmts",Boolean.TRUE);
dsProps.put("useServerPrepStmts",Boolean.TRUE);
Properties configProps = new Properties();
configProps.put("dataSourceClassName", dataSourceClassName);
configProps.put("poolName",poolName);
configProps.put("maximumPoolSize",maximumPoolSize);
configProps.put("minimumIdle",minimumIdle);
configProps.put("minimumIdle",minimumIdle);
configProps.put("connectionTimeout", connectionTimeout);
configProps.put("idleTimeout", idleTimeout);
configProps.put("dataSourceProperties", dsProps);
HikariConfig hc = new HikariConfig(configProps);
HikariDataSource ds = new HikariDataSource(hc);
return ds;
}
}
razón por la que no puede usar dataSourceClassName porque lanzará y excepción
Caused by: java.lang.IllegalStateException: both driverClassName and dataSourceClassName are specified, one or the other should be used.
lo que significa que el arranque de primavera infringe la propiedad spring.datasource.url del controlador y, al mismo tiempo, establece dataSourceClassName y crea esta excepción. Para hacer las cosas bien, su application.properties debería tener un aspecto similar al de HikariCP Datasource:
# hikariCP
spring.jpa.databasePlatform=org.hibernate.dialect.MySQLDialect
spring.datasource.url=jdbc:mysql://localhost:3306/exampledb
spring.datasource.username=root
spring.datasource.password=
spring.datasource.poolName=SpringBootHikariCP
spring.datasource.maximumPoolSize=5
spring.datasource.minimumIdle=3
spring.datasource.maxLifetime=2000000
spring.datasource.connectionTimeout=30000
spring.datasource.idleTimeout=30000
spring.datasource.pool-prepared-statements=true
spring.datasource.max-open-prepared-statements=250
Nota: compruebe si hay algún tomcat-jdbc.jar o commons-dbcp.jar en su classpath agregado la mayoría de las veces por dependencia transitiva. Si están presentes en classpath, Spring Boot configurará el Datasource utilizando el grupo de conexiones predeterminado que es tomcat. HikariCP solo se usará para crear el origen de datos si no hay otro proveedor en el classpath. hay una secuencia alternativa de tomcat -> a HikariCP -> a Commons DBCP.
@Configuration
@ConfigurationProperties(prefix = "params.datasource")
public class JpaConfig extends HikariConfig {
@Bean
public DataSource dataSource() throws SQLException {
return new HikariDataSource(this);
}
}
application.yml
params:
datasource:
driverClassName: com.mysql.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/myDb
username: login
password: password
maximumPoolSize: 5
¡ACTUALIZADO! Desde la versión Spring Boot 1.3.0 :
- Solo agrega HikariCP a las dependencias
- Configurar application.yml
application.yml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:mem:TEST
driver-class-name: org.h2.Driver
username: username
password: password
hikari:
idle-timeout: 10000
¡ACTUALIZADO! Desde la versión Spring Boot 2.0.0 :
El grupo de conexiones predeterminado ha cambiado de Tomcat a Hikari :)