我们有一个简单的微服务设置,基于 Windows 服务器上的 Spring Boot 和 Java 8。
许多服务的负载都很低,因为它们作为各种外部合作伙伴的集成。所以他们很多时候都是闲着的。
问题是 JVM 仅在触发垃圾收集时才将内存释放回操作系统。因此服务可能开始使用 32mb,然后服务单个请求并分配 2GB 内存。如果该服务上没有其他活动,则不会进行 GC,服务器上的其他服务将受到影响。
使用 System.gc 在外部或内部触发 GC 工作得很好,我已经弄清楚如何使用和-XX:MaxHeapFreeRatio
控制堆何时应该扩展并向操作系统释放内存。-XX:MinHeapFreeRatio
-XX:+UseG1GC
我的问题是:当 JVM 空闲时,确保内存重新回到操作系统的最佳方法是什么?
一个想法是让服务监控自己并在一段空闲时间后触发 System.gc,但这可能很棘手且容易出错。所以希望有更好的建议。
您可以通过运行该程序的 X 个实例来重现。大约 10 个让我的 8GB Windows 机器放弃了。
import java.util.*;
public class Load {
public static void main(String[] args) throws Exception {
alloc();
Scanner s = new Scanner(System.in);
System.out.println("enter to gc ");
s.nextLine();
System.gc();
System.out.println("enter to exit");
s.nextLine();
}
private static void alloc() {
ArrayList<String[]> strings = new ArrayList<>();
int max = 1000000;
for (int i = 0; i < max; i++) {
strings.add(new String[500]);
}
}
}
c:\> java -server -XX:+UseG1GC -Xms32m -Xmx2048m Load
编辑:这被标记为重复两次,但它不是链接问题的重复。第一个问题是同一个问题的 2010 版本,但这个问题是关于为什么 GC 不将内存释放回操作系统(当时不可能)。另一个问题是关于基本 GC 设置的,我已经写过我理解的。我希望讨论如何在系统空闲时触发垃圾收集器。因此,每五秒运行一次 System.gc 是不可接受的,因为那样会与有效请求发生冲突并破坏响应时间的风险很高。