lunes, 15 de julio de 2013

Genexus y "No operations allowed after connection closed.Connection was implicitly closed by the driver."


Me he vuelto loco con este error, todavía no tengo muy claro a que se debe pero parece ser que Genexus mantiene la conexion abierta mientras mysql la cerró, al intentar acceder nuevamente la webapp cae.

Sintomas:  En un webpanel cualquiera el cual se mostraba perfectamente, luego de transcurrida cierta cantidad de tiempo , al hacer refresh aparece el error:

Estado HTTP 500 -


type Informe de Excepción
mensaje
descripción El servidor encontró un error interno () que hizo que no pudiera rellenar este requerimiento.
excepción
javax.servlet.ServletException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed by the driver.
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
 at java.lang.reflect.Constructor.newInstance(Unknown Source)
 at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
 at com.mysql.jdbc.Util.getInstance(Util.java:381)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1012)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:986)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
 at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1201)
 at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1188)
 at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4273)
 at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4239)
 at com.genexus.db.driver.GXConnection.prepareStatement(Unknown Source)
 at com.genexus.db.driver.PreparedStatementCache.createStatement(Unknown Source)
 at com.genexus.db.driver.PreparedStatementCache.getStatement(Unknown Source)
 at com.genexus.db.driver.GXConnection.getStatement(Unknown Source)
 at com.genexus.db.driver.GXConnection.getStatement(Unknown Source)
 at com.genexus.db.SentenceProvider.getPreparedStatement(Unknown Source)
 at com.genexus.db.ForEachCursor.preExecute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)

Lo primero que hice fue ver los valores de conexión del mysql, las variables interactive_timeout y wait_timeout
Para ello en el administrador de consultas de mysql ejecutar: Show Variables like '%timeout'

Ambas estaban con el valor 300 , es decir que transcurridos 300 segundos mysql cerraría la conexión.

Visto eso se me ocurrió agregar en el connection string un ?autoreconnect=true para que se vuelva a conectar, pero eso empeoro las cosas ya que quedaba intentando reconectar hasta caer por heap space error, matandome el servidor.

Luego de semanas de idas y venidas la solución aparentemente fue la siguiente:

Setear las propiedades del datastore Recycle type y Recycle time asi:
El valor 3 de recycle time corresponde a un valor menor al seteado en wait_timout de mysql, hay que tener en cuenta que uno va expresado en minutos y el otro en segundos.




2 comentarios:

Pablin dijo...

Marcos, muy buena la info, tuve el mismo problema con esa excepción. El mysql está en un hosting compartido por lo que no tengo demasiada administración.

Una consulta, el valor de interactive_timeout tiene importancia en la solución? por ejemplo que también deba ser mayor (en segundos) al parámetro Recycle Time de GX ? Porque ahora el mysql tiene interactive en 25seg y wait_timeout en 700seg.

configuré GX para Recycle Time de 8 minutos (menor a 700s pero mayor a 25s del interactive). Con esto no da más la expeción pero al tiempo se cae el server completo.

Ahora pedí que pusiera el interactive_timeout también en 700s o en algún valor mayor a 60 para poder configurar en minutos Recycle Time.

Cualquier info viene bárbaro,
Muchas gracias

Marcos dijo...

Hola Pablo,

interactive_timeout es a nivel de mysql, y por lo que recuerdo ( hace tiempo de esto ) dejé los valores por default.

Si bien la solución que publiqué mejoro notoriamente el sitio, también ha pasado que tiene algunas caidas cada tanto.

El tema de hostings compartidos es lo que tiene.

Otra opción que manejé es hacer que el pool de conexiones lo maneje el propio tomcat y no genexus, no era dificil, consistía en agregar unas líneas en los archivos xml de configuracion de tomcat. Capaz podes vichar por ese lado.

Saludos.