test leakdetectionthreshold hikari example connectiontestquery borrow baeldung java spring spring-boot hikaricp

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:

https://github.com/brettwooldridge/HikariCP/blob/2.3.x/hikaricp-common/src/main/java/com/zaxxer/hikari/AbstractHikariConfig.java

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:

  1. Spring Boot Starter JPA (web y seguridad - opcional)
  2. La construcción de Gradle también
  3. 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

  1. Primero excluya, instruye a gradle que excluye el grupo de conexiones jdbc-tomcat al descargar las dependencias spring-boot-starter-data-jpa . Esto se puede lograr configurando spring.datasource.type=com.zaxxer.hikari.HikariDataSource también, pero no quiero una dependencia adicional si no lo necesito
  2. La segunda exclusión, indica a Gradle que excluya hibernate-core al descargar la dependencia de com.zaxxer y eso es porque hibernate-core ya se ha descargado con Spring Boot y no queremos terminar con versiones diferentes.
  3. Third exclude, indica a gradle que excluya hibernate-core al descargar el módulo hibernate-hikaricp , que es necesario para hacer que HikariCP use org.hibernate.hikaricp.internal.HikariCPConnectionProvider como proveedor de conexión en lugar de obsoleto com.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 en application.properties y se quejaba de dataSource, dataSourceClassName, jdbcUrl . Tuve que depurar en HikariConfig, HikariConfigurationUtil, HikariCPConnectionProvider y descubrí que HikariCP no podía encontrar las propiedades de application.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

  1. rellene el objeto HikariConfig utilizando las propiedades de Hikari deseadas
  2. 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 :

  1. Solo agrega HikariCP a las dependencias
  2. 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 :)