tomcat 中的 Java Web 应用程序定期冻结
Posted
技术标签:
【中文标题】tomcat 中的 Java Web 应用程序定期冻结【英文标题】:Java web app in tomcat periodically freezes up 【发布时间】:2012-07-11 13:40:13 【问题描述】:我运行 Tomcat (7.0.28) 的 Java Web 应用程序周期性地变得无响应。我希望对可能的罪魁祸首(同步?)提出一些建议,以及一些推荐的工具,以收集有关崩溃期间发生的情况的更多信息。我积累的一些事实:
当 Web 应用程序冻结时,tomcat 继续向应用程序提供请求线程,但应用程序不会释放它们。线程池填满到最大值(当前为 250),然后后续请求立即失败。在正常操作期间,活动线程永远不会超过 2 或 3 个。
出现问题时,我们的任何 tomcat 或 Web 应用程序日志中均未记录任何类型的错误或异常。
通过 tomcat 管理 Web 应用在我们的应用程序上执行“停止”然后“启动”可以立即解决此问题(直到今天)。
最近频率是一天两到三次,今天更糟,大概是 20 次,有时不会立即恢复。
问题仅在工作时间出现
我们的暂存系统没有出现该问题
当问题发生时,服务器上的处理器和内存使用率保持不变(并且相当低)。 Tomcat 报告有大量可用内存。
当问题发生时,Tomcat 会继续响应。管理 web 应用运行良好,tomcat 继续向我们的应用发送请求,直到池中的所有线程都被填满。
当问题发生时,我们的数据库服务器保持响应。我们使用 Spring 框架进行数据访问和注入。
问题通常出现在使用率很高的情况下,但使用率从来不会出现异常高的峰值。
问题历史:大约一年半前发生了类似的事情。经过多次服务器配置和代码更改,问题直到大约一个月前才消失。在过去的几周内,它的发生频率要高得多,平均每天 2 或 3 次,有时连续数次。
我今天发现了一些可能不是线程安全的服务器代码,我对此进行了修复,但问题仍然存在(尽管频率较低)。这是非线程安全代码可能导致的问题吗?
更新: 有几篇帖子暗示数据库连接池耗尽,我朝那个方向做了一些搜索,发现了另一个*** question,它解释了我遇到的几乎所有问题。
显然,在 Apache 的 BasicDataSource 实现中,maxActive 和 maxIdle 连接的默认值都是 8。另外,maxWait 设置为 -1,所以当连接池用完并且有新的连接请求进来时,它将永远等待不记录任何异常。我仍将等待此问题再次发生并在 JVM 上执行 jstack 转储,以便我可以分析该信息,但看起来这就是问题所在。它唯一没有解释的是为什么应用程序有时无法从这个问题中恢复。我想请求有时会堆积起来,一旦落后就永远赶不上。
更新二:我在崩溃期间运行了一个 jstack,发现了以下大约 250 个(最大线程):
"http-nio-443-exec-294" daemon prio=10 tid=0x00002aaabd4ed800 nid=0x5a5d in Object.wait() [0x00000000579e2000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118)
- locked <0x0000000743116b30> (a org.apache.commons.pool.impl.GenericObjectPool$Latch)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:718)
在我未经训练的眼睛看来,这看起来相当确凿。看起来数据库连接池已达到上限。我配置了 3 秒的 maxWait,而没有修改 maxActive 和 maxIdle,只是为了确保当池填满时我们开始看到记录的异常。然后我会将这些值设置为适当的值并进行监控。
更新 III: 配置 maxWait 后,我开始在我的日志中看到这些,正如预期的那样:
org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
我已将 maxActive 设置为 -1(无限),将 maxIdle 设置为 10。我会监视一段时间,但我的猜测是问题到此为止。
【问题讨论】:
kill -3 <pid>
是你的朋友。运行它并查看线程转储。您可能想查看 Thread Dump Analyzer 以进行信息分组 (java.net/projects/tda)。
没有任何其他信息的猜测(需要线程转储!):数据库连接池耗尽。
这正是发生在我身上的事情,web 应用程序变得太大,最大连接数太低,等待时间未定义,线程时不时地堆积起来,服务器会冻结。增加最大缺点并设置最大等待的特定时间,现在我只是在监视,但服务器运行良好。感谢这个迷你教程。
【参考方案1】:
根据经验,您可能希望查看您的数据库连接池实现。可能是您的数据库有足够的容量,但您的应用程序中的连接池仅限于少量连接。我不记得细节了,但我似乎记得有一个类似的问题,这是我改用 BoneCP 的原因之一,我发现它在负载测试下非常快速和可靠。
尝试以下建议的调试后,尝试增加池中可用的连接数,看看是否有任何影响。
我今天发现了一些可能不是线程安全的服务器代码, 我对此进行了修复,但问题仍然存在 (虽然不太频繁)。这是这样的问题吗 非线程安全的代码会导致什么?
这取决于您所说的线程安全是什么意思。在我看来,您的应用程序正在导致线程deadlock。您可能希望使用配置为允许调试器连接的 JVM 运行您的生产环境,然后使用 JVisualVM、JConsole 或其他分析工具(YourKit 是优秀的 IMO)来查看您拥有哪些线程,以及它们是什么'正在等待。
【讨论】:
是的,BoneCP 摇滚。 commons-dbcp 很烂。 Tomcat 7 附带一个 dbcp tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html 但要使用它,驱动程序必须可以从与 tomcat-jdbc.jar 相同的类加载器访问新的 tomcat。 Redsonic:这不是真的。如果您的DataSource
是在上下文中定义的,而不是作为在上下文之间共享的JNDI 资源,那么它可以在上下文的类路径中(即在.war 中)。这就是我在生产系统中使用它的方式。
啊好的。我没有测试自己。我报告了tomcat 7 doc中的内容。好吧,在这种情况下,它也是一个选项:)以上是关于tomcat 中的 Java Web 应用程序定期冻结的主要内容,如果未能解决你的问题,请参考以下文章