Docker 中的 OOM 与 Spring Boot + H2 + JPA 和批处理
OOM in Docker with Spring Boot + H2 + JPA and Batch Processing
java 应用程序 运行 在 docker 容器中。
rest controller 和另一个微服务接收到的文档临时存储在内部 H2 数据库中(在内存中)。然后在 tika 的帮助下处理这些并发送到下一个微服务。最后在内部数据库中删除文件。
这一切都按预期工作。数据库中的文档大小在处理过程中不断增加和减少(借助 H2 网络控制台进行控制)。
Class 的 Persisted Document 如下所示:
@Entity
@Table(name = "Document")
public class Document {
@Id
@GeneratedValue
Long id = 0L;
@Lob
private String content;
@Lob
private String contentHtml = "";
@ElementCollection
@MapKeyColumn(name = "name")
@Column(length=1000, name = "value")
@CollectionTable(name = "meta_attributes", joinColumns = @JoinColumn(name = "meta_id"))
@LazyCollection(LazyCollectionOption.FALSE)
private Map<String, String> metadata;
@Enumerated(EnumType.STRING)
private DocStatus status;
public Document() {
}
但问题是增加了 docker 容器的内存消耗。我们尝试使用 3 和 6GB 的 MEMORY_MAX。在这两种情况下,内存使用量都会缓慢增加,直到容器以状态 137(已终止)退出。
处理了大约50'000个文件后,表的状态如下:
在 jmap 的帮助下制作的关于容器内 jvm 的转储显示大部分内存被 MVMap (PageReferences) 消耗,这似乎是 H2 用于存储数据的:
我的问题:
这更可能是 H2 内部的一种内存泄漏,还是更可能是配置问题?我尝试的是将使用的 JPARepository 方法从 .save() 更改为 .saveAndFlush(),但没有任何改变。我无法想象这与实体管理器有关,因为它全部由 Spring Boot 管理。
最可能的原因是您没有调用 commit(),这意味着旧版本的数据永远不会被刷新
更新:原因不在 H2 或 JPA 中,而是在错误的 docker-compose 配置中。我们确实为容器内的 JVM 运行 (-Xmx$MEMORY_MAX) 以及 docker 本身 (mem_limit).
分配了相同数量的内存
将 JVM 的 MEMORY_MAX 设置为最大 mem_limit 的 80% 后一切正常。
java 应用程序 运行 在 docker 容器中。
rest controller 和另一个微服务接收到的文档临时存储在内部 H2 数据库中(在内存中)。然后在 tika 的帮助下处理这些并发送到下一个微服务。最后在内部数据库中删除文件。
这一切都按预期工作。数据库中的文档大小在处理过程中不断增加和减少(借助 H2 网络控制台进行控制)。
Class 的 Persisted Document 如下所示:
@Entity
@Table(name = "Document")
public class Document {
@Id
@GeneratedValue
Long id = 0L;
@Lob
private String content;
@Lob
private String contentHtml = "";
@ElementCollection
@MapKeyColumn(name = "name")
@Column(length=1000, name = "value")
@CollectionTable(name = "meta_attributes", joinColumns = @JoinColumn(name = "meta_id"))
@LazyCollection(LazyCollectionOption.FALSE)
private Map<String, String> metadata;
@Enumerated(EnumType.STRING)
private DocStatus status;
public Document() {
}
但问题是增加了 docker 容器的内存消耗。我们尝试使用 3 和 6GB 的 MEMORY_MAX。在这两种情况下,内存使用量都会缓慢增加,直到容器以状态 137(已终止)退出。
处理了大约50'000个文件后,表的状态如下:
在 jmap 的帮助下制作的关于容器内 jvm 的转储显示大部分内存被 MVMap (PageReferences) 消耗,这似乎是 H2 用于存储数据的:
我的问题:
这更可能是 H2 内部的一种内存泄漏,还是更可能是配置问题?我尝试的是将使用的 JPARepository 方法从 .save() 更改为 .saveAndFlush(),但没有任何改变。我无法想象这与实体管理器有关,因为它全部由 Spring Boot 管理。
最可能的原因是您没有调用 commit(),这意味着旧版本的数据永远不会被刷新
更新:原因不在 H2 或 JPA 中,而是在错误的 docker-compose 配置中。我们确实为容器内的 JVM 运行 (-Xmx$MEMORY_MAX) 以及 docker 本身 (mem_limit).
分配了相同数量的内存将 JVM 的 MEMORY_MAX 设置为最大 mem_limit 的 80% 后一切正常。