【发布时间】:2014-03-12 19:49:44
【问题描述】:
我正在使用 JProfiler 和 JConsole 分析 Grails Web 应用程序,并观察到一个我无法完全理解的现象。
我正在分析的设置如下:
- 使用 maven 作为 WAR 构建并部署到 Tomcat 的 Grails Web 应用程序。
- 单个 Solr 实例
- Tomcat 的线程池大小为 100 个 HTTP 工作线程,BIO 连接器
应用程序几乎为每个请求调用 Solr。没有数据库,也没有其他后端交互。 Ehcache 用于一些缓存。
我创建了一组针对应用程序触发的中等负载测试。我已经为我的本地设置找到了一种负载限制。在此限制之下,我对 Grails 应用程序提出以下意见:
- 响应时间
- HTTP 线程主要花时间处理网络 I/O,有点可运行和等待时间以及非常少的阻塞时间
- CPU 大约 70%
当我将负载提高到超出上述限制时,情况会发生巨大变化:
- 响应时间增加到几秒钟
- HTTP 线程主要处于阻塞或可运行状态,极少净 I/O 和等待时间
- CPU 似乎在 40% 到 80% 之间“跳跃”了很多
现在,虽然在较高的负载下事情变得更慢是完全可以理解的,但我非常担心会发生超过负载限制的锁争用以及大量时间花费在阻塞上的事实。我调查了监控历史,特别是发现了很多类似以下的事件:
- 监控类
org.apache.catalina.loader.WebappClassLoader - 等待和拥有线程是一些 HTTP 工作者
- 阻止监视器所花费的时间很长(定期大约 2 秒)
- 这些事件也发生在负载限制以下,但它们很少见,不会产生如此大的破坏性影响
- 拥有线程和等待线程的堆栈跟踪非常不同,下面是一个示例。
过滤的拥有线程的堆栈跟踪
groovy.lang.GroovyClassLoader.loadClass(java.lang.String)
Script1.$createCallSiteArray()
Script1.$getCallSiteArray()
Script1.__$swapInit()
Script1.<clinit>()
groovy.lang.Script$evaluate.callCurrent(groovy.lang.GroovyObject, java.lang.Object)
gsp_some_gsp_gsp.run()
org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateRenderer.render(...)
Script1.call(java.lang.Object, java.lang.Object[ ])
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(...)
过滤的等待线程的堆栈跟踪:
groovy.lang.Script$evaluate.callCurrent(groovy.lang.GroovyObject, java.lang.Object)
gsp_some_gsp_gsp.run()
org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateRenderer.render(...)
Script1.call(java.lang.Object, java.lang.Object[ ])
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(...)
gsp_some_other_gsp_gsp$_run_closure2_closure5.doCall()
org.codehaus.groovy.grails.web.taglib.GroovyPageTagBody.call()
java_util_concurrent_Callable$call$53.call(java.lang.Object)
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(...)
另一个观察结果(无论加载限制如何)是,加载的类的总数不断增加。 (也有定期的类卸载,所以 PermGen 目前不是问题,但似乎不断生成新的类。)
我的问题是为什么会发生这种对 WebappClassLoader 的阻塞。这是正常行为吗?超过负载限制阻塞线程堆叠的事实只是机器过载的标志吗?这与 Groovy 或 Grails 或 Tomcat 类加载有关吗?有什么可以解决的吗?
有关系统的一些其他详细信息:
java version "1.7.0_51"
OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.12.04.2)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)
Grails version 2.3.4
Groovy version 2.1.9
Ehcache 2.4.6
Tomcat version 7.0.26
Ubuntu 12.04
curl-loader for load tests
【问题讨论】:
标签: java tomcat grails groovy classloader