2011-04-22 11 views
10

Ayer, el RDS de AWS disminuyó, al igual que nuestra base de datos.¿Cómo configurar un getConnection() timeout para c3p0?

Cuando esto ocurría, C3P0 intentaba obtener una conexión a la base de datos y se bloqueaba. Obviamente, me gustaría que mi aplicación devuelva una página de error en estas instancias, en lugar de simplemente esperar una respuesta para siempre.

Aquí es lo que el código es el siguiente:

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

¿Cómo se puede establecer un tiempo de espera para conseguir una conexión de agrupación de conexiones de c3p0?

Pensé que checkoutTimeout() sería, pero no lo es. Es "la cantidad de milisegundos que un cliente que llama a getConnection() esperará que se compruebe o adquiera una conexión cuando se agote el grupo". Como el grupo no está agotado (no está disponible), esto no se aplica.

También pensé que setAcquireRetryAttempts y setAcquireIncrement funcionarían, pero no lo hacen porque una conexión no falla, simplemente no responde.

Cuando me sacó toda la pila, aquí es donde se cala:

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 

Cuando busqué en Google "socketRead0 tiempo de espera" y "socketRead0 cuelgue" - Veo una gran cantidad de problemas, pero no hay soluciones reales.

¿Hay alguna manera de forzar un tiempo de espera aquí?

Gracias!

Respuesta

3

El problema está en ReadAheadInputStream de MySQL, que usa lectura de bloqueo. El socket nativo se bloqueó y nunca (?) Devuelve un código de error. Entonces la conexión también se cuelga.

No veo una forma de manejarlo, salvo colocar el código en un hilo y unirlo() al mismo con tiempo de espera. Aunque no creo que el problema justifique las complicaciones: espero que Amazon saque las conclusiones correctas del tiempo de inactividad y no permita que vuelva a suceder.

1

Bueno, puede asignar un queryTimeout en el nivel de conexión. IIRC, MySQL obedece esto. No sé si a C3P0 le gustará, pero podría funcionar.