如何为c3p0设置getConnection()超时时间?

11

昨天AWS的RDS崩溃了,我们的数据库也随之宕机。

当发生这种情况时,C3P0会尝试获取数据库连接并挂起。我希望在这些情况下,我的应用程序能够返回一个错误页面,而不是永远等待响应。

以下是代码示例:

ComboPooledDataSource db = new ComboPooledDataSource();
...
Connection conn = db.getConnection();

如何为从c3p0连接池获取连接设置超时时间?

我原以为checkoutTimeout()方法就是用来设置超时时间的,但实际上它并不是。该方法是“客户端在连接池耗尽时调用getConnection()将等待一个Connection被检入或获取的毫秒数。”由于连接池没有耗尽(只是不可用),因此该方法不适用。

我还以为setAcquireRetryAttempts和setAcquireIncrement会起作用,但它们并不会,因为连接并没有失败,而只是没有响应。

当我查看整个堆栈时,程序停滞在这里:

SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int) line: not available [native method]    
SocketInputStream.read(byte[], int, int) line: 129  
ReadAheadInputStream.fill(int) line: 113    
ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(byte[], int, int) line: 160    
ReadAheadInputStream.read(byte[], int, int) line: 188   
MysqlIO.readFully(InputStream, byte[], int, int) line: 2428 
MysqlIO.reuseAndReadPacket(Buffer, int) line: 2882  
MysqlIO.reuseAndReadPacket(Buffer) line: 2871   
MysqlIO.checkErrorPacket(int) line: 3414    
MysqlIO.sendCommand(int, String, Buffer, boolean, String) line: 1936    
MysqlIO.sqlQueryDirect(StatementImpl, String, String, Buffer, int, int, int, boolean, String, Field[]) line: 2060   
JDBC4Connection(ConnectionImpl).execSQL(StatementImpl, String, int, Buffer, int, int, boolean, String, Field[], boolean) line: 2542 
JDBC4PreparedStatement(PreparedStatement).executeInternal(int, Buffer, boolean, boolean, Field[], boolean) line: 1734   
JDBC4PreparedStatement(PreparedStatement).executeQuery() line: 1885 
NewProxyPreparedStatement.executeQuery() line: 76   
C3P0PooledConnectionPoolManager.initializeAutomaticTestTable(String, DbAuth) line: 799  
C3P0PooledConnectionPoolManager.createPooledConnectionPool(DbAuth) line: 696    
C3P0PooledConnectionPoolManager.getPool(DbAuth) line: 257   
C3P0PooledConnectionPoolManager.getPool() line: 271 
ComboPooledDataSource(AbstractPoolBackedDataSource).getNumThreadsAwaitingCheckoutDefaultUser() line: 203    
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
Method.invoke(Object, Object...) line: 597  
BeansUtils.extractAccessiblePropertiesToMap(Map, Object, Collection) line: 359  
BeansUtils.appendPropNamesAndValues(StringBuffer, Object, Collection) line: 324 
ComboPooledDataSource.toString() line: 539  
ComboPooledDataSource(AbstractPoolBackedDataSource).getPoolManager() line: 462  
ComboPooledDataSource(AbstractPoolBackedDataSource).getConnection() line: 128   

当我在谷歌上搜索“socketRead0 timeout”和“socketRead0 hang”时,我看到了很多问题,但没有真正的解决方案。

有没有办法在这里强制设置超时时间?

2个回答

3
问题出在MySQL的ReadAheadInputStream中,它使用阻塞读取。本地套接字被阻塞,永远不会返回错误代码。所以连接也会挂起。
我没有看到任何处理方法,除非将您的代码放入一个线程中,并使用超时join()。然而,我不认为这个问题值得这样做:我希望亚马逊能从停机时间中得出正确的结论,并且不会让它再次发生。

1

嗯,你可以在连接级别上分配一个queryTimeout。如果我没记错的话,MySQL会遵守这个设置。不知道C3P0是否支持,但这可能有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接