背景

公司项目用到了HikariCP连接池,配置了一堆参数我也看不懂,正好在BI这一块需要优化,我就从连接池下手看下有没有需要的优化项(主要是优化配置),然后看了一遍官网总结了一下

https://github.com/brettwooldridge/HikariCP HikariCP文档所在地址

代码构建连接池

1、直接代码构建

HikariDataSource ds = new HikariDataSource();
 ds.setJdbcUrl(“jdbc:mysql://localhost:3306/simpsons”);
 ds.setUsername(“bart”);
 ds.setPassword(“51mp50n”);
 …
  • 2、配置文件构建

HikariConfig config = new HikariConfig("/some/path/hikari.properties");
HikariDataSource ds = new HikariDataSource(config);

配置文件中的配置
dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=test
dataSource.password=test
dataSource.databaseName=mydb
dataSource.portNumber=5432
dataSource.serverName=localhost

配置参数

1、dataSourceClassName和jdbcUrl 选一个
但是用jdbcUrl 的时候,可能还需要设置driverClassName ,但是第一步的时候是不需要设置它,先测试可不可以。

  • 2、username
  • 3、password
  • 4、idleTimeout

This property controls the maximum amount of time that a connection is allowed to sit idle in the pool. This setting only applies when minimumIdle is defined to be less than maximumPoolSize
此属性控制允许连接在池中保持空闲状态的最长时间。只有在minimumIdle 定义了,小于maximumPoolSize时才生效,默认10分钟

  • 5、maxLifetime

此属性控制池中连接的最大生存期,(可以理解为在空闲的连接)。使用中的连接永远不会停止,只有关闭连接后,连接才会被移除。这个值强烈建议设置,比数据库的connection time limit 短几秒。默认为30分钟

  • 6、connectionTestQuery

这个值得设定是在“旧版”驱动程序的Connection.isValid() API的情况下。这是将在从池中为您提供连接之前执行的查询,以验证与数据库的连接仍然有效(正确的做法就是再开始时不设置此参数,如果报Connection.isValid()相关的参数在将其设置)如果驱动不兼容,将会报错。 这个设置一般为"SELECT 1"

  • 7、minimumIdle

连接池设定的最小连接数。官方解释为最好不要去设定这个值,为了最好的效率,还是把它当做一个固定大小的连接池。默认值和maximumPoolSize 相同,相当于就是一个拥有maximumPoolSize 一样大的固定连接池。

  • 8、maximumPoolSize

连接池能够达到的最大大小,包括空闲和使用中的连接。
配置最大连接的公式为 默认为10

  • 9、driverClassName

HikariCP将尝试仅通过来通过DriverManager解析驱动程序jdbcUrl,但是对于某些较旧的驱动程序,driverClassName也必须指定。除非获得明显的错误消息指示未找到驱动程序,否则请忽略此属性。

  • 10、connectionTimeout

此属性控制客户端(即您)等待来自池的连接的最大毫秒数。如果超过此时间而没有可用的连接,则会抛出SQLException。可接受的最低连接超时为250 ms。 默认值:30000(30秒)

####连接池大小的配置
连接池并不是越大越好,合理的配置参照官方的这篇文章

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

给出的配置公式为

connections = ((core_count * 2) + effective_spindle_count)
 core_count 为core的数量
 effective_spindle_count 为挂载的磁盘数量

对于有长连接的联接池来说,需要将长连接和短连接分开,初始化2个连接池,然后对于长连接的加一些外部限制,降低并发。

实际项目中遇到的问题

1、报错 Connection is not available, request timed out after 60000ms

报错如下

java.sql.SQLTransientConnectionException: HikariPool-2 - Connection is not available, request timed out after 60000ms.

  • 具体分析:我们的项目是使用sparkJDBC 来实现交互式查询的,所以出现这个问题有以下两个原因
    1、连接在用完没有及时的还到连接池里面
    2、数据量大的数据造成交互慢,我们之前按照公式设置了20个连接,频繁的数据访问造成了数据连接不够,来不及生成。
  • 结论
    代码这块问题不大,对于向这种sparkJDBC交互的场景,严格来说相当于长短连接混合的场景,使用connections = ((core_count * 2) + effective_spindle_count)公司来获取连接边有些牵强。最后,还是调大连接成,有原来20个加大到40个,然后看下反应。