5

我有一个在 Linux Mint 上运行的 Java 应用程序。每一分钟,程序都会显示出非常明显的减速——停顿。停顿是一致的 3 到 4 秒。当我们运行同一程序的更多实例时,它们也会每分钟暂停 3 到 4 秒。每个程序在一分钟的不同秒停止。

最近更新:

在最后一次更新(如下)增加线程池的线程数后,GUI 问题消失了。运行大约 40 小时后,我们观察到 JettyHttpClient 阻塞-GET ( Request.send()) 调用中的线程泄漏。为了解释机制,使用 Executor 类:主线程每隔几分钟运行一次。它使用 Executor 运行一个独立的线程,通过 HTTP GET 命令调用主机,Jetty 的HttpClient.request.send().

HttpClient运行大约 40 小时后,池中运行的线程数出现峰值。所以 40 个小时,相同的线程运行良好。工作假设是大约在那个时候,一个或多个send()调用没有完成或超时并且没有返回到调用线程。本质上,这个/这些线程挂在 Jetty 客户端中。

在查看jVisualMV中的每个常规循环时,我们会看到每个循环的正常行为;一些 HttpClient 线程为主机 GET 启动,在几秒钟内执行并离开。监视器上还有大约 10 个属于 JettyHttpClient线程池的线程,它们已经“存在”了(现在)10 个小时。

预期是在底层客户端或网络处理中存在一些错误。我很惊讶没有超时异常或编程异常。我现在可以问一些明确的问题。

  1. HttpClient里面会发生什么Request.send()
  2. 呼叫返回的超时时间是多少?我认为仍然会有绝对超时或锁定检查等(不是吗?)
  3. I/O 系统能否挂起,让调用者线程挂起——而 Java 乖乖……
    • 在预定时间触发管理器线程,然后
    • 接下来Http.Request.send()发生,
    • 池中的新线程为下一次发送启动(似乎已经发生)。
    • 虽然早期send()陷入困境
  4. 我可以限制或以其他方式清理这些卡住的线程吗?

这发生在我们增加线程池大小之前。发生的事情是,“责备”变得更加集中在问题领域。HttpClient我们也对底层系统持怀疑态度,因为我们在一天中的同一(非特定)时间再次与 Apache 发生了锁定。

提前更新)...

观察到的暂停行为是JavaFX GUI 不更新/刷新;显示器的时钟(textView),setText()呼叫在冻结期间以每秒两次更新的速度记录(这是新信息)。时钟不会更新(在 Mint Linux 上),它在 Windows 上运行时会继续更新。为了防止我重复自己关于 GC、日志、探针等的问题。答案将是相同的;我们已经进行了数周的广泛诊断。这个问题无疑是混合了:Linux JVM / Linux Mint / 线程(每个 JavaFX)。其他新数据是线程池计数增加 +2,似乎消除了冻结——需要进一步测试来确认并调整数字。但问题是“"

我们已经连续几天在 Windows 上运行了该程序的多个实例,没有停顿。当我们在 Mint Linux 平台上运行时,我们会看到冻结,这是非常一致的。

该程序有几个按计划运行的正在运行的线程。一个线程为 http 套接字打开 Internet。当我们注释掉那个区域时,停顿就消失了。但是,我们在使用 Windows 时看不到这种行为。实验指向特定于 Mint 网络 I/O 子系统、linux 调度、Linux Java 8 JVM 或两者之间的某些交互的东西。

正如您可能猜到的那样,我们正在为此撕毁我们的头发。例如,我们关闭了日志记录并且暂停仍然存在。我们恢复了日志记录,只调用了一次 http 服务器,每 60 秒暂停一次,秒数相同。即使我们不进行其他处理,也会发生这种情况。我们尝试了不同的 http 库等。似乎很清楚它是在 JVM 或 Linux 中。

有谁知道解决这个问题的方法?

4

0 回答 0