简体   繁体   中英

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

The java application is running inside a docker container.

Documents received by rest controller and from another microservice are temporarly stored in internal H2 database (in memory). These are then processed with help of tika and sent to next microservice. At the end documents are deleted in internal database.

This all works as intended. Document size in database is increasing and decreasing during processing (controlled with help of H2 web-console).

Class of Persisted Document looks as follow:

@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() {
}

But problem is increasing memory consumption of docker container. We tried with a MEMORY_MAX of 3 and 6GB. In both cases, memory usage slowly increased until container exited with Status 137 (Killed).

After processing of about 50'000 files, state of tables is as follows:

在此处输入图片说明

A dump of regarding jvm inside container made with help of jmap shows that most memory is consumed by MVMap (PageReferences) which seems to be used from H2 for storing data:

在此处输入图片说明

在此处输入图片说明

My questions:

Is this more likely to be a kind of memory leak inside H2 or is it more likely to be a configuration thing? What I tried was to change used JPARepository method from .save() to .saveAndFlush() whicht did not change anything. I cannot imagine that this has something to do with Entity Manager as this is all managed by Spring Boot.

最可能的原因是您没有调用 commit(),这意味着旧版本的数据永远不会被刷新

Update: Cause was not in H2 or JPA but in a bad docker-compose configuration. We did allocate same amount of memory for JVM running inside container (-Xmx$MEMORY_MAX) as well as for docker itself (mem_limit).

After setting MEMORY_MAX for JVM to a maximum of 80% of mem_limit everything worked fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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