java - Cómo resolver el problema de interbloqueo en ColdFusion 9: coldfusion.util.AbstractCache $ Lock
compiler-construction coldfusion-9 (2)
He intentado resolver un problema en el que la ejecución de determinados scripts provoca un punto muerto, colocando todas las solicitudes subsiguientes en el limbo, utilizando un 99,9% de la CPU y, finalmente, bloqueando el servidor.
Aquí hay un ejemplo de seguimiento de pila para una de las solicitudes que se ha puesto en el limbo (esperando eternamente):
Thread Stack Trace
Trace Time: 21:00:44.463 06-Jun-2012
Request ID: 6131
Script Name: http://www.example.com/allreviews.cfm
Started: 21:00:21.225 06-Jun-2012
Exec Time: 23238ms
Memory Used: (24%)230,667KB
Memory Free: 701,428KB
Thread ID: 0x191e (6430)
Thread Name: jrpp-494
Priority: 5
Hashcode: 1081611879
State: WAITING
"jrpp-494" prio=5 in Object.wait()
java.lang.Object.wait(Object.java:???)[Native Method]
- waiting on <0x9253305> (a coldfusion.util.AbstractCache$Lock)
java.lang.Object.wait(Object.java:485)
coldfusion.util.AbstractCache.fetch(AbstractCache.java:46)
coldfusion.util.SoftCache.get_statsOff(SoftCache.java:133)
coldfusion.util.SoftCache.get(SoftCache.java:81)
coldfusion.runtime.TemplateClassLoader.findClass(TemplateClassLoader.java:609)
coldfusion.runtime.RuntimeServiceImpl.getFile(RuntimeServiceImpl.java:785)
coldfusion.runtime.RuntimeServiceImpl.resolveTemplatePath(RuntimeServiceImpl.java:766)
coldfusion.tagext.lang.CustomTag.setName(CustomTag.java:21)
cfApplication2ecfm456206189._factor0(/srv/www/htdocs/www.example.com/www/Application.cfm:28)
cfApplication2ecfm456206189.runPage(/srv/www/htdocs/www.example.com/www/Application.cfm:1)
coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231)
coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416)
coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65)
coldfusion.filter.CfincludeFilter.include(CfincludeFilter.java:33)
coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:279)
coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)
coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
coldfusion.filter.PathFilter.invoke(PathFilter.java:94)
coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)
coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)
coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)
coldfusion.CfmServlet.service(CfmServlet.java:200)
coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doHttpServletRequest(FusionReactorCoreFilter.java:503)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFusionRequest(FusionReactorCoreFilter.java:337)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFilter(FusionReactorCoreFilter.java:246)
com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:121)
jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
jrun.servlet.FilterChain.service(FilterChain.java:101)
jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
Si está interesado, puede ver el seguimiento completo de la pila con lo que llamaré ''la secuencia de comandos de bloqueo'' en la parte superior y todas las demás esperando por ella.
Cuando me encontré con este problema por primera vez, no tenía los rastros de la pila. Publiqué la pregunta, " Cuando ColdFusion está maximizando la CPU, ¿cómo averiguo qué está masticando / sofocando? ". Recibí muchas respuestas útiles y, al observar las trazas de la pila , pude determinar que eran las mismas tres secuencias de comandos las que causaban este problema de interbloqueo una y otra vez.
En cada caso, la línea superior en ''el script de bloqueo'' dice:
coldfusion.compiler.ClassReader.skipFully(ClassReader.java:79)
Y todas las demás solicitudes están obstruidas detrás de ella tienen la siguiente línea en sus respectivos rastreos de pila:
- waiting on <0x9253305> (a coldfusion.util.AbstractCache$Lock)
Una cosa que me molestaba, era por qué no se respetaba el tiempo de espera de mi solicitud ; estos guiones se colgarán para siempre y nunca morirán. WTF, ¿verdad? Así que tuve que hacerlo yo mismo. Entonces, cuando mato a ''la secuencia de comandos de bloqueo'', los demás son liberados del limbo. En ese momento, si están por debajo del tiempo de espera de la solicitud, finalizan el procesamiento, y si ya terminaron (que la mayoría de ellas son en su mayoría), simplemente proceden al tiempo de espera. Pero no van a agotar el tiempo de espera y las solicitudes se acumulan hasta que se usan los hilos activos y la cola de hilos está llena y todo se agota.
Matar manualmente estos cada vez que se solicitan obviamente no es una solución, así que, como mi esposa siempre me recuerda, "depurar, depurar, depurar". <cfabort>
un <cfabort>
condicional que <cfabort>
y descubrí que estaba avanzando a través de Application.cfm, a través de mi header.cfm, y hasta el <cfinclude>
del script problemático. Si coloco el <cfabort>
dentro del script problemático (incluso en la parte superior), no abortaría y se produciría el problema del interbloqueo. Si lo coloco justo antes de incluir, la solicitud abortaría y se evitaría el problema del interbloqueo. Extraño.
No hay código entre estos dos lugares, ¿verdad? Justo antes del include y justo dentro del include debería ser funcionalmente equivalente, ¿no? Probablemente no, porque claramente algo está sucediendo allí.
No estoy usando ninguna etiqueta <cflock>
. El bloqueo que está sucediendo parece estar sucediendo en el nivel de caché de plantilla. Este mismo comportamiento se observa independientemente de si las opciones "Caché de confianza", "Plantilla de caché en solicitud" o "Caché de componentes" están marcadas en admin (en cualquier combinación de marcadas / no marcadas). He borrado el caché de plantillas y el Caché de componente cada una más de una vez. Reinicié el servidor CF una y otra vez ... todo fue en vano.
Durante la solución de problemas, leí este artículo que describe un problema similar con un bloqueo de caché del compilador en CF8 (8.0.1) junto con instrucciones para aplicar un parche para solucionarlo. Pero eso no es CF9 ... así que obviamente no puedo aplicar su parche.
¿Qué hacer? ¿Alguien más ha encontrado este problema? ... ¿Y tienes una solución?
Como solución alternativa, puede intentar deshabilitar completamente el almacenamiento en caché de plantillas estableciendo "Número máximo de plantillas en caché" en 0. No es ideal para la producción ... pero podría ser mejor que colgar.
Resulta que a veces los archivos de clase están dañados y necesitan ser regenerados. Cuando experimente este problema, se manifestará como se describe arriba, con un interbloqueo al intentar cargar el archivo de clase dañado. Los pasos para regenerar los archivos de clase son simples, de la siguiente manera:
Vaya a ColdFusion Administrator> Configuración del servidor> Almacenamiento en caché
Desmarque la siguiente opción:
[] Guardar archivos de clase Cuando selecciona esta opción, los archivos de clase generados por ColdFusion se guardan en el disco para su reutilización después de que el servidor se reinicia. Adobe recomienda esto para los sistemas de producción. Durante el desarrollo, Adobe recomienda que no seleccione esta opción.Haga clic en el botón [Enviar cambios]
Reinicie el servidor ColdFusion
Vaya a ColdFusion Administrator> Configuración del servidor> Almacenamiento en caché
Verifique la siguiente opción:
[x] Guardar archivos de clase Cuando selecciona esta opción, los archivos de clase generados por ColdFusion se guardan en el disco para su reutilización después de que el servidor se reinicia. Adobe recomienda esto para los sistemas de producción. Durante el desarrollo, Adobe recomienda que no seleccione esta opción.Haga clic en el botón [Enviar cambios]
¡Y listo! El problema desaparece por completo, y todo vuelve a ser como debería ser. ;-)
¿Por qué y cómo se corrompen los archivos de clase? No lo sé. Tal vez este podría ser el tema de otra pregunta. Todo lo que sé es que esto resuelve el problema. Por lo general, no estoy seguro de aceptar mis propias respuestas como autoritativas, por lo que si alguien tiene una mejor explicación de este problema y su solución, no dude en publicarlo.