Как установить тайм-аут getConnection() для c3p0?

Вчера RDS AWS вышел из строя — и наша база данных тоже.

Когда это происходило, C3P0 пытался установить соединение с базой данных и зависал. Я, очевидно, хотел бы, чтобы мое приложение возвращало страницу с ошибкой в ​​​​этих случаях, а не просто ждало ответа вечно.

Вот как выглядит код:

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

Как установить тайм-аут для получения соединения из пула соединений c3p0?

Я думал, что это будет checkoutTimeout(), но это не так. Это «количество миллисекунд, в течение которых клиент, вызывающий getConnection(), будет ожидать подтверждения или получения соединения, когда пул исчерпан». Так как пул не исчерпан (он просто недоступен) это не касается.

Я также думал, что 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" и "зависание socketRead0" - я вижу много проблем, но не вижу реальных решений.

Есть ли способ заставить период ожидания здесь?

Спасибо!


person nostromo    schedule 22.04.2011    source источник


Ответы (2)


Проблема заключается в MySQL ReadAheadInputStream, который использует блокировку чтения. Собственный сокет заблокирован и никогда (?) не возвращает код ошибки. Так что соединение тоже зависает.

Я не вижу способа справиться с этим, кроме как поместить ваш код в поток и присоединиться к нему () с тайм-аутом. Я не верю, хотя проблема оправдывает сложности: надеюсь, Amazon сделает правильные выводы из простоя и не допустит, чтобы это повторилось.

person Vladimir Dyuzhev    schedule 23.04.2011

Ну, вы можете назначить queryTimeout на уровне соединения. IIRC, MySQL подчиняется этому. Не знаю, понравится ли это C3P0, но может сработать.

person MJB    schedule 23.04.2011