当前位置: 首页 > 面试题库 >

Tomcat中的Java Web应用程序会定期冻结

左丘弘致
2023-03-14
问题内容

我的运行Tomcat(7.0.28)的Java
Web应用程序会定期无响应。我希望对可能的罪魁祸首(同步?)提出一些建议,以及一些建议的工具,以收集有关崩溃期间发生的事情的更多信息。我积累的一些事实:

  • 当Web应用程序冻结时,tomcat继续将请求线程送入应用程序,但该应用程序不会释放它们。线程池已满(目前为250),然后后续请求立即失败。在正常操作期间,活动线程永远不会超过2或3。

  • 发生问题时,不会在我们的任何tomcat或Web应用程序日志中记录任何类型的错误或异常。

  • 通过tomcat管理Web应用程序在我们的应用程序上执行“停止”,然后执行“启动”,将立即解决此问题(直到今天)。

  • 最近的频率是每天两次或三次,尽管今天情况更糟,可能是20次,有时还不立即恢复。

  • 仅在工作时间出现问题

  • 在我们的登台系统上不会发生此问题

  • 发生问题时,服务器上的处理器和内存使用率保持不变(并且相当低)。Tomcat报告大量可用内存。

  • 发生问题时,Tomcat继续保持响应。管理网络应用程序运行良好,tomcat继续向我们的应用程序发送请求,直到池中的所有线程都被填满。

  • 发生问题时,我们的数据库服务器将保持响应状态。我们使用Spring框架进行数据访问和注入。

  • 使用率很高时通常会出现问题,但是使用率绝不会出现异常高的峰值。

  • 问题历史记录:大约一年半以前发生了类似的事情。在许多服务器配置和代码更改之后,该问题消失了直到大约一个月前。在过去的几周内,这种情况发生的频率更高,平均一天2到3次,有时连续几次。

  • 今天,我确定了一些服务器代码,这些代码可能不是线程安全的,为此我进行了修复,但是问题仍然在发生(尽管不那么频繁)。这是非线程安全代码可能导致的那种问题吗?

更新:
有几篇文章建议数据库连接池用尽,我对此进行了一些搜索,然后发现了另一个Stackoverflow问题,该问题几乎可以解释我遇到的所有问题。

显然,Apache的BasicDataSource实现中的maxActive和maxIdle连接的默认值分别为8。而且,maxWait设置为-1,因此当池耗尽且有新的连接请求进入时,它将永远等待,而无需记录任何内容。有点例外。我仍然要等待这个问题再次发生,并在JVM上执行jstack
dump,以便我可以分析该信息,但是看起来这就是问题所在。它唯一无法解释的是为什么应用有时无法从此问题中恢复。我想这些请求有时会堆积起来,一旦它落在后面,就永远无法追上。

更新二: 我在崩溃期间运行了一个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)

在我未经训练的眼睛看来,这是相当确定的。看起来数据库连接池已达到顶峰。我配置了三秒的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。我将监视一会儿,但是我猜这是问题的结尾。


问题答案:

根据经验,您可能需要查看 数据库连接池的
实现。可能是数据库具有足够的容量,但是应用程序中的连接池仅限于少数几个连接。我不记得详细信息,但是我似乎想起有一个类似的问题,这是我改用BoneCP的原因之一,在负载测试下,我发现它非常快速且可靠。

在尝试了下面建议的调试之后,请尝试增加池中可用的连接数,看看是否有影响。

今天,我确定了一些服务器代码,这些代码可能不是线程安全的,为此我进行了修复,但是问题仍然在发生(尽管不那么频繁)。这是非线程安全代码可能导致的那种问题吗?

这取决于您所说的线程安全。在我看来,您的应用程序正在导致线程死锁。您可能希望使用配置为允许调试器连接的JVM运行生产环境,然后使用JVisualVM,JConsole或其他性能分析工具(YourKit是出色的IMO)来窥视所拥有的线程以及它们的线程。在等待。



 类似资料:
  • 问题内容: 运行Tomcat(7.0.28)的Java Web应用程序会定期变得无响应。我希望对可能的罪魁祸首(同步?)提出一些建议,以及一些建议的工具,以收集有关崩溃期间发生的事情的更多信息。我积累的一些事实: 当Web应用程序冻结时,tomcat继续将请求线程送入应用程序,但该应用程序不会释放它们。线程池已满(当前为250),然后后续请求立即失败。在正常操作期间,活动线程永远不会超过2或3。

  • 已安装Java版本(签入控制面板): jre1.6.0,Java更新2, Java更新3, Java更新5, Java更新31 (在C:/Program Files/Java相关文件夹中找到:jre1.6.0、jre1.6.0_02、jre1.6.0_03、jre1.6.0_05、jre6) 根据http://docs.oracle.com/javase/1.5.0/docs/guide/java

  • 我在运行的Tomcat服务器上有一个小型Vaadin/RapidClipse应用程序。作为反向代理,我使用TraefikV1.7.4。如果我直接通过http://159.69.121.213:8080/testtraefik/连接到服务器,一切正常。 http://159.69.121.213:8080/testtraefik/是公共的,您可以直接使用它进行测试。 如果我通过mycob.int.y

  • 还有,我应该什么时候关闭executor服务? 我是新的纺纱线程这种方式,有人能帮助我了解它是如何工作的吗?

  • 我正在开发一个使用Hibernate的简单JSF应用程序。我将所有必需的库导入WEB-INF/lib文件夹,并将它们指向类路径。但是当我尝试编译它时,我遇到了错误: 这是我创建SessionFactory并使用它的代码: 我在这里使用它: 那我做错了什么?我该怎么解决这个问题?

  • 问题内容: Tomcat5.5上部署的Web应用程序的默认会话超时是多少?它是特定于浏览器的吗?在我的Web应用程序中,默认超时没有在代码中或代码中提及。 问题答案: 打开并找到这个 所有Web应用程序都隐式继承自此默认Web描述符。您可以覆盖session-config以及在web.xml中定义的其他设置。 这实际上来自我的Tomcat 7(Windows),但我认为5.5 conf差别不大

  • 部署在Tomcat5.5上的Web应用程序的默认会话超时是多少?它是浏览器特定的吗?在我的Web应用程序中,默认超时在和代码中都没有提到。

  • 问题内容: 问题 :定期更新GUI字段时,SWT冻结。 我想有一个带有文本字段的基于SWT的GUI,其值会定期增加。 最初,我从单独的线程访问textField导致抛出异常: 线程“ Thread-0”中的异常org.eclipse.swt.SWTException:在org.eclipse.swt.SWT.error(SWT.java)的org.eclipse.swt.SWT.error(SWT