背景
公司项目用到了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个,然后看下反应。