繁体   English   中英

Docker 中的 OOM 与 Spring Boot + H2 + JPA 和批处理

[英]OOM in Docker with Spring Boot + H2 + JPA and Batch Processing

Java 应用程序在 docker 容器内运行。

休息控制器和另一个微服务收到的文档暂时存储在内部 H2 数据库中(在内存中)。 然后在 tika 的帮助下处理这些并发送到下一个微服务。 最后文件在内部数据库中被删除。

这一切都按预期工作。 数据库中的文档大小在处理过程中会增加和减少(在 H2 网络控制台的帮助下进行控制)。

持久化文档类如下所示:

@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 容器的内存消耗。 我们尝试使用 3GB 和 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% 后,一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM