Java 10引入了相应的-XX:{Initial|Min|Max}RAMPercentage标志来配置容器环境中的堆。
我在 k8s 集群中运行 Elasticsearch。Elaticsearch容器具有以下资源配置:
resources:
limits:
memory: 512Mi
requests:
memory: 256Mi
Run Code Online (Sandbox Code Playgroud)
问题:如果我设置-XX:MaxRAMPercentage为50%,值是多少?
128Mi:所请求内存的 50%?256Mi: 限制的50%?128Mi-256Mi:实时内存的 50%?喜欢读一些答案后,这个和JEP-346,我已经意识到,G1确实释放内存返回给操作系统。
然而,它是否将内存释放回操作系统,甚至到了当前内存使用量可能低于初始堆内存的程度(即在此 JEP 之前,在我的情况下为 JDK11)?
假设我有一个 Java 11 VM在RAM上运行Xms并Xmx设置为,但是我只消耗大约. G1 会向操作系统释放足够的内存吗?5GB8GB1GB
我没有在任何地方找到任何文件说 G1 仅限于释放Xms记住阈值。
我在生产中观察到这一点,MemAvailable 一直减少到一个点,然后在 GC 之后,它在 8GB 的盒子上跃升至接近 30-35%。所以我假设它正在释放内存,这就是 MemAvailable 跳回的原因。
另外,向操作系统释放内存到底是什么意思,它是调用 free/unmap 吗?
我在一台 32GB 的机器上运行着 23 个 Java 进程。没有进程指定 JVM 内存参数,例如 Xmx。java -XX:+PrintFlagsFinal -version | grep MaxHeapSize报告最大默认堆大小如预期为 8GB。
每个进程都运行嵌入式 Tomcat(Spring Boot 应用程序(大多数版本为 2.3.4)),除了一个是运行三个 WAR 的独立 tomcat 9 实例。这些应用程序的使用率较低(通常是一名用户每天使用 10 分钟)。它们不是内存或 CPU 密集型的。其中之一是 Spring Boot admin,另一个是 Spring Cloud 的 Eureka 服务注册表。对于这两个,我只有一个主要方法来简单地引导 Spring Boot 应用程序。
然而,RES如顶部所示,每个进程的内存都在逐渐增加。例如,Spring Boot 服务注册表在过去 12 小时内从 1.1GB 增加到 1.5GB。所有进程都显示出类似的小幅增长,RES但在同一 12 小时内,总的增长使可用内存减少了 2 GB。过去 12 小时(依此类推)也是如此,直到当前可用内存仅为 4.7GB。
我担心的是,我会继续看到这种趋势(即使没有使用应用程序)。内存永远不会从应用程序中释放,因此可用内存总量持续减少。这是正常的吗,因为也许每个 JVM 都会看到操作系统中的内存仍然可用并且有 8GB 堆空间可供使用?一旦达到操作系统可用内存阈值,JVM 是否会在某个时刻停止占用内存?或者它会一直持续到所有可用内存都被用完为止?
更新
大多数应用程序使用的堆小于 200MB,但堆大小为 1.5 - 2.8GB。堆最大为 8GB。
我有一个在 Kubernetes 集群上运行的 openjdk:8 映像。我添加了内存 HPA(Horizontal Pod Autoscaling),它可以很好地扩展,但由于 JVM 不会将内存从堆释放回操作系统,因此 Pod 不会缩小规模。以下是 hpa.yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: image-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: image-server
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 60
Run Code Online (Sandbox Code Playgroud)
解决此问题的一种方法是使用正确的 GC 并使其释放内存,但由于 JVM 出于性能原因设计为不会频繁地从堆中释放内存,因此这样做并不是一个好主意。Kubernetes 有办法处理这个问题吗?就像不检查操作系统的内存使用情况一样,我们是否可以只检查堆和缩放中的内存使用情况?
java ×3
jvm ×3
kubernetes ×2
g1gc ×1
heap-memory ×1
java-11 ×1
linux ×1
memory ×1
spring-boot ×1