我有一个 Spring Boot 应用程序,它在 Cloud Foundry 上崩溃,没有明显的崩溃日志。该应用程序有 3 个实例,这三个实例中的任何一个有时一天崩溃两次,有时两天崩溃一次。没有定义的崩溃模式。
我尝试添加以下 java 参数,结果如上所述: -XX:ErrorFile :错误时未创建文件 -XX:+HeapDumpOnOutOfMemoryError :实例崩溃时创建堆转储。
实例崩溃时会创建堆转储,但没有 OOM 日志。
我还尝试为 Spring Boot 应用程序添加嵌入式 tomcat 日志,并添加了以下软件包: org.apache.tomcat、org.apache.catalina、org.apache.coyote。尝试在 docker 本地创建 OOM,并且可以看到 OOM 日志出现在应用程序的 tomcat 日志中。
澄清一下,问题是如何找到哪个内存组件导致了 OOM?
最佳答案
当您在 Cloud Foundry 上运行 Java 应用程序时,使用 -XX:+HeapDumpOnOutOfMemoryError
不会有帮助的。添加该选项将触发堆转储,但它将写入您的应用程序容器内。一旦完成,容器就会消失,您将无法获取写入的文件。
为了在 Cloud Foundry 上实现此功能,Java 构建包提供了一些帮助。
Java buildpack configures a killagent被添加到 JVM 中。当出现 OutOfMemoryError 时,该代理将执行。它将打印内存使用情况的直方图,并且还将打印内存摘要。您将在
cf logs
的输出中看到这些.例如:
Resource exhaustion event: the JVM was unable to allocate memory from the heap. ResourceExhausted! (1/0) | Instance Count | Total Bytes | Class Name | | 18273 | 313157136 | [B | | 47806 | 7648568 | [C | | 14635 | 1287880 | Ljava/lang/reflect/Method; | | 46590 | 1118160 | Ljava/lang/String; | | 8413 | 938504 | Ljava/lang/Class; | | 28573 | 914336 | Ljava/util/concurrent/ConcurrentHashMap$Node; |
和
Memory usage: Heap memory: init 65011712, used 332392888, committed 351797248, max 351797248 Non-heap memory: init 2555904, used 63098592, committed 64815104, max 377790464 Memory pool usage: Code Cache: init 2555904, used 14702208, committed 15007744, max 251658240 PS Eden Space: init 16252928, used 84934656, committed 84934656, max 84934656 PS Survivor Space: init 2621440, used 0, committed 19398656, max 19398656 Compressed Class Space: init 0, used 5249512, committed 5505024, max 19214336 Metaspace: init 0, used 43150616, committed 44302336, max 106917888 PS Old Gen: init 43515904, used 247459792, committed 247463936, max 247463936
所有 Java 应用程序在使用 Cloud Foundry 上的 Java buildpack 运行时都会获得此信息,这有助于了解应用程序崩溃时的内存使用情况。如果您没有看到此内容,则您的应用因其他原因崩溃(见下文)。
如果您需要更深入地了解内存使用情况,您可以获得完整的堆转储。为此,您需要将持久存储绑定(bind)到您的应用程序。如果您将卷服务绑定(bind)到您的应用程序,其中服务名称包含
heap-dump
,然后 Java buildpack 将设置此存储以自动用于捕获堆转储。If a Volume Service with the string heap-dump in its name or tag is bound to the application, terminal heap dumps will be written with the pattern
<CONTAINER_DIR>/<SPACE_NAME>-<SPACE_ID[0,8]>/<APPLICATION_NAME>-<APPLICATION_ID[0,8]>/<INSTANCE_INDEX>-<TIMESTAMP>-<INSTANCE_ID[0,8]>.hprof
如果您没有看到 JVM Killagent 的输出,或者没有看到持久存储中生成的堆转储:
- 检查 JVM 代理是否已添加。当构建包在暂存期间运行时,您应该会看到 Killagent 被下载并安装。
- 它还应该显示在 Java 构建包生成的启动命令中。检查启动命令以确保您看到代理。请注意,如果您使用
cf push -c
指定您自己的启动命令,则构建包将无法添加代理。 。 - 您只是没有遇到 OutOfMemoryError。您的应用程序可能因其他原因崩溃。最常见的情况是超出了容器的内存限制,而不是 JVM 的内存限制。在这种情况下,容器将立即崩溃,并且您将无法从 Killagent 获得输出。
希望有帮助!
关于java - Spring Boot 应用程序在 Cloud Foundry 上崩溃,没有任何崩溃日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58125487/