【发布时间】:2017-02-18 14:08:26
【问题描述】:
我多年来一直在与这个问题作斗争,但我终其一生都无法弄清楚问题所在。让我为我们正在使用的堆栈做好准备:
- 基于 Web 的 Java 8 应用程序
- GWT
- 休眠 4.3.11
- MySQL
- MongoDB
- 春天
- Tomcat 8(例如,包括 Tomcat 连接池而不是 C3PO)
- 休眠搜索/Lucene
- 兵马俑和 EhCache
问题是每隔几天(有时每隔一天,有时每隔 10 天一次,它会有所不同)在凌晨,我们的应用程序“锁定”。澄清一下,它不会崩溃,您只是无法登录或为此做任何事情。所有后台任务 - 一切 - 只是停止。如果我们在此状态下尝试登录,我们可以在日志文件中看到它正在将我们验证为有效用户,但从未发送任何响应,因此应用程序只是“旋转”。
迄今为止,我们发现与这些“锁定”发生时间相关的唯一模式是,它发生在我们早上计划的任务或 SAP 导入正在运行时。但是,运行的进程并不总是相同,有时锁定发生在我们的 SAP 导入之一期间,有时在内部计划任务执行期间发生。所有这些事情的共同点是它们在工作时间之外(凌晨 1 点到 6 点之间)运行,并且它们是相当密集的过程。
我们使用 JavaMelody 进行监控,我们每次看到的是,在凌晨 1 点到 6 点的窗口中,从不同时间开始,使用的 jdbc 连接数刚刚开始飙升(根据所附图像)。一旦开始,锁定发生只是时间问题,解决它的唯一方法是反弹 Tomcat 从而重新启动应用程序。
据我所知,内存、CPU 等在发生锁定时都很好,唯一看起来有问题的是使用的 jdbc 连接数量不断增加。
我已经多次检查我们的事务管理代码,以确保事务被正确关闭(事务管理代码非常老式:在 try 块中显式开始和提交,在 catch 块中回滚和实体管理器关闭在 finally 块中)。这一切对我来说似乎都是正确的,所以我真的,真的很难过。除此之外,我最近还明确将Hibernate连接释放模式正确配置为after_transaction,但问题依然存在。
另一个奇怪的事情是,我们为不同的客户端运行同一个应用程序的多个实例,而这个问题只在一个客户端上经常发生。他们是我们的客户,迄今为止要处理的数据最多,尽管所有客户都运行这些计划任务,但这个大客户是唯一一个使用 SAP 导入的客户。这就是为什么我最初认为 SAP 导入是问题所在,但它在今天凌晨 1 点后被锁定,那是导入甚至开始运行之前的几个小时。在这种情况下,它在内部计划任务执行期间被锁定。
有谁知道是什么导致了这种奇怪的行为?我已经研究了我能想到的一切,但无济于事。
【问题讨论】:
-
您说交易正在关闭,但您是在关闭实体管理器吗?您还需要关闭它们才能将连接释放回池。
-
@coladict 我认为这不是真的,因为正如我所提到的,我将连接释放模式设置为事务后,因此据我从文档中了解,它应该在提交/回滚时释放它们.无论如何,这是一个有争议的问题,因为我在我的问题中确实说过我在 finally 块中关闭了实体管理器。
-
嗯,在监控页面的“系统信息”部分中有“打开的 jdbc 连接”链接,可以帮助您找到任何泄漏。如果有任何打开的连接,您将获得有关创建连接的位置的堆栈跟踪,其峰值可能在 Hibernate 中的某个地方,但您只需向下直到到达您的类。
-
@coladict 我看不到该信息的历史记录。当应用程序被锁定时,我无法访问 /monitoring,一旦我将其退回,“实时”数据就消失了,我只能访问图表上显示的历史数据。好吧,至少据我所知,除非您知道在我退回应用程序/Tomcat 后我可以获得您所指数据的方法。
-
尝试使用 jconsole 或 visualvm 或任何其他命令工具(如 jmap 或 jstack)获取线程转储。然后使用线程堆栈分析器分析线程转储(您也可以使用文本编辑器进行分析)并查看谁在持有连接。
标签: java hibernate tomcat jdbc java-melody