这几天遇到一个奇怪的问题,使用H2自带的连接池,经常出现从连接池是获取连接不成功,程序阻塞的情况。代码很简单,官方网站上对连接池的使用也语焉不详。
JdbcConnectionPool pool = JdbcConnectionPool.create(url, username, password); pool.setLoginTimeout(Integer.parseInt(100000));// 建立连接超时时间 pool.setMaxConnections(Integer.parseInt(100));// 建立连接最大个数 Connection conn = pool.getConnection();
没有办法,看了看源码,发现获取连接时,如果没有可用连接,就差不多是一个死循环。
public Connection getConnection() throws SQLException { long max = System.currentTimeMillis() + timeout * 1000; do { synchronized (this) { if (activeConnections < maxConnections) { return getConnectionNow(); } try { wait(1000); } catch (InterruptedException e) { // ignore } } } while (System.currentTimeMillis() <= max); throw new SQLException("Login timeout", "08001", 8001); }
看代码,建立连接超时时间的单位应该是秒,我按毫秒设的,结果造成程序的阻塞。阻塞的原因找到了,但连接池中连接数量过多也是一个问题,理论上应该不会过多。
想了想,H2的连接池似乎没有设置连接的最大存活时间,如果程序编写有问题,导致经常出现连接没有正常关闭,可能会导致很多无效的连接一直存活,当占满连接池的时候,就会无法获取有效的连接。
以上为我的猜测,不确定是否正确。
决定不再使用H2自带的连接池,改用原来一直使用的Proxool连接池。观察一段时间,再看能否解决问题。
另:java的连接池技术好像好多年都没有什么发展了,有些奇怪,难道连接池技术已经发展完备了,没有再发展的余地了吗?可能是这样。